diff --git a/doc/Eqs/HADRESS_AT_pair_coul_dsf.jpg b/doc/Eqs/HADRESS_AT_pair_coul_dsf.jpg
new file mode 100644
index 000000000..2edcc1fc5
Binary files /dev/null and b/doc/Eqs/HADRESS_AT_pair_coul_dsf.jpg differ
diff --git a/doc/Eqs/HADRESS_AT_pair_coul_dsf.tex b/doc/Eqs/HADRESS_AT_pair_coul_dsf.tex
new file mode 100644
index 000000000..e97481cff
--- /dev/null
+++ b/doc/Eqs/HADRESS_AT_pair_coul_dsf.tex
@@ -0,0 +1,10 @@
+\documentclass[12pt]{article}
+
+\begin{document}
+$$
+  V^{AT} = 
+  q_iq_j \left[ \frac{\mbox{erfc} (\alpha r)}{r} -  \frac{\mbox{erfc} (\alpha r_c)}{r_c} + 
+  \left( \frac{\mbox{erfc} (\alpha r_c)}{r_c^2} +  \frac{2\alpha}{\sqrt{\pi}}\frac{\exp (-\alpha^2    r^2_c)}{r_c} \right)(r-r_c) \right] \qquad r < r_c 
+$$
+
+\end{document}
diff --git a/doc/Eqs/HADRESS_AT_pair_lj.png b/doc/Eqs/HADRESS_AT_pair_lj.png
new file mode 100644
index 000000000..2f2e73591
Binary files /dev/null and b/doc/Eqs/HADRESS_AT_pair_lj.png differ
diff --git a/doc/Eqs/HADRESS_AT_pair_lj.tex b/doc/Eqs/HADRESS_AT_pair_lj.tex
new file mode 100644
index 000000000..6e28b198b
--- /dev/null
+++ b/doc/Eqs/HADRESS_AT_pair_lj.tex
@@ -0,0 +1,11 @@
+\documentstyle[12pt]{article}
+
+\begin{document}
+
+$$
+ V^{AT} = 4 \epsilon \left[ \left(\frac{\sigma}{r}\right)^{12} - 
+                       \left(\frac{\sigma}{r}\right)^6 \right]
+                       \qquad r < r_c
+$$
+
+\end{document}
diff --git a/doc/Eqs/HADRESS_CG_pair_lj.png b/doc/Eqs/HADRESS_CG_pair_lj.png
new file mode 100644
index 000000000..518845994
Binary files /dev/null and b/doc/Eqs/HADRESS_CG_pair_lj.png differ
diff --git a/doc/Eqs/HADRESS_CG_pair_lj.tex b/doc/Eqs/HADRESS_CG_pair_lj.tex
new file mode 100644
index 000000000..86194536f
--- /dev/null
+++ b/doc/Eqs/HADRESS_CG_pair_lj.tex
@@ -0,0 +1,11 @@
+\documentstyle[12pt]{article}
+
+\begin{document}
+
+$$
+ V^{CG} = 4 \epsilon \left[ \left(\frac{\sigma}{r}\right)^{12} - 
+                       \left(\frac{\sigma}{r}\right)^6 \right]
+                       \qquad r < r_c
+$$
+
+\end{document}
diff --git a/doc/Eqs/HADRESS_Switching_Function_Cylinder.tex b/doc/Eqs/HADRESS_Switching_Function_Cylinder.tex
new file mode 100644
index 000000000..bd6b156c0
--- /dev/null
+++ b/doc/Eqs/HADRESS_Switching_Function_Cylinder.tex
@@ -0,0 +1,15 @@
+\documentclass[12pt]{article}
+
+\begin{document}
+
+\begin{eqnarray*}
+\lambda(r)=\left\{
+\begin{array}{ll}
+1 & r \leq r_{at}\\
+\cos^2\left(\frac{\pi(r-r_{at})}{2r_{hy}}\right) & r_{at}< r \leq r_{at}+r_{hy}\\
+0 & r > r_{at}+r_{hy}
+\end{array}
+\right.
+\end{eqnarray*}
+
+\end{document}
\ No newline at end of file
diff --git a/doc/Eqs/HADRESS_Switching_Function_Slab.png b/doc/Eqs/HADRESS_Switching_Function_Slab.png
new file mode 100644
index 000000000..c50bcb458
Binary files /dev/null and b/doc/Eqs/HADRESS_Switching_Function_Slab.png differ
diff --git a/doc/Eqs/HADRESS_Switching_Function_Slab.tex b/doc/Eqs/HADRESS_Switching_Function_Slab.tex
new file mode 100644
index 000000000..878bb4da8
--- /dev/null
+++ b/doc/Eqs/HADRESS_Switching_Function_Slab.tex
@@ -0,0 +1,13 @@
+\documentclass[12pt]{article}
+
+\begin{document}
+$$
+\lambda(x)=\left\{
+\begin{array}{ll}
+1 & |x| \leq L_{AT}/2\\
+\cos^2\left(\frac{\pi(x-L_{AT}/2)}{2L_{HY}}\right) & \frac{L_{AT}}{2}< |x| \leq \frac{L_{AT}}{2}+L_{HY}\\
+0 & |x| > L_{AT}+L_{HY}
+\end{array}
+\right.
+$$
+\end{document}
\ No newline at end of file
diff --git a/doc/Eqs/HADRESS_Switching_Function_Sphere.png b/doc/Eqs/HADRESS_Switching_Function_Sphere.png
new file mode 100644
index 000000000..6a16b9838
Binary files /dev/null and b/doc/Eqs/HADRESS_Switching_Function_Sphere.png differ
diff --git a/doc/Eqs/HADRESS_Switching_Function_Sphere.tex b/doc/Eqs/HADRESS_Switching_Function_Sphere.tex
new file mode 100644
index 000000000..bd6b156c0
--- /dev/null
+++ b/doc/Eqs/HADRESS_Switching_Function_Sphere.tex
@@ -0,0 +1,15 @@
+\documentclass[12pt]{article}
+
+\begin{document}
+
+\begin{eqnarray*}
+\lambda(r)=\left\{
+\begin{array}{ll}
+1 & r \leq r_{at}\\
+\cos^2\left(\frac{\pi(r-r_{at})}{2r_{hy}}\right) & r_{at}< r \leq r_{at}+r_{hy}\\
+0 & r > r_{at}+r_{hy}
+\end{array}
+\right.
+\end{eqnarray*}
+
+\end{document}
\ No newline at end of file
diff --git a/doc/Eqs/HADRESS_System_Hamiltonian.png b/doc/Eqs/HADRESS_System_Hamiltonian.png
new file mode 100644
index 000000000..2e76b4819
Binary files /dev/null and b/doc/Eqs/HADRESS_System_Hamiltonian.png differ
diff --git a/doc/Eqs/HADRESS_System_Hamiltonian.tex b/doc/Eqs/HADRESS_System_Hamiltonian.tex
new file mode 100644
index 000000000..34239bc52
--- /dev/null
+++ b/doc/Eqs/HADRESS_System_Hamiltonian.tex
@@ -0,0 +1,9 @@
+\documentclass[12pt]{article}
+
+\begin{document}
+
+\begin{eqnarray}\label{hadress_H}
+&&H = K + V^{int} + \sum_{\alpha} \left\{{\lambda_\alpha} {V^{AT}_\alpha} + {(1 - \lambda_\alpha)} {V^{CG}_\alpha} \right\}\\ \nonumber
+\end{eqnarray}
+
+\end{document}
\ No newline at end of file
diff --git a/doc/Eqs/HADRESS_System_Potentials.png b/doc/Eqs/HADRESS_System_Potentials.png
new file mode 100644
index 000000000..8cfcfe612
Binary files /dev/null and b/doc/Eqs/HADRESS_System_Potentials.png differ
diff --git a/doc/Eqs/HADRESS_System_Potentials.tex b/doc/Eqs/HADRESS_System_Potentials.tex
new file mode 100644
index 000000000..821df897a
--- /dev/null
+++ b/doc/Eqs/HADRESS_System_Potentials.tex
@@ -0,0 +1,10 @@
+\documentclass[12pt]{article}
+
+\begin{document}
+
+\begin{eqnarray}\label{hadress_V}
+&& V^{AT}_\alpha \equiv \displaystyle\frac{1}{2}\sum_{\beta,\beta\neq \alpha}^{N} \sum_{ij} V^{AT}(|\textbf{r}_{\alpha i} - \textbf{r}_{\beta j}|)\\ \nonumber
+&& V^{CG}_\alpha \equiv \displaystyle\frac{1}{2}\sum_{\beta,\beta\neq \alpha}^{N} V^{CG}(|\textbf{R}_\alpha - \textbf{R}_\beta|)
+\end{eqnarray}
+
+\end{document}
\ No newline at end of file
diff --git a/doc/JPG/HADRESS_MODEL_LAMMPS.png b/doc/JPG/HADRESS_MODEL_LAMMPS.png
new file mode 100644
index 000000000..5626fef66
Binary files /dev/null and b/doc/JPG/HADRESS_MODEL_LAMMPS.png differ
diff --git a/doc/fix_lambdah_calc.html b/doc/fix_lambdah_calc.html
new file mode 100644
index 000000000..269af18ff
--- /dev/null
+++ b/doc/fix_lambdah_calc.html
@@ -0,0 +1,244 @@
+<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 lambdah command 
+</H3>
+<P><B>Syntax:</B>
+</P>
+<PRE>fix ID group-ID lambdah/calc N<sub>H-mol</sub> L<sub>HY</sub> L<sub>AT</sub> P<sub>flag</sub> &#948;&#955; dT<sub>p</sub> T<sub>p</sub><sup>Start</sup> T<sub>p</sub><sup>End</sup> HY<sub>Shape</sub> D<sub>flag</sub> &Delta;x dT<sub>d</sub> T<sub>d</sub><sup>Start</sup> T<sub>d</sub><sup>End</sup> &#963; R &#961;<sub>0</sub> c file<sub>flag</sub> 
+</PRE>
+<UL><LI>ID is documented in <A HREF = "fix.html">fix</A> command 
+
+<LI>group-ID has to be all 
+
+<LI>lambdaH/calc = style name of this fix command 
+
+<LI>N<sub>H-mol</sub> = Number of molecular types within the low resolution 
+
+<LI>L<sub>HY</sub> = Length of Hybrid region 
+
+<LI>L<sub>AT</sub> = Length of Atomistic (high resolution) region 
+
+<LI>P<sub>flag</sub> = <I>0</I> or <I>1</I> 
+
+<PRE>  <I>0</I> Constant-pressure route is off
+  <I>1</I> Constant-pressure route is on 
+</PRE>
+<LI>&#948;&#955; = Bin size in constant-pressure route 
+
+<LI>dT<sub>p</sub> = Time step interval of constant-pressure route 
+
+<LI>T<sub>p</sub><sup>Start</sup> = Starting time step of constant-pressure route 
+
+<LI>T<sub>p</sub><sup>End</sup> = Ending time step of constant-pressure route 
+
+<LI>HY<sub>Shape</sub> = Shape of Hybrid region : <I>slab</I>, <I>sphere</I>, <I>cylinder</I> 
+
+<PRE>  <I>slab</I> is for rectangular hybrid region
+  <I>sphere</I> is for spherical hybrid region
+  <I>cylinder</I> is for cylinderical hybrid region 
+</PRE>
+<LI>D<sub>flag</sub> = <I>0</I> or <I>1</I> 
+
+<PRE>  <I>0</I> Constant-density route is off 
+  <I>1</I> Constant-density route is on 
+</PRE>
+<LI>&Delta;x = Bin size in constant-density route (length unit) 
+
+<LI>dT<sub>d</sub> = Time step interval of constant-density route 
+
+<LI>T<sub>d</sub><sup>Start</sup> = Starting time step of constant-density route 
+
+<LI>T<sub>d</sub><sup>End</sup> = Ending time step of constant-density route 
+
+<LI>&#963; = Width of gaussian function in constant-density route (length unit) 
+
+<LI>R = Range of gaussian function in constant-density route (length unit) 
+
+<LI>&#961;<sub>0</sub> = Reference number density in constant-density route 
+
+<LI>c = Prefactor in constant-density route (energy unit) 
+
+<LI>file<sub>flag</sub> = <I>0</I> or <I>1</I> 
+
+<PRE>  <I>0</I> Do not employ density-balancing file 
+  <I>1</I> Employ density-balancing file 
+</PRE>
+
+</UL>
+<P><B>Examples:</B>
+</P>
+<PRE>fix 1 all lambdah/calc 1 25 60 1 0.02 1000 150000 300000 slab 1 1.5 500 400000 700000 6 2 0.1 2 0
+fix 1 all lambdah/calc 1 25 60 1 0.02 1000 100000 200000 sphere 1 1.5 500 300000 700000 6 2 0.1 2 0 
+</PRE>
+<P><B>Description:</B>
+</P>
+<P>The Hamiltonian adaptive resolution simulation scheme (H-AdResS) is a dual-resolution simulation method that
+joins models with different levels of complexity for the same system within a global Hamiltonian framework <A HREF = "#Potestio2013_1">(Potestio2013_1)</A>, <A HREF = "#Potestio2013_2">(Potestio2013_2)</A>, <A HREF = "#Heidari2016">(Heidari2016)</A>.
+</P>
+<P>Depending on the shape of the Hybrid region which might be either slab, sphere or cynlinder, this fix calculates 
+the resolution of every atom based on the center of mass of its molecule.
+The following switching function is defined for a simulation box whose atomistic region is limited to [-0.5L<sub>AT</sub> 0.5L<sub>AT</sub>]:
+</P>
+<CENTER><IMG SRC = "Eqs/HADRESS_Switching_Function_Slab.png">
+</CENTER>
+<P>The following switching function is defined for a spherical/cylinderical atomistic region located at the middle of the simulation box:
+</P>
+<CENTER><IMG SRC = "Eqs/HADRESS_Switching_Function_Sphere.png">
+</CENTER>
+<P>A setup of a Hamiltonian Adaptive Resolution Simulation is shown below. The box is partitioned into three
+ different region types, namely: Coarse-grained (CG), Hybrid (HY), and Atomistic (AT). In each region,
+ the resolution of each molecule (here water) is determined by the instantaneous value of the
+ smooth function &#955; represented above the simulation snapshot.
+</P>
+<CENTER><IMG SRC = "JPG/HADRESS_MODEL_LAMMPS.png">
+</CENTER>
+<P><I>N<sub>H-mol</sub></I> determines the number of molecular types within the low resolution. For instance, for a system containing 
+coarse-grained water molecules in the coarse-grained region, this number equals one. However, for a sytem containing 
+water molecules and ions such as Na and Cl and they interact differently in the coarse-grained region, 
+this number is 3.
+</P>
+<P>The <I>L<sub>HY</sub></I> specifies the length of the Hybrid region. For the cases of cylinderical or spherical hybrid regions, this quantity denotes <I>r<sub>HY</sub></I>.
+</P>
+<P>The <I>L<sub>AT</sub></I> determines the length of Atomistic region. For the cases of cylinderical or spherical hybrid regions, this quantity denotes <I>r<sub>AT</sub></I>.
+</P>
+<P>The <I>P<sub>flag</sub></I> switches off and on the constant-pressure route.
+</P>
+<P>The <I>&#948;&#955;</I> denotes the bin size over the hybrid region. In the on-the-fly method of averaging the drift forces, 
+particles are sorted into uniformly spaced &#955; bins of <I>&#948;&#955;</I> side.
+</P>
+<P>The <I>dT<sub>p</sub></I> denotes the time intervals in constant-pressure route at which the averaged drift forces are applied on the molecules of the hybrid region.
+</P>
+<P>The <I>T<sub>p</sub><sup>Start</sup></I> denotes the time step at which the simulation of the constant-pressure route is started.
+</P>
+<P>The <I>T<sub>p</sub><sup>End</sup></I> specifies the ending time step of the constant-pressure route.
+</P>
+<P>The <I>HY<sub>Shape</sub></I> specifies the geometry of the Hybrid region. This could be <I>slab</I>, <I>sphere</I>, <I>cylinder</I>.
+</P>
+<P><I>D<sub>flag</sub></I> switches off and on the constant-pressure route.
+</P>
+<P><I>&Delta;x</I> is the bin size by which the simulation box is descritized in the constant-density route.
+</P>
+<P><I>dT<sub>d</sub></I> is the time interval in constant-density route at which the averaged thermodynamic forces are applied.
+</P>
+<P><I>T<sub>d</sub><sup>Start</sup></I> is the starting time step of constant-density route.
+</P>
+<P><I>T<sub>d</sub><sup>End</sup></I> is the ending time step of constant-density route.
+</P>
+<P><I>&#963;</I> is the width of Gaussian function in the constant-density route.
+</P>
+<P><I>R</I> is the range of Gaussian function in the constant-density route.
+</P>
+<P><I>&#961;<sub>0</sub></I> is the reference density in the constant-density route.
+</P>
+<P><I>c</I> is the prefactor in the constant-density route.
+</P>
+<P><I>file<sub>flag</sub></I> denotes a flag whether the file containing the density-balancing force is employed or not.
+</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>. 
+</P>
+<P>This fix creates a file named "Mean_Comp_Density.txt" in which the compensation forces are printed. 
+This file is created at <I>T<sub>d</sub><sup>Start</sup></I> and is updated every <I>dT<sub>d</sub></I>. 
+The updating process of the file is finished at time step <I>T<sub>d</sub><sup>End</sup></I>. 
+For those equillibrated simulations starting at time step larger than <I>T<sub>d</sub><sup>End</sup></I>, 
+the file "Mean_Comp_Density.txt" is loaded in this fix.
+</P>
+<HR>
+
+<P><B>Restrictions:</B>
+</P>
+<P>This fix calculates the center of mass of the particles. Thus at the beginning of the calculation,
+it is required that all atoms belonging to a molecule are on the same side of the box.
+</P>
+<P>To employ the H-AdResS scheme, the full/hars atom style has to be used:
+</P>
+<PRE>  atom_style      full/hars 
+</PRE>
+<P>To perform HAdResS, Data File should contain the following extra information with respect to the Data File defined in full atom style:
+</P>
+<P>[1] <B>mol_H</B> determines the number of molecular types in the low resolution (coarse-grained) region.
+</P>
+<P>[2] <B>representative_flag</B> determines which atom carries the molecule's information 
+(center of mass, molecule's resolution, ...) in the low resolution (coarse-grained) region.
+</P>
+<P>[3] <B>mol_type</B> denotes the type of the molecule in the low resolution (coarse-grained) region.
+</P>
+<P>The following example is extracted from a Data File in which the simulation box contains water molecules and the ions of sodium and cholorine:
+</P>
+<PRE>30720 atoms
+20480 bonds
+10240 angles 
+</PRE>
+<PRE>4 atom types
+<B>1 mol_H types</B>
+1 bond types
+1 angle types 
+</PRE>
+<PRE>-99.968000 99.968000 xlo xhi
+-20.793600 20.793600 ylo yhi
+-20.793600 20.793600 zlo zhi 
+</PRE>
+<PRE>Masses 
+</PRE>
+<PRE>1 15.999400
+2 1.007940
+3 22.9898 
+4 35.453 
+</PRE>
+<PRE>Atoms
+#atomID molecule-tag atom-type q <B>representative_flag mol_type</B> x y z
+1 1 1 -0.847200 1 1 -99.654503 -19.897600 -20.192101
+2 1 2 0.423600 0 1 -100.568001 -19.999300 -20.586599
+3 1 2 0.423600 0 1 -99.777702 -20.103100 -19.221300
+4 2 1 -0.847200 1 1 -97.826401 -17.709900 -20.127100
+5 2 2 0.423600 0 1 -96.938400 -18.071301 -19.842800
+6 2 2 0.423600 0 1 -97.735100 -16.718800 -20.030100
+7 3 3 1.0 1 1 -97.429398 -20.402201 -17.494900
+8 3 4 -1.0 1 1 -96.834000 -19.671400 -17.160999
+.
+.
+. 
+</PRE>
+<P>As it is shown, the representative_flag of the oxygen atoms is equal 1, and
+since the soldium and cholorine are single atom ions, their representative_flags are also equals 1.
+The interactions of water molecules and ions are the same in the coarse-grained region,
+thus they all carry the same molecular type (mol_type).
+</P>
+<HR>
+
+<P><B>Related commands:</B>
+</P>
+<P><A HREF = "pair_lj_hars.html">pair_lj_hars.html</A>
+</P>
+<P><B>Default:</B> none
+</P>
+<HR>
+
+<A NAME = "Potestio2013_1"></A>
+
+<P><B>(Potestio2013_1)</B> R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, <I>Hamiltonian Adaptive Resolution Simulation for Molecular Liquids</I>, <A HREF = "http://dx.doi.org/10.1103/PhysRevLett.110.108301">Phys. Rev. Lett. [110],
+108301 (2013)</A>
+</P>
+<A NAME = "Potestio2013_2"></A>
+
+<P><B>(Potestio2013_2)</B> R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, <I>Monte Carlo Adaptive Resolution Simulation of Multicomponent Molecular Liquids</I>, <A HREF = "http://dx.doi.org/10.1103/PhysRevLett.111.060601">Phys. Rev. Lett. [111],
+060601 (2013)</A>
+</P>
+<A NAME = "Heidari2016"></A>
+
+<P><B>(Heidari2016)</B> M. Heidari, R. Cortes-Huerto, D. Donadio and R. Potestio, <I>Accurate and general treatment of electrostatic interaction in Hamiltonian adaptive resolution simulations</I>, "EPJST (2016)"
+</P>
+</HTML>
diff --git a/doc/fix_lambdah_calc.txt b/doc/fix_lambdah_calc.txt
new file mode 100644
index 000000000..178f727d1
--- /dev/null
+++ b/doc/fix_lambdah_calc.txt
@@ -0,0 +1,212 @@
+"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 lambdah command :h3
+
+[Syntax:]
+
+fix ID group-ID lambdah/calc N<sub>H-mol</sub> L<sub>HY</sub> L<sub>AT</sub> P<sub>flag</sub> &#948;&#955; dT<sub>p</sub> T<sub>p</sub><sup>Start</sup> T<sub>p</sub><sup>End</sup> HY<sub>Shape</sub> D<sub>flag</sub> &Delta;x dT<sub>d</sub> T<sub>d</sub><sup>Start</sup> T<sub>d</sub><sup>End</sup> &#963; R &#961;<sub>0</sub> c file<sub>flag</sub> :pre
+
+ID is documented in "fix"_fix.html command :ulb,l
+group-ID has to be all :l
+lambdaH/calc = style name of this fix command :l
+N<sub>H-mol</sub> = Number of molecular types within the low resolution :l
+L<sub>HY</sub> = Length of Hybrid region :l
+L<sub>AT</sub> = Length of Atomistic (high resolution) region :l
+P<sub>flag</sub> = {0} or {1} :l
+  {0} Constant-pressure route is off
+  {1} Constant-pressure route is on :pre
+&#948;&#955; = Bin size in constant-pressure route :l
+dT<sub>p</sub> = Time step interval of constant-pressure route :l
+T<sub>p</sub><sup>Start</sup> = Starting time step of constant-pressure route :l
+T<sub>p</sub><sup>End</sup> = Ending time step of constant-pressure route :l
+HY<sub>Shape</sub> = Shape of Hybrid region : {slab}, {sphere}, {cylinder} :l
+  {slab} is for rectangular hybrid region
+  {sphere} is for spherical hybrid region
+  {cylinder} is for cylinderical hybrid region :pre
+D<sub>flag</sub> = {0} or {1} :l
+  {0} Constant-density route is off 
+  {1} Constant-density route is on :pre
+&Delta;x = Bin size in constant-density route (length unit) :l
+dT<sub>d</sub> = Time step interval of constant-density route :l
+T<sub>d</sub><sup>Start</sup> = Starting time step of constant-density route :l
+T<sub>d</sub><sup>End</sup> = Ending time step of constant-density route :l
+&#963; = Width of gaussian function in constant-density route (length unit) :l
+R = Range of gaussian function in constant-density route (length unit) :l
+&#961;<sub>0</sub> = Reference number density in constant-density route :l
+c = Prefactor in constant-density route (energy unit) :l
+file<sub>flag</sub> = {0} or {1} :l
+  {0} Do not employ density-balancing file 
+  {1} Employ density-balancing file :pre
+
+:ule  
+
+[Examples:]
+
+fix 1 all lambdah/calc 1 25 60 1 0.02 1000 150000 300000 slab 1 1.5 500 400000 700000 6 2 0.1 2 0
+fix 1 all lambdah/calc 1 25 60 1 0.02 1000 100000 200000 sphere 1 1.5 500 300000 700000 6 2 0.1 2 0 :pre
+
+[Description:]
+
+The Hamiltonian adaptive resolution simulation scheme (H-AdResS) is a dual-resolution simulation method that
+joins models with different levels of complexity for the same system within a global Hamiltonian framework "(Potestio2013_1)"_#Potestio2013_1, "(Potestio2013_2)"_#Potestio2013_2, "(Heidari2016)"_#Heidari2016.
+
+Depending on the shape of the Hybrid region which might be either slab, sphere or cynlinder, this fix calculates 
+the resolution of every atom based on the center of mass of its molecule.
+The following switching function is defined for a simulation box whose atomistic region is limited to \[-0.5L<sub>AT</sub> 0.5L<sub>AT</sub>\]:
+
+:c,image(Eqs/HADRESS_Switching_Function_Slab.png)
+
+The following switching function is defined for a spherical/cylinderical atomistic region located at the middle of the simulation box:
+
+:c,image(Eqs/HADRESS_Switching_Function_Sphere.png)
+
+A setup of a Hamiltonian Adaptive Resolution Simulation is shown below. The box is partitioned into three
+ different region types, namely: Coarse-grained (CG), Hybrid (HY), and Atomistic (AT). In each region,
+ the resolution of each molecule (here water) is determined by the instantaneous value of the
+ smooth function &#955; represented above the simulation snapshot.
+ 
+:c,image(JPG/HADRESS_MODEL_LAMMPS.png)
+
+{N<sub>H-mol</sub>} determines the number of molecular types within the low resolution. For instance, for a system containing 
+coarse-grained water molecules in the coarse-grained region, this number equals one. However, for a sytem containing 
+water molecules and ions such as Na and Cl and they interact differently in the coarse-grained region, 
+this number is 3.
+
+The {L<sub>HY</sub>} specifies the length of the Hybrid region. For the cases of cylinderical or spherical hybrid regions, this quantity denotes {r<sub>HY</sub>}.
+
+The {L<sub>AT</sub>} determines the length of Atomistic region. For the cases of cylinderical or spherical hybrid regions, this quantity denotes {r<sub>AT</sub>}.
+
+The {P<sub>flag</sub>} switches off and on the constant-pressure route.
+
+The {&#948;&#955;} denotes the bin size over the hybrid region. In the on-the-fly method of averaging the drift forces, 
+particles are sorted into uniformly spaced &#955; bins of {&#948;&#955;} side.
+
+The {dT<sub>p</sub>} denotes the time intervals in constant-pressure route at which the averaged drift forces are applied on the molecules of the hybrid region.
+
+The {T<sub>p</sub><sup>Start</sup>} denotes the time step at which the simulation of the constant-pressure route is started.
+
+The {T<sub>p</sub><sup>End</sup>} specifies the ending time step of the constant-pressure route.
+
+The {HY<sub>Shape</sub>} specifies the geometry of the Hybrid region. This could be {slab}, {sphere}, {cylinder}.
+
+{D<sub>flag</sub>} switches off and on the constant-pressure route.
+
+{&Delta;x} is the bin size by which the simulation box is descritized in the constant-density route.
+
+{dT<sub>d</sub>} is the time interval in constant-density route at which the averaged thermodynamic forces are applied.
+
+{T<sub>d</sub><sup>Start</sup>} is the starting time step of constant-density route.
+
+{T<sub>d</sub><sup>End</sup>} is the ending time step of constant-density route.
+
+{&#963;} is the width of Gaussian function in the constant-density route.
+
+{R} is the range of Gaussian function in the constant-density route.
+
+{&#961;<sub>0</sub>} is the reference density in the constant-density route.
+
+{c} is the prefactor in the constant-density route.
+
+{file<sub>flag</sub>} denotes a flag whether the file containing the density-balancing force is employed or not.
+
+:line
+
+[Restart, fix_modify, output, run start/stop, minimize info:]
+
+No information about this fix is written to "binary restart
+files"_restart.html. 
+
+This fix creates a file named "Mean_Comp_Density.txt" in which the compensation forces are printed. 
+This file is created at {T<sub>d</sub><sup>Start</sup>} and is updated every {dT<sub>d</sub>}. 
+The updating process of the file is finished at time step {T<sub>d</sub><sup>End</sup>}. 
+For those equillibrated simulations starting at time step larger than {T<sub>d</sub><sup>End</sup>}, 
+the file "Mean_Comp_Density.txt" is loaded in this fix.
+
+:line
+
+[Restrictions:]
+
+This fix calculates the center of mass of the particles. Thus at the beginning of the calculation,
+it is required that all atoms belonging to a molecule are on the same side of the box.
+
+To employ the H-AdResS scheme, the full/hars atom style has to be used:
+
+  atom_style      full/hars :pre
+
+To perform HAdResS, Data File should contain the following extra information with respect to the Data File defined in full atom style:
+
+\[1\] [mol_H] determines the number of molecular types in the low resolution (coarse-grained) region.
+
+\[2\] [representative_flag] determines which atom carries the molecule's information 
+(center of mass, molecule's resolution, ...) in the low resolution (coarse-grained) region.
+
+\[3\] [mol_type] denotes the type of the molecule in the low resolution (coarse-grained) region.
+
+The following example is extracted from a Data File in which the simulation box contains water molecules and the ions of sodium and cholorine:
+
+30720 atoms
+20480 bonds
+10240 angles :pre
+
+4 atom types
+[1 mol_H types]
+1 bond types
+1 angle types :pre
+
+-99.968000 99.968000 xlo xhi
+-20.793600 20.793600 ylo yhi
+-20.793600 20.793600 zlo zhi :pre
+
+Masses :pre
+
+1 15.999400
+2 1.007940
+3 22.9898 
+4 35.453 :pre
+
+Atoms
+#atomID molecule-tag atom-type q [representative_flag mol_type] x y z
+1 1 1 -0.847200 1 1 -99.654503 -19.897600 -20.192101
+2 1 2 0.423600 0 1 -100.568001 -19.999300 -20.586599
+3 1 2 0.423600 0 1 -99.777702 -20.103100 -19.221300
+4 2 1 -0.847200 1 1 -97.826401 -17.709900 -20.127100
+5 2 2 0.423600 0 1 -96.938400 -18.071301 -19.842800
+6 2 2 0.423600 0 1 -97.735100 -16.718800 -20.030100
+7 3 3 1.0 1 1 -97.429398 -20.402201 -17.494900
+8 3 4 -1.0 1 1 -96.834000 -19.671400 -17.160999
+.
+.
+. :pre
+
+As it is shown, the representative_flag of the oxygen atoms is equal 1, and
+since the soldium and cholorine are single atom ions, their representative_flags are also equals 1.
+The interactions of water molecules and ions are the same in the coarse-grained region,
+thus they all carry the same molecular type (mol_type).
+
+:line
+
+[Related commands:]
+
+"pair_lj_hars.html"_pair_lj_hars.html
+
+[Default:] none
+
+:line
+
+
+:link(Potestio2013_1)
+[(Potestio2013_1)] R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, {Hamiltonian Adaptive Resolution Simulation for Molecular Liquids}, "Phys. Rev. Lett. \[110\],
+108301 (2013)"_http://dx.doi.org/10.1103/PhysRevLett.110.108301
+
+:link(Potestio2013_2)
+[(Potestio2013_2)] R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, {Monte Carlo Adaptive Resolution Simulation of Multicomponent Molecular Liquids}, "Phys. Rev. Lett. \[111\],
+060601 (2013)"_http://dx.doi.org/10.1103/PhysRevLett.111.060601
+
+:link(Heidari2016)
+[(Heidari2016)] M. Heidari, R. Cortes-Huerto, D. Donadio and R. Potestio, {Accurate and general treatment of electrostatic interaction in Hamiltonian adaptive resolution simulations}, "EPJST (2016)"
diff --git a/doc/pair_lj_hars.html b/doc/pair_lj_hars.html
new file mode 100644
index 000000000..50596c9d3
--- /dev/null
+++ b/doc/pair_lj_hars.html
@@ -0,0 +1,198 @@
+<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>pair_style lj/cut/hars/at command 
+</H3>
+<H3>pair_style lj/cut/coul/dsf/hars/at command 
+</H3>
+<H3>pair_style lj/cut/hars/cg command 
+</H3>
+<P><B>Syntax:</B>
+</P>
+<PRE>pair_style style args 
+</PRE>
+<LI>style = 
+
+<PRE>	<I>lj/cut/hars/at</I> or
+	<I>lj/cut/coul/dsf/hars/at</I> or
+	<I>lj/cut/hars/cg</I> 
+</PRE>
+<LI>args = list of arguments for a particular style 
+
+<PRE>  <I>lj/cut/hars/at</I> args = cutoff All_AT Flag_Load_File
+    cutoff = global cutoff for Lennard Jones interactions (distance units)
+    All_AT = Fully atomic simulation flag, = <I>0</I> or <I>1</I>
+      <I>0</I> Fully atomic simulation is off and HAdResS is on
+      <I>1</I> Fully atomic simulation is on and HAdResS is off 
+    Flag_Load_File = Flag of employing compensation energy file, = <I>0</I> or <I>1</I>
+      <I>0</I> Do not employ compensation energy until T<sub>p</sub><sup>Start</sup>
+      <I>1</I> Employ compensation energy file immediately 
+</PRE>
+<PRE>  <I>lj/cut/coul/dsf/hars/at</I> args = Alpha LJcutoff Coulcutoff All_AT Flag_Load_File
+    Alpha = Damping coefficient in DSF potential (1.0/distance units)
+    LJcutoff = global cutoff for Lennard Jones interactions (distance units)
+    Coulcutoff = global cutoff for DSF coulombic interactions (distance units)
+    All_AT = Fully atomic simulation flag, = <I>0</I> or <I>1</I>
+      <I>0</I> Fully atomic simulation is off and HAdResS is on
+      <I>1</I> Fully atomic simulation is on and HAdResS is off 
+    Flag_Load_File = Flag of employing compensation energy file, = <I>0</I> or <I>1</I>
+      <I>0</I> Do not employ compensation energy until T<sub>p</sub><sup>Start</sup>
+      <I>1</I> Employ compensation energy file immediately 
+</PRE>
+<PRE>  <I>lj/cut/hars/cg</I> args = cutoff All_CG Flag_Load_File
+    cutoff = global cutoff for Lennard Jones interactions (distance units)
+    All_CG = Fully coarse-grained simulation flag, = <I>0</I> or <I>1</I>
+      <I>0</I> Fully coarse-grained simulation is off and HAdResS is on
+      <I>1</I> Fully coarse-grained simulation is on and HAdResS is off
+    Flag_Load_File = Flag of employing compensation energy file, = <I>0</I> or <I>1</I>
+      <I>0</I> Do not employ compensation energy until T<sub>p</sub><sup>Start</sup>
+      <I>1</I> Employ compensation energy file immediately 
+</PRE>
+<P><B>Examples:</B>
+</P>
+<PRE>pair_style      hybrid/overlay lj/cut/hars/cg 2.469416506 0 0 lj/cut/hars/at 0.2 10.0 12.0 0 0
+pair_style      hybrid/overlay lj/cut/hars/cg 1.1224 1 0 lj/cut/hars/at 1.5 1 0 
+</PRE>
+<P><B>Description:</B>
+</P>
+<P>In the H-AdResS scheme, the description of the interactions within a system of particles is given in terms
+of a global Hamiltonian function H, which has the following form <A HREF = "#Potestio2013_1">(Potestio2013_1)</A>, <A HREF = "#Potestio2013_2">(Potestio2013_2)</A>, <A HREF = "#Heidari2016">(Heidari2016)</A>:
+</P>
+<CENTER><IMG SRC = "Eqs/HADRESS_System_Hamiltonian.png">
+</CENTER>
+<P>The term K is the atomistic kinetic energy, and V<sup>int</sup> consists of all the intramolecular bonded interactions (e.g. bond stretching). 
+The value of the switching function is determined by the sizes L<sub>AT</sub>
+L<sub>HY</sub> of the atomistic and hybrid regions, respectively, and of the specific geometry of the atomistic region. 
+</P>
+<P>In the Hamiltonian, the non-bonded potential energy contribution of each molecule is given by a weighted sum of two terms
+V<sub>&#945;</sub><sup>CG</sup> and V<sub>&#945;</sub><sup>AT</sup>, defined as:
+</P>
+<CENTER><IMG SRC = "Eqs/HADRESS_System_Potentials.png">
+</CENTER>
+<P>The <I>lj/cut/hars/at</I> styles compute the standard 12/6 Lennard-Jones potential for the atoms located in atomistic (high resolution) and hybrid region. 
+The general formula is given by
+</P>
+<CENTER><IMG SRC = "Eqs/HADRESS_AT_pair_lj.png">
+</CENTER>
+<P>rc is the cutoff.
+</P>
+<P>Style <I>lj/cut/coul/dsf/hars/at</I> computes the standard 12/6 Lennard-Jones and Coulomb interactions for atoms of atomistic (high resolution) and hybrid region. 
+The Coulombic term is computed via the damped shifted force model introduced by <A HREF = "#Fennell">Fennell et al.</A>, given by:
+</P>
+<CENTER><IMG SRC = "Eqs/HADRESS_AT_pair_coul_dsf.jpg">
+</CENTER>
+<P>where <I>alpha</I> is the damping parameter and erfc() is the complementary
+error-function. This potential is essentially a short-range,
+spherically-truncated, charge-neutralized, shifted, pairwise <I>1/r</I>
+summation.
+</P>
+<P>The <I>lj/cut/hars/cg</I> styles compute the standard 12/6 Lennard-Jones potential for the atoms located in the low resolution (coarse-grained) and hybrid region. 
+The general formula is given by
+</P>
+<CENTER><IMG SRC = "Eqs/HADRESS_CG_pair_lj.png">
+</CENTER>
+<P>rc is the cutoff.
+As mentioned above, the interactions in the coarse-grained region are computed based on the center of mass of the particles.
+</P>
+<P>Important Note: For dual resolution simulations, it is required to use hybrid/overlay to include 
+both resolution pair-styles. 
+</P>
+<P>For all of dual resolution pair styles, the following coefficients must
+be defined for each pair of atoms types via the
+<A HREF = "pair_coeff.html">pair_coeff</A> command as in the examples below
+</P>
+<LI>epsilon (energy units) 
+
+<LI>sigma (distance units) 
+
+<LI>cutoff (distance units) 
+
+<P>For examples:
+</P>
+<PRE>  pair_coeff      * * lj/cut/hars/cg 1.0 2.2
+  pair_coeff      1 1 lj/cut/coul/dsf/hars/at 0.15535 3.166
+  pair_coeff      * 2 lj/cut/coul/dsf/hars/at 0.0000 0.0000 
+</PRE>
+<P>Note that sigma is defined in the LJ formula as the zero-crossing
+distance for the potential, not as the energy minimum at 2^(1/6)
+sigma. 
+</P>
+<P>All potentials have to be shifted at the cutoff through the command
+</P>
+<PRE>  pair_modify     shift yes 
+</PRE>
+<HR>
+
+<P><B>Mixing, shift, table, tail correction, restart, rRESPA info</B>:
+</P>
+<P>All of the <I>lj/cut</I> pair styles support the
+<A HREF = "pair_modify.html">pair_modify</A> shift option for the energy of the
+Lennard-Jones portion of the pair interaction.
+</P>
+<P>All of the <I>lj/cut</I> pair styles write their information to <A HREF = "restart.html">binary
+restart files</A>, so pair_style and pair_coeff commands do
+not need to be specified in an input script that reads a restart file.
+</P>
+<P>The pair styles do not support the use of the rRESPA hierarchy.
+</P>
+<P>Each pair styles creates a file named as "Mean_Comp_Energy_XX.txt", where the file name's suffix "XX", is replaced by "AT" and "CG" for atomistic and coarse-grained pairwise interactions respectively. 
+In these files the averaged compensation energy as function of the resolution (&#955;) is printed. Each file is created at <I>T<sub>p</sub><sup>Start</sup></I> and is updated every <I>dT<sub>p</sub></I>. 
+The updating process of the files is finished at time step <I>T<sub>p</sub><sup>End</sup></I>. 
+For those equilibrated simulations starting at time step larger than <I>T<sub>p</sub><sup>End</sup></I>, the file "Mean_Comp_Energy_XX.txt" is loaded in each pair styles. For more information, 
+see <A HREF = "fix_lambdah_calc.html">fix_lambdah_calc</A>.
+</P>
+<HR>
+
+<P><B>Restrictions:</B>
+</P>
+<P>In HAdResS, it is required to include both high resolution (atomistic) 
+and low resolution (coarse-grained) force fields together through 
+</P>
+<PRE>  pair_style      hybrid/overlay 
+</PRE>
+<P>An example of such setup is given above.
+</P>
+<P>To employ the H-AdResS scheme, the full/hars atom style as well as <A HREF = "fix_lambdah_calc.html">(fix_lambdah_calc)</A> have to be used:
+</P>
+<PRE>  atom_style      full/hars 
+</PRE>
+<PRE>  fix             ID group-ID lambdah/calc ... 
+</PRE>
+<HR>
+
+<P><B>Related commands:</B>
+</P>
+<P><A HREF = "fix_lambdah_calc.html">fix_lambdah_calc</A>, <A HREF = "pair_coeff.html">pair_coeff</A>
+</P>
+<P><B>Default:</B> none
+</P>
+<HR>
+
+<A NAME = "Potestio2013_1"></A>
+
+<P><B>(Potestio2013_1)</B> R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, <I>Hamiltonian Adaptive Resolution Simulation for Molecular Liquids</I>, <A HREF = "http://dx.doi.org/10.1103/PhysRevLett.110.108301">Phys. Rev. Lett. [110],
+108301 (2013)</A>
+</P>
+<A NAME = "Potestio2013_2"></A>
+
+<P><B>(Potestio2013_2)</B> R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, <I>Monte Carlo Adaptive Resolution Simulation of Multicomponent Molecular Liquids</I>, <A HREF = "http://dx.doi.org/10.1103/PhysRevLett.111.060601">Phys. Rev. Lett. [111],
+060601 (2013)</A>
+</P>
+<A NAME = "Heidari2016"></A>
+
+<P><B>(Heidari2016)</B> M. Heidari, R. Cortes-Huerto, D. Donadio and R. Potestio, <I>Accurate and general treatment of electrostatic interaction in Hamiltonian adaptive resolution simulations</I>, "EPJST (2016)"
+</P>
+<A NAME = "Fennell"></A>
+
+<P><B>(Fennell)</B> C. J. Fennell, J. D. Gezelter, J Chem Phys, 124, 
+234104 (2006).
+</P>
+</HTML>
diff --git a/doc/pair_lj_hars.txt b/doc/pair_lj_hars.txt
new file mode 100644
index 000000000..7813f40aa
--- /dev/null
+++ b/doc/pair_lj_hars.txt
@@ -0,0 +1,181 @@
+"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
+
+pair_style lj/cut/hars/at command :h3
+pair_style lj/cut/coul/dsf/hars/at command :h3
+pair_style lj/cut/hars/cg command :h3
+
+[Syntax:]
+
+pair_style style args :pre
+
+style = :l
+	{lj/cut/hars/at} or
+	{lj/cut/coul/dsf/hars/at} or
+	{lj/cut/hars/cg} :pre
+args = list of arguments for a particular style :l
+  {lj/cut/hars/at} args = cutoff All_AT Flag_Load_File
+    cutoff = global cutoff for Lennard Jones interactions (distance units)
+    All_AT = Fully atomic simulation flag, = {0} or {1}
+      {0} Fully atomic simulation is off and HAdResS is on
+      {1} Fully atomic simulation is on and HAdResS is off 
+    Flag_Load_File = Flag of employing compensation energy file, = {0} or {1}
+      {0} Do not employ compensation energy until T<sub>p</sub><sup>Start</sup>
+      {1} Employ compensation energy file immediately :pre
+  {lj/cut/coul/dsf/hars/at} args = Alpha LJcutoff Coulcutoff All_AT Flag_Load_File
+    Alpha = Damping coefficient in DSF potential (1.0/distance units)
+    LJcutoff = global cutoff for Lennard Jones interactions (distance units)
+    Coulcutoff = global cutoff for DSF coulombic interactions (distance units)
+    All_AT = Fully atomic simulation flag, = {0} or {1}
+      {0} Fully atomic simulation is off and HAdResS is on
+      {1} Fully atomic simulation is on and HAdResS is off 
+    Flag_Load_File = Flag of employing compensation energy file, = {0} or {1}
+      {0} Do not employ compensation energy until T<sub>p</sub><sup>Start</sup>
+      {1} Employ compensation energy file immediately :pre
+  {lj/cut/hars/cg} args = cutoff All_CG Flag_Load_File
+    cutoff = global cutoff for Lennard Jones interactions (distance units)
+    All_CG = Fully coarse-grained simulation flag, = {0} or {1}
+      {0} Fully coarse-grained simulation is off and HAdResS is on
+      {1} Fully coarse-grained simulation is on and HAdResS is off
+    Flag_Load_File = Flag of employing compensation energy file, = {0} or {1}
+      {0} Do not employ compensation energy until T<sub>p</sub><sup>Start</sup>
+      {1} Employ compensation energy file immediately :pre
+
+[Examples:]
+
+pair_style      hybrid/overlay lj/cut/hars/cg 2.469416506 0 0 lj/cut/hars/at 0.2 10.0 12.0 0 0
+pair_style      hybrid/overlay lj/cut/hars/cg 1.1224 1 0 lj/cut/hars/at 1.5 1 0 :pre
+
+[Description:]
+
+In the H-AdResS scheme, the description of the interactions within a system of particles is given in terms
+of a global Hamiltonian function H, which has the following form "(Potestio2013_1)"_#Potestio2013_1, "(Potestio2013_2)"_#Potestio2013_2, "(Heidari2016)"_#Heidari2016:
+
+:c,image(Eqs/HADRESS_System_Hamiltonian.png)
+
+The term K is the atomistic kinetic energy, and V<sup>int</sup> consists of all the intramolecular bonded interactions (e.g. bond stretching). 
+The value of the switching function is determined by the sizes L<sub>AT</sub>
+L<sub>HY</sub> of the atomistic and hybrid regions, respectively, and of the specific geometry of the atomistic region. 
+
+In the Hamiltonian, the non-bonded potential energy contribution of each molecule is given by a weighted sum of two terms
+V<sub>&#945;</sub><sup>CG</sup> and V<sub>&#945;</sub><sup>AT</sup>, defined as:
+
+:c,image(Eqs/HADRESS_System_Potentials.png)
+
+The {lj/cut/hars/at} styles compute the standard 12/6 Lennard-Jones potential for the atoms located in atomistic (high resolution) and hybrid region. 
+The general formula is given by
+
+:c,image(Eqs/HADRESS_AT_pair_lj.png)
+
+rc is the cutoff.
+
+Style {lj/cut/coul/dsf/hars/at} computes the standard 12/6 Lennard-Jones and Coulomb interactions for atoms of atomistic (high resolution) and hybrid region. 
+The Coulombic term is computed via the damped shifted force model introduced by "Fennell et al."_#Fennell, given by:
+
+:c,image(Eqs/HADRESS_AT_pair_coul_dsf.jpg)
+
+where {alpha} is the damping parameter and erfc() is the complementary
+error-function. This potential is essentially a short-range,
+spherically-truncated, charge-neutralized, shifted, pairwise {1/r}
+summation.
+
+The {lj/cut/hars/cg} styles compute the standard 12/6 Lennard-Jones potential for the atoms located in the low resolution (coarse-grained) and hybrid region. 
+The general formula is given by
+
+:c,image(Eqs/HADRESS_CG_pair_lj.png)
+
+rc is the cutoff.
+As mentioned above, the interactions in the coarse-grained region are computed based on the center of mass of the particles.
+
+Important Note: For dual resolution simulations, it is required to use hybrid/overlay to include 
+both resolution pair-styles. 
+
+For all of dual resolution pair styles, the following coefficients must
+be defined for each pair of atoms types via the
+"pair_coeff"_pair_coeff.html command as in the examples below
+
+epsilon (energy units) :l
+sigma (distance units) :l
+cutoff (distance units) :l
+
+For examples:
+
+  pair_coeff      * * lj/cut/hars/cg 1.0 2.2
+  pair_coeff      1 1 lj/cut/coul/dsf/hars/at 0.15535 3.166
+  pair_coeff      * 2 lj/cut/coul/dsf/hars/at 0.0000 0.0000 :pre
+
+Note that sigma is defined in the LJ formula as the zero-crossing
+distance for the potential, not as the energy minimum at 2^(1/6)
+sigma. 
+
+All potentials have to be shifted at the cutoff through the command
+
+  pair_modify     shift yes :pre
+
+
+:line
+
+
+[Mixing, shift, table, tail correction, restart, rRESPA info]:
+
+All of the {lj/cut} pair styles support the
+"pair_modify"_pair_modify.html shift option for the energy of the
+Lennard-Jones portion of the pair interaction.
+
+All of the {lj/cut} pair styles write their information to "binary
+restart files"_restart.html, so pair_style and pair_coeff commands do
+not need to be specified in an input script that reads a restart file.
+
+The pair styles do not support the use of the rRESPA hierarchy.
+
+Each pair styles creates a file named as "Mean_Comp_Energy_XX.txt", where the file name's suffix "XX", is replaced by "AT" and "CG" for atomistic and coarse-grained pairwise interactions respectively. 
+In these files the averaged compensation energy as function of the resolution (&#955;) is printed. Each file is created at {T<sub>p</sub><sup>Start</sup>} and is updated every {dT<sub>p</sub>}. 
+The updating process of the files is finished at time step {T<sub>p</sub><sup>End</sup>}. 
+For those equilibrated simulations starting at time step larger than {T<sub>p</sub><sup>End</sup>}, the file "Mean_Comp_Energy_XX.txt" is loaded in each pair styles. For more information, 
+see "fix_lambdah_calc"_fix_lambdah_calc.html.
+
+:line
+
+[Restrictions:]
+
+In HAdResS, it is required to include both high resolution (atomistic) 
+and low resolution (coarse-grained) force fields together through 
+
+  pair_style      hybrid/overlay :pre
+An example of such setup is given above.
+
+To employ the H-AdResS scheme, the full/hars atom style as well as "(fix_lambdah_calc)"_fix_lambdah_calc.html have to be used:
+
+  atom_style      full/hars :pre
+
+  fix             ID group-ID lambdah/calc ... :pre
+
+:line
+
+[Related commands:]
+
+"fix_lambdah_calc"_fix_lambdah_calc.html, "pair_coeff"_pair_coeff.html
+
+[Default:] none
+
+:line
+
+:link(Potestio2013_1)
+[(Potestio2013_1)] R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, {Hamiltonian Adaptive Resolution Simulation for Molecular Liquids}, "Phys. Rev. Lett. \[110\],
+108301 (2013)"_http://dx.doi.org/10.1103/PhysRevLett.110.108301
+
+:link(Potestio2013_2)
+[(Potestio2013_2)] R. Potestio, S. Fritsch, P. Espanol, R. Delgado-Buscalioni, K. Kremer, R. Everaers, and D. Donadio, {Monte Carlo Adaptive Resolution Simulation of Multicomponent Molecular Liquids}, "Phys. Rev. Lett. \[111\],
+060601 (2013)"_http://dx.doi.org/10.1103/PhysRevLett.111.060601
+
+:link(Heidari2016)
+[(Heidari2016)] M. Heidari, R. Cortes-Huerto, D. Donadio and R. Potestio, {Accurate and general treatment of electrostatic interaction in Hamiltonian adaptive resolution simulations}, "EPJST (2016)"
+
+:link(Fennell)
+[(Fennell)] C. J. Fennell, J. D. Gezelter, J Chem Phys, 124, 
+234104 (2006).
diff --git a/src/USER-HADRESS/Install.sh b/src/USER-HADRESS/Install.sh
new file mode 100644
index 000000000..1b919c4c5
--- /dev/null
+++ b/src/USER-HADRESS/Install.sh
@@ -0,0 +1,60 @@
+# Install/unInstall package files in LAMMPS
+# mode = 0/1/2 for uninstall/install/update
+
+mode=$1
+
+# arg1 = file, arg2 = file it depends on
+
+action () {
+  if (test $mode = 0) then
+    rm -f ../$1
+  elif (! cmp -s $1 ../$1) then
+    if (test -z "$2" || test -e ../$2) then
+      cp $1 ..
+      if (test $mode = 2) then
+        echo "  updating src/$1"
+      fi
+    fi
+  elif (test -n "$2") then
+    if (test ! -e ../$2) then
+      rm -f ../$1
+    fi
+  fi
+}
+
+# all package files with no dependencies
+
+for file in *.cpp *.h; do
+  action $file
+done
+
+# edit 2 Makefile.package files to include/exclude package info
+
+if (test $1 = 1) then
+
+  if (test -e ../Makefile.package) then
+    sed -i -e 's/[^ \t]*user-hadress[^ \t]* //' ../Makefile.package
+    sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(user-hadress_SYSINC) |' ../Makefile.package
+    sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(user-hadress_SYSLIB) |' ../Makefile.package
+    sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(user-hadress_SYSPATH) |' ../Makefile.package
+  fi
+
+  if (test -e ../Makefile.package.settings) then
+    sed -i -e '/^include.*user-hadress.*$/d' ../Makefile.package.settings
+    # multiline form needed for BSD sed on Macs
+    sed -i -e '4 i \
+include ..\/..\/lib\/user-hadress\/Makefile.lammps
+' ../Makefile.package.settings
+  fi
+
+elif (test $1 = 0) then
+
+  if (test -e ../Makefile.package) then
+    sed -i -e 's/[^ \t]*user-hadress[^ \t]* //' ../Makefile.package
+  fi
+
+  if (test -e ../Makefile.package.settings) then
+    sed -i -e '/^include.*user-hadress.*$/d' ../Makefile.package.settings
+  fi
+
+fi
diff --git a/src/USER-HADRESS/atom.cpp b/src/USER-HADRESS/atom.cpp
new file mode 100644
index 000000000..6ef632683
--- /dev/null
+++ b/src/USER-HADRESS/atom.cpp
@@ -0,0 +1,2206 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain rights in this software.  This software is distributed under
+   the GNU General Public License.
+
+   See the README file in the top-level LAMMPS directory.
+------------------------------------------------------------------------- */
+
+#include <mpi.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "atom.h"
+#include "style_atom.h"
+#include "atom_vec.h"
+#include "atom_vec_ellipsoid.h"
+#include "comm.h"
+#include "neighbor.h"
+#include "force.h"
+#include "modify.h"
+#include "fix.h"
+#include "output.h"
+#include "thermo.h"
+#include "update.h"
+#include "domain.h"
+#include "group.h"
+#include "molecule.h"
+#include "accelerator_cuda.h"
+#include "atom_masks.h"
+#include "math_const.h"
+#include "memory.h"
+#include "error.h"
+
+using namespace LAMMPS_NS;
+using namespace MathConst;
+
+#define DELTA 1
+#define DELTA_MEMSTR 1024
+#define EPSILON 1.0e-6
+#define CUDA_CHUNK 3000
+
+enum{LAYOUT_UNIFORM,LAYOUT_NONUNIFORM,LAYOUT_TILED};    // several files
+
+/* ---------------------------------------------------------------------- */
+
+Atom::Atom(LAMMPS *lmp) : Pointers(lmp)
+{
+  natoms = 0;
+  nlocal = nghost = nmax = 0;
+  ntypes = 0;
+  nbondtypes = nangletypes = ndihedraltypes = nimpropertypes = 0;
+  nbonds = nangles = ndihedrals = nimpropers = 0;
+
+  firstgroupname = NULL;
+  sortfreq = 1000;
+  nextsort = 0;
+  userbinsize = 0.0;
+  maxbin = maxnext = 0;
+  binhead = NULL;
+  next = permute = NULL;
+
+  // initialize atom arrays
+  // customize by adding new array
+
+  tag = NULL;
+  type = mask = NULL;
+  image = NULL;
+  x = v = f = NULL;
+
+  molecule = NULL;
+  molindex = molatom = NULL;
+  q = NULL;
+  mu = NULL;
+  omega = angmom = torque = NULL;
+  radius = rmass = NULL;
+  ellipsoid = line = tri = body = NULL;
+
+  lambdaH = NULL;
+  gradlambdaH = NULL;
+  replambdaH = NULL;
+  moltypeH = NULL;
+  comH = NULL;
+  nmoltypesH = 0;
+
+  vfrac = s0 = NULL;
+  x0 = NULL;
+
+  spin = NULL;
+  eradius = ervel = erforce = NULL;
+  cs = csforce = vforce = ervelforce = NULL;
+  etag = NULL;
+
+  rho = drho = e = de = cv = NULL;
+  vest = NULL;
+
+  // USER-DPD
+
+  uCond = uMech = uChem = uCG = uCGnew = NULL;
+  duCond = duMech = duChem = NULL;
+  dpdTheta = NULL;
+
+  // USER-SMD
+
+  contact_radius = NULL;
+  smd_data_9 = NULL;
+  smd_stress = NULL;
+  eff_plastic_strain = NULL;
+  eff_plastic_strain_rate = NULL;
+  damage = NULL;
+
+  // molecular info
+
+  bond_per_atom =  extra_bond_per_atom = 0;
+  num_bond = NULL;
+  bond_type = NULL;
+  bond_atom = NULL;
+
+  angle_per_atom = extra_angle_per_atom = 0;
+  num_angle = NULL;
+  angle_type = NULL;
+  angle_atom1 = angle_atom2 = angle_atom3 = NULL;
+
+  dihedral_per_atom = extra_dihedral_per_atom = 0;
+  num_dihedral = NULL;
+  dihedral_type = NULL;
+  dihedral_atom1 = dihedral_atom2 = dihedral_atom3 = dihedral_atom4 = NULL;
+
+  improper_per_atom = extra_improper_per_atom = 0;
+  num_improper = NULL;
+  improper_type = NULL;
+  improper_atom1 = improper_atom2 = improper_atom3 = improper_atom4 = NULL;
+
+  maxspecial = 1;
+  nspecial = NULL;
+  special = NULL;
+
+  // user-defined molecules
+
+  nmolecule = 0;
+  molecules = NULL;
+
+  // custom atom arrays
+
+  nivector = ndvector = 0;
+  ivector = NULL;
+  dvector = NULL;
+  iname = dname = NULL;
+
+  // initialize atom style and array existence flags
+  // customize by adding new flag
+
+  sphere_flag = peri_flag = electron_flag = 0;
+  wavepacket_flag = sph_flag = 0;
+
+  molecule_flag = 0;
+  q_flag = mu_flag = 0;
+  omega_flag = torque_flag = angmom_flag = 0;
+  radius_flag = rmass_flag = 0;
+  ellipsoid_flag = line_flag = tri_flag = body_flag = 0;
+
+  vfrac_flag = 0;
+  spin_flag = eradius_flag = ervel_flag = erforce_flag = ervelforce_flag = 0;
+  cs_flag = csforce_flag = vforce_flag = etag_flag = 0;
+
+  rho_flag = e_flag = cv_flag = vest_flag = 0;
+  dpd_flag = 0;
+
+  // USER-SMD
+
+  smd_flag = 0;
+  contact_radius_flag = 0;
+  smd_data_9_flag = 0;
+  smd_stress_flag = 0;
+  x0_flag = 0;
+  eff_plastic_strain_flag = 0;
+  eff_plastic_strain_rate_flag = 0;
+  damage_flag = 0;
+
+  // Peridynamic scale factor
+
+  pdscale = 1.0;
+
+  // ntype-length arrays
+
+  mass = NULL;
+  mass_setflag = NULL;
+
+  // callback lists & extra restart info
+
+  nextra_grow = nextra_restart = nextra_border = 0;
+  extra_grow = extra_restart = extra_border = NULL;
+  nextra_grow_max = nextra_restart_max = nextra_border_max = 0;
+  nextra_store = 0;
+  extra = NULL;
+
+  // default atom ID and mapping values
+
+  tag_enable = 1;
+  map_style = map_user = 0;
+  map_tag_max = -1;
+  map_maxarray = map_nhash = -1;
+
+  max_same = 0;
+  sametag = NULL;
+  map_array = NULL;
+  map_bucket = NULL;
+  map_hash = NULL;
+
+  atom_style = NULL;
+  avec = NULL;
+
+  datamask = ALL_MASK;
+  datamask_ext = ALL_MASK;
+}
+
+/* ---------------------------------------------------------------------- */
+
+Atom::~Atom()
+{
+  delete [] atom_style;
+  delete avec;
+
+  delete [] firstgroupname;
+  memory->destroy(binhead);
+  memory->destroy(next);
+  memory->destroy(permute);
+
+  // delete atom arrays
+  // customize by adding new array
+
+  memory->destroy(tag);
+  memory->destroy(type);
+  memory->destroy(mask);
+  memory->destroy(image);
+  memory->destroy(x);
+  memory->destroy(v);
+  memory->destroy(f);
+
+  memory->destroy(molecule);
+  memory->destroy(molindex);
+  memory->destroy(molatom);
+
+  memory->destroy(lambdaH);
+  memory->destroy(replambdaH);
+  memory->destroy(moltypeH);
+  memory->destroy(gradlambdaH);
+  memory->destroy(comH);
+
+  memory->destroy(q);
+  memory->destroy(mu);
+  memory->destroy(omega);
+  memory->destroy(angmom);
+  memory->destroy(torque);
+  memory->destroy(radius);
+  memory->destroy(rmass);
+  memory->destroy(ellipsoid);
+  memory->destroy(line);
+  memory->destroy(tri);
+  memory->destroy(body);
+
+  memory->destroy(vfrac);
+  memory->destroy(s0);
+  memory->destroy(x0);
+
+  memory->destroy(spin);
+  memory->destroy(eradius);
+  memory->destroy(ervel);
+  memory->destroy(erforce);
+  memory->destroy(ervelforce);
+  memory->destroy(cs);
+  memory->destroy(csforce);
+  memory->destroy(vforce);
+  memory->destroy(etag);
+
+  memory->destroy(rho);
+  memory->destroy(drho);
+  memory->destroy(e);
+  memory->destroy(de);
+  memory->destroy(cv);
+  memory->destroy(vest);
+
+  memory->destroy(contact_radius);
+  memory->destroy(smd_data_9);
+  memory->destroy(smd_stress);
+  memory->destroy(eff_plastic_strain);
+  memory->destroy(eff_plastic_strain_rate);
+  memory->destroy(damage);
+
+  memory->destroy(dpdTheta);
+  memory->destroy(uCond);
+  memory->destroy(uMech);
+  memory->destroy(uChem);
+  memory->destroy(uCG);
+  memory->destroy(uCGnew);
+  memory->destroy(duCond);
+  memory->destroy(duMech);
+  memory->destroy(duChem);
+
+  memory->destroy(nspecial);
+  memory->destroy(special);
+
+  memory->destroy(num_bond);
+  memory->destroy(bond_type);
+  memory->destroy(bond_atom);
+
+  memory->destroy(num_angle);
+  memory->destroy(angle_type);
+  memory->destroy(angle_atom1);
+  memory->destroy(angle_atom2);
+  memory->destroy(angle_atom3);
+
+  memory->destroy(num_dihedral);
+  memory->destroy(dihedral_type);
+  memory->destroy(dihedral_atom1);
+  memory->destroy(dihedral_atom2);
+  memory->destroy(dihedral_atom3);
+  memory->destroy(dihedral_atom4);
+
+  memory->destroy(num_improper);
+  memory->destroy(improper_type);
+  memory->destroy(improper_atom1);
+  memory->destroy(improper_atom2);
+  memory->destroy(improper_atom3);
+  memory->destroy(improper_atom4);
+
+  // delete custom atom arrays
+
+  for (int i = 0; i < nivector; i++) {
+    delete [] iname[i];
+    memory->destroy(ivector[i]);
+  }
+  for (int i = 0; i < ndvector; i++) {
+    delete [] dname[i];
+    memory->destroy(dvector[i]);
+  }
+
+  memory->sfree(iname);
+  memory->sfree(dname);
+  memory->sfree(ivector);
+  memory->sfree(dvector);
+
+  // delete user-defined molecules
+
+  for (int i = 0; i < nmolecule; i++) delete molecules[i];
+  memory->sfree(molecules);
+
+  // delete per-type arrays
+
+  delete [] mass;
+  delete [] mass_setflag;
+
+  // delete extra arrays
+
+  memory->destroy(extra_grow);
+  memory->destroy(extra_restart);
+  memory->destroy(extra_border);
+  memory->destroy(extra);
+
+  // delete mapping data structures
+
+  map_delete();
+}
+
+/* ----------------------------------------------------------------------
+   copy modify settings from old Atom class to current Atom class
+------------------------------------------------------------------------- */
+
+void Atom::settings(Atom *old)
+{
+  tag_enable = old->tag_enable;
+  map_user = old->map_user;
+  map_style = old->map_style;
+  sortfreq = old->sortfreq;
+  userbinsize = old->userbinsize;
+  if (old->firstgroupname) {
+    int n = strlen(old->firstgroupname) + 1;
+    firstgroupname = new char[n];
+    strcpy(firstgroupname,old->firstgroupname);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   create an AtomVec style
+   called from lammps.cpp, input script, restart file, replicate
+------------------------------------------------------------------------- */
+
+void Atom::create_avec(const char *style, int narg, char **arg, int trysuffix)
+{
+  delete [] atom_style;
+  if (avec) delete avec;
+
+  // unset atom style and array existence flags
+  // may have been set by old avec
+  // customize by adding new flag
+
+  sphere_flag = peri_flag = electron_flag = 0;
+  wavepacket_flag = sph_flag = 0;
+
+  molecule_flag = 0;
+  q_flag = mu_flag = 0;
+  replambdaH_flag = 0;
+  moltypeH_flag = 0;
+
+  omega_flag = torque_flag = angmom_flag = 0;
+  radius_flag = rmass_flag = 0;
+  ellipsoid_flag = line_flag = tri_flag = body_flag = 0;
+
+  vfrac_flag = 0;
+  spin_flag = eradius_flag = ervel_flag = erforce_flag = ervelforce_flag = 0;
+  cs_flag = csforce_flag = vforce_flag = etag_flag = 0;
+
+  rho_flag = e_flag = cv_flag = vest_flag = 0;
+
+  // create instance of AtomVec
+  // use grow() to initialize atom-based arrays to length 1
+  //   so that x[0][0] can always be referenced even if proc has no atoms
+
+  int sflag;
+  avec = new_avec(style,trysuffix,sflag);
+  avec->store_args(narg,arg);
+  avec->process_args(narg,arg);
+  avec->grow(1);
+
+  if (sflag) {
+    char estyle[256];
+    if (sflag == 1) sprintf(estyle,"%s/%s",style,lmp->suffix);
+    else sprintf(estyle,"%s/%s",style,lmp->suffix2);
+    int n = strlen(estyle) + 1;
+    atom_style = new char[n];
+    strcpy(atom_style,estyle);
+  } else {
+    int n = strlen(style) + 1;
+    atom_style = new char[n];
+    strcpy(atom_style,style);
+  }
+
+  // if molecular system:
+  // atom IDs must be defined
+  // force atom map to be created
+  // map style may be reset by map_init() and its call to map_style_set()
+
+  molecular = avec->molecular;
+  if (molecular && tag_enable == 0)
+    error->all(FLERR,"Atom IDs must be used for molecular systems");
+  if (molecular) map_style = 1;
+}
+
+/* ----------------------------------------------------------------------
+   generate an AtomVec class, first with suffix appended
+------------------------------------------------------------------------- */
+
+AtomVec *Atom::new_avec(const char *style, int trysuffix, int &sflag)
+{
+  if (trysuffix && lmp->suffix_enable) {
+    if (lmp->suffix) {
+      sflag = 1;
+      char estyle[256];
+      sprintf(estyle,"%s/%s",style,lmp->suffix);
+
+      if (0) return NULL;
+
+#define ATOM_CLASS
+#define AtomStyle(key,Class) \
+      else if (strcmp(estyle,#key) == 0) return new Class(lmp);
+#include "style_atom.h"
+#undef AtomStyle
+#undef ATOM_CLASS
+    }
+
+    if (lmp->suffix2) {
+      sflag = 2;
+      char estyle[256];
+      sprintf(estyle,"%s/%s",style,lmp->suffix2);
+
+      if (0) return NULL;
+
+#define ATOM_CLASS
+#define AtomStyle(key,Class) \
+      else if (strcmp(estyle,#key) == 0) return new Class(lmp);
+#include "style_atom.h"
+#undef AtomStyle
+#undef ATOM_CLASS
+    }
+  }
+
+  sflag = 0;
+  if (0) return NULL;
+
+#define ATOM_CLASS
+#define AtomStyle(key,Class) \
+  else if (strcmp(style,#key) == 0) return new Class(lmp);
+#include "style_atom.h"
+#undef ATOM_CLASS
+
+  else error->all(FLERR,"Unknown atom style");
+  return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void Atom::init()
+{
+  // delete extra array since it doesn't persist past first run
+
+  if (nextra_store) {
+    memory->destroy(extra);
+    extra = NULL;
+    nextra_store = 0;
+  }
+
+  // check arrays that are atom type in length
+
+  check_mass();
+
+  // setup of firstgroup
+
+  if (firstgroupname) {
+    firstgroup = group->find(firstgroupname);
+    if (firstgroup < 0)
+      error->all(FLERR,"Could not find atom_modify first group ID");
+  } else firstgroup = -1;
+
+  // init AtomVec
+
+  avec->init();
+}
+
+/* ---------------------------------------------------------------------- */
+
+void Atom::setup()
+{
+  // setup bins for sorting
+  // cannot do this in init() because uses neighbor cutoff
+
+  if (sortfreq > 0) setup_sort_bins();
+}
+
+/* ----------------------------------------------------------------------
+   return ptr to AtomVec class if matches style or to matching hybrid sub-class
+   return NULL if no match
+------------------------------------------------------------------------- */
+
+AtomVec *Atom::style_match(const char *style)
+{
+  if (strcmp(atom_style,style) == 0) return avec;
+  else if (strcmp(atom_style,"hybrid") == 0) {
+    AtomVecHybrid *avec_hybrid = (AtomVecHybrid *) avec;
+    for (int i = 0; i < avec_hybrid->nstyles; i++)
+      if (strcmp(avec_hybrid->keywords[i],style) == 0)
+        return avec_hybrid->styles[i];
+  }
+  return NULL;
+}
+
+/* ----------------------------------------------------------------------
+   modify parameters of the atom style
+   some options can only be invoked before simulation box is defined
+   first and sort options cannot be used together
+------------------------------------------------------------------------- */
+
+void Atom::modify_params(int narg, char **arg)
+{
+  if (narg == 0) error->all(FLERR,"Illegal atom_modify command");
+
+  int iarg = 0;
+  while (iarg < narg) {
+    if (strcmp(arg[iarg],"id") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command");
+      if (domain->box_exist)
+        error->all(FLERR,
+                   "Atom_modify id command after simulation box is defined");
+      if (strcmp(arg[iarg+1],"yes") == 0) tag_enable = 1;
+      else if (strcmp(arg[iarg+1],"no") == 0) tag_enable = 0;
+      else error->all(FLERR,"Illegal atom_modify command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"map") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command");
+      if (domain->box_exist)
+        error->all(FLERR,
+                   "Atom_modify map command after simulation box is defined");
+      if (strcmp(arg[iarg+1],"array") == 0) map_user = 1;
+      else if (strcmp(arg[iarg+1],"hash") == 0) map_user = 2;
+      else error->all(FLERR,"Illegal atom_modify command");
+      map_style = map_user;
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"first") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command");
+      if (strcmp(arg[iarg+1],"all") == 0) {
+        delete [] firstgroupname;
+        firstgroupname = NULL;
+      } else {
+        int n = strlen(arg[iarg+1]) + 1;
+        firstgroupname = new char[n];
+        strcpy(firstgroupname,arg[iarg+1]);
+        sortfreq = 0;
+      }
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"sort") == 0) {
+      if (iarg+3 > narg) error->all(FLERR,"Illegal atom_modify command");
+      sortfreq = force->inumeric(FLERR,arg[iarg+1]);
+      userbinsize = force->numeric(FLERR,arg[iarg+2]);
+      if (sortfreq < 0 || userbinsize < 0.0)
+        error->all(FLERR,"Illegal atom_modify command");
+      if (sortfreq >= 0 && firstgroupname)
+        error->all(FLERR,"Atom_modify sort and first options "
+                   "cannot be used together");
+      iarg += 3;
+    } else error->all(FLERR,"Illegal atom_modify command");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   check that atom IDs are valid
+   error if any atom ID < 0 or atom ID = MAXTAGINT
+   if any atom ID > 0, error if any atom ID == 0
+   if any atom ID > 0, error if tag_enable = 0
+   if all atom IDs = 0, tag_enable must be 0
+   if max atom IDs < natoms, must be duplicates
+   OK if max atom IDs > natoms
+   NOTE: not fully checking that atom IDs are unique
+------------------------------------------------------------------------- */
+
+void Atom::tag_check()
+{
+  tagint min = MAXTAGINT;
+  tagint max = 0;
+
+  for (int i = 0; i < nlocal; i++) {
+    min = MIN(min,tag[i]);
+    max = MAX(max,tag[i]);
+  }
+
+  tagint minall,maxall;
+  MPI_Allreduce(&min,&minall,1,MPI_LMP_TAGINT,MPI_MIN,world);
+  MPI_Allreduce(&max,&maxall,1,MPI_LMP_TAGINT,MPI_MAX,world);
+
+  if (minall < 0) error->all(FLERR,"One or more Atom IDs is negative");
+  if (maxall >= MAXTAGINT) error->all(FLERR,"One or more atom IDs is too big");
+  if (maxall > 0 && minall == 0)
+    error->all(FLERR,"One or more atom IDs is zero");
+  if (maxall > 0 && tag_enable == 0)
+    error->all(FLERR,"Non-zero atom IDs with atom_modify id = no");
+  if (maxall == 0 && natoms && tag_enable)
+    error->all(FLERR,"All atom IDs = 0 but atom_modify id = yes");
+  if (tag_enable && maxall < natoms)
+    error->all(FLERR,"Duplicate atom IDs exist");
+}
+
+/* ----------------------------------------------------------------------
+   add unique tags to any atoms with tag = 0
+   new tags are grouped by proc and start after max current tag
+   called after creating new atoms
+   error if new tags will exceed MAXTAGINT
+------------------------------------------------------------------------- */
+
+void Atom::tag_extend()
+{
+  // maxtag_all = max tag for all atoms
+
+  tagint maxtag = 0;
+  for (int i = 0; i < nlocal; i++) maxtag = MAX(maxtag,tag[i]);
+  tagint maxtag_all;
+  MPI_Allreduce(&maxtag,&maxtag_all,1,MPI_LMP_TAGINT,MPI_MAX,world);
+
+  // DEBUG: useful for generating 64-bit IDs even for small systems
+  // use only when LAMMPS is compiled with BIGBIG
+
+  //maxtag_all += 1000000000000;
+
+  // notag = # of atoms I own with no tag (tag = 0)
+  // notag_sum = # of total atoms on procs <= me with no tag
+
+  bigint notag = 0;
+  for (int i = 0; i < nlocal; i++) if (tag[i] == 0) notag++;
+
+  bigint notag_total;
+  MPI_Allreduce(&notag,&notag_total,1,MPI_LMP_BIGINT,MPI_SUM,world);
+  if (notag_total >= MAXTAGINT)
+    error->all(FLERR,"New atom IDs exceed maximum allowed ID");
+
+  bigint notag_sum;
+  MPI_Scan(&notag,&notag_sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
+
+  // itag = 1st new tag that my untagged atoms should use
+
+  tagint itag = maxtag_all + notag_sum - notag + 1;
+  for (int i = 0; i < nlocal; i++) if (tag[i] == 0) tag[i] = itag++;
+}
+
+/* ----------------------------------------------------------------------
+   check that atom IDs span range from 1 to Natoms inclusive
+   return 0 if mintag != 1 or maxtag != Natoms
+   return 1 if OK
+   doesn't actually check if all tag values are used
+------------------------------------------------------------------------- */
+
+int Atom::tag_consecutive()
+{
+  tagint idmin = MAXTAGINT;
+  tagint idmax = 0;
+
+  for (int i = 0; i < nlocal; i++) {
+    idmin = MIN(idmin,tag[i]);
+    idmax = MAX(idmax,tag[i]);
+  }
+  tagint idminall,idmaxall;
+  MPI_Allreduce(&idmin,&idminall,1,MPI_LMP_TAGINT,MPI_MIN,world);
+  MPI_Allreduce(&idmax,&idmaxall,1,MPI_LMP_TAGINT,MPI_MAX,world);
+
+  if (idminall != 1 || idmaxall != natoms) return 0;
+  return 1;
+}
+
+/* ----------------------------------------------------------------------
+   count and return words in a single line
+   make copy of line before using strtok so as not to change line
+   trim anything from '#' onward
+------------------------------------------------------------------------- */
+
+int Atom::count_words(const char *line)
+{
+  int n = strlen(line) + 1;
+  char *copy;
+  memory->create(copy,n,"atom:copy");
+  strcpy(copy,line);
+
+  char *ptr;
+  if ((ptr = strchr(copy,'#'))) *ptr = '\0';
+
+  if (strtok(copy," \t\n\r\f") == NULL) {
+    memory->destroy(copy);
+    return 0;
+  }
+  n = 1;
+  while (strtok(NULL," \t\n\r\f")) n++;
+
+  memory->destroy(copy);
+  return n;
+}
+
+/* ----------------------------------------------------------------------
+   count and return words in a single line using provided copy buf
+   make copy of line before using strtok so as not to change line
+   trim anything from '#' onward
+------------------------------------------------------------------------- */
+
+int Atom::count_words(const char *line, char *copy)
+{
+  strcpy(copy,line);
+
+  char *ptr;
+  if ((ptr = strchr(copy,'#'))) *ptr = '\0';
+
+  if (strtok(copy," \t\n\r\f") == NULL) {
+    memory->destroy(copy);
+    return 0;
+  }
+  int n = 1;
+  while (strtok(NULL," \t\n\r\f")) n++;
+
+  return n;
+}
+
+/* ----------------------------------------------------------------------
+   deallocate molecular topology arrays
+   done before realloc with (possibly) new 2nd dimension set to
+     correctly initialized per-atom values, e.g. bond_per_atom
+   needs to be called whenever 2nd dimensions are changed
+     and these arrays are already pre-allocated,
+     e.g. due to grow(1) in create_avec()
+------------------------------------------------------------------------- */
+
+void Atom::deallocate_topology()
+{
+  memory->destroy(atom->bond_type);
+  memory->destroy(atom->bond_atom);
+  atom->bond_type = NULL;
+  atom->bond_atom = NULL;
+
+  memory->destroy(atom->angle_type);
+  memory->destroy(atom->angle_atom1);
+  memory->destroy(atom->angle_atom2);
+  memory->destroy(atom->angle_atom3);
+  atom->angle_type = NULL;
+  atom->angle_atom1 = atom->angle_atom2 = atom->angle_atom3 = NULL;
+
+  memory->destroy(atom->dihedral_type);
+  memory->destroy(atom->dihedral_atom1);
+  memory->destroy(atom->dihedral_atom2);
+  memory->destroy(atom->dihedral_atom3);
+  memory->destroy(atom->dihedral_atom4);
+  atom->dihedral_type = NULL;
+  atom->dihedral_atom1 = atom->dihedral_atom2 =
+    atom->dihedral_atom3 = atom->dihedral_atom4 = NULL;
+
+  memory->destroy(atom->improper_type);
+  memory->destroy(atom->improper_atom1);
+  memory->destroy(atom->improper_atom2);
+  memory->destroy(atom->improper_atom3);
+  memory->destroy(atom->improper_atom4);
+  atom->improper_type = NULL;
+  atom->improper_atom1 = atom->improper_atom2 =
+    atom->improper_atom3 = atom->improper_atom4 = NULL;
+}
+
+/* ----------------------------------------------------------------------
+   unpack N lines from Atom section of data file
+   call style-specific routine to parse line
+------------------------------------------------------------------------- */
+
+void Atom::data_atoms(int n, char *buf, tagint id_offset, int type_offset,
+                      int shiftflag, double *shift)
+{
+  int m,xptr,iptr;
+  imageint imagedata;
+  double xdata[3],lamda[3];
+  double *coord;
+  char *next;
+
+  next = strchr(buf,'\n');
+  *next = '\0';
+  int nwords = count_words(buf);
+  *next = '\n';
+
+  if (nwords != avec->size_data_atom && nwords != avec->size_data_atom + 3)
+    error->all(FLERR,"Incorrect atom format in data file");
+
+  char **values = new char*[nwords];
+
+  // set bounds for my proc
+  // if periodic and I am lo/hi proc, adjust bounds by EPSILON
+  // insures all data atoms will be owned even with round-off
+
+  int triclinic = domain->triclinic;
+
+  double epsilon[3];
+  if (triclinic) epsilon[0] = epsilon[1] = epsilon[2] = EPSILON;
+  else {
+    epsilon[0] = domain->prd[0] * EPSILON;
+    epsilon[1] = domain->prd[1] * EPSILON;
+    epsilon[2] = domain->prd[2] * EPSILON;
+  }
+
+  double sublo[3],subhi[3];
+  if (triclinic == 0) {
+    sublo[0] = domain->sublo[0]; subhi[0] = domain->subhi[0];
+    sublo[1] = domain->sublo[1]; subhi[1] = domain->subhi[1];
+    sublo[2] = domain->sublo[2]; subhi[2] = domain->subhi[2];
+  } else {
+    sublo[0] = domain->sublo_lamda[0]; subhi[0] = domain->subhi_lamda[0];
+    sublo[1] = domain->sublo_lamda[1]; subhi[1] = domain->subhi_lamda[1];
+    sublo[2] = domain->sublo_lamda[2]; subhi[2] = domain->subhi_lamda[2];
+  }
+
+  if (comm->layout != LAYOUT_TILED) {
+    if (domain->xperiodic) {
+      if (comm->myloc[0] == 0) sublo[0] -= epsilon[0];
+      if (comm->myloc[0] == comm->procgrid[0]-1) subhi[0] += epsilon[0];
+    }
+    if (domain->yperiodic) {
+      if (comm->myloc[1] == 0) sublo[1] -= epsilon[1];
+      if (comm->myloc[1] == comm->procgrid[1]-1) subhi[1] += epsilon[1];
+    }
+    if (domain->zperiodic) {
+      if (comm->myloc[2] == 0) sublo[2] -= epsilon[2];
+      if (comm->myloc[2] == comm->procgrid[2]-1) subhi[2] += epsilon[2];
+    }
+
+  } else {
+    if (domain->xperiodic) {
+      if (comm->mysplit[0][0] == 0.0) sublo[0] -= epsilon[0];
+      if (comm->mysplit[0][1] == 1.0) subhi[0] += epsilon[0];
+    }
+    if (domain->yperiodic) {
+      if (comm->mysplit[1][0] == 0.0) sublo[1] -= epsilon[1];
+      if (comm->mysplit[1][1] == 1.0) subhi[1] += epsilon[1];
+    }
+    if (domain->zperiodic) {
+      if (comm->mysplit[2][0] == 0.0) sublo[2] -= epsilon[2];
+      if (comm->mysplit[2][1] == 1.0) subhi[2] += epsilon[2];
+    }
+  }
+
+  // xptr = which word in line starts xyz coords
+  // iptr = which word in line starts ix,iy,iz image flags
+
+  xptr = avec->xcol_data - 1;
+  int imageflag = 0;
+  if (nwords > avec->size_data_atom) imageflag = 1;
+  if (imageflag) iptr = nwords - 3;
+
+  // loop over lines of atom data
+  // tokenize the line into values
+  // extract xyz coords and image flags
+  // remap atom into simulation box
+  // if atom is in my sub-domain, unpack its values
+
+  for (int i = 0; i < n; i++) {
+    next = strchr(buf,'\n');
+
+    values[0] = strtok(buf," \t\n\r\f");
+    if (values[0] == NULL)
+      error->all(FLERR,"Incorrect atom format in data file");
+    for (m = 1; m < nwords; m++) {
+      values[m] = strtok(NULL," \t\n\r\f");
+      if (values[m] == NULL)
+        error->all(FLERR,"Incorrect atom format in data file");
+    }
+
+    if (imageflag)
+      imagedata = ((imageint) (atoi(values[iptr]) + IMGMAX) & IMGMASK) |
+        (((imageint) (atoi(values[iptr+1]) + IMGMAX) & IMGMASK) << IMGBITS) |
+        (((imageint) (atoi(values[iptr+2]) + IMGMAX) & IMGMASK) << IMG2BITS);
+    else imagedata = ((imageint) IMGMAX << IMG2BITS) |
+           ((imageint) IMGMAX << IMGBITS) | IMGMAX;
+
+    xdata[0] = atof(values[xptr]);
+    xdata[1] = atof(values[xptr+1]);
+    xdata[2] = atof(values[xptr+2]);
+    if (shiftflag) {
+      xdata[0] += shift[0];
+      xdata[1] += shift[1];
+      xdata[2] += shift[2];
+    }
+
+    domain->remap(xdata,imagedata);
+    if (triclinic) {
+      domain->x2lamda(xdata,lamda);
+      coord = lamda;
+    } else coord = xdata;
+
+    if (coord[0] >= sublo[0] && coord[0] < subhi[0] &&
+        coord[1] >= sublo[1] && coord[1] < subhi[1] &&
+        coord[2] >= sublo[2] && coord[2] < subhi[2]) {
+      avec->data_atom(xdata,imagedata,values);
+      if (id_offset) tag[nlocal-1] += id_offset;
+      if (type_offset) {
+        type[nlocal-1] += type_offset;
+        if (type[nlocal-1] > ntypes)
+          error->one(FLERR,"Invalid atom type in Atoms section of data file");
+      }
+    }
+
+    buf = next + 1;
+  }
+
+  delete [] values;
+}
+
+/* ----------------------------------------------------------------------
+   unpack N lines from Velocity section of data file
+   check that atom IDs are > 0 and <= map_tag_max
+   call style-specific routine to parse line
+------------------------------------------------------------------------- */
+
+void Atom::data_vels(int n, char *buf, tagint id_offset)
+{
+  int j,m;
+  tagint tagdata;
+  char *next;
+
+  next = strchr(buf,'\n');
+  *next = '\0';
+  int nwords = count_words(buf);
+  *next = '\n';
+
+  if (nwords != avec->size_data_vel)
+    error->all(FLERR,"Incorrect velocity format in data file");
+
+  char **values = new char*[nwords];
+
+  // loop over lines of atom velocities
+  // tokenize the line into values
+  // if I own atom tag, unpack its values
+
+  for (int i = 0; i < n; i++) {
+    next = strchr(buf,'\n');
+
+    values[0] = strtok(buf," \t\n\r\f");
+    for (j = 1; j < nwords; j++)
+      values[j] = strtok(NULL," \t\n\r\f");
+
+    tagdata = ATOTAGINT(values[0]) + id_offset;
+    if (tagdata <= 0 || tagdata > map_tag_max)
+      error->one(FLERR,"Invalid atom ID in Velocities section of data file");
+    if ((m = map(tagdata)) >= 0) avec->data_vel(m,&values[1]);
+
+    buf = next + 1;
+  }
+
+  delete [] values;
+}
+
+/* ----------------------------------------------------------------------
+   process N bonds read into buf from data files
+   if count is non-NULL, just count bonds per atom
+   else store them with atoms
+   check that atom IDs are > 0 and <= map_tag_max
+------------------------------------------------------------------------- */
+
+void Atom::data_bonds(int n, char *buf, int *count, tagint id_offset,
+                      int type_offset)
+{
+  int m,tmp,itype;
+  tagint atom1,atom2;
+  char *next;
+  int newton_bond = force->newton_bond;
+
+  for (int i = 0; i < n; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT,
+           &tmp,&itype,&atom1,&atom2);
+    if (id_offset) {
+      atom1 += id_offset;
+      atom2 += id_offset;
+    }
+    itype += type_offset;
+
+    if (atom1 <= 0 || atom1 > map_tag_max ||
+        atom2 <= 0 || atom2 > map_tag_max)
+      error->one(FLERR,"Invalid atom ID in Bonds section of data file");
+    if (itype <= 0 || itype > nbondtypes)
+      error->one(FLERR,"Invalid bond type in Bonds section of data file");
+    if ((m = map(atom1)) >= 0) {
+      if (count) count[m]++;
+      else {
+        bond_type[m][num_bond[m]] = itype;
+        bond_atom[m][num_bond[m]] = atom2;
+        num_bond[m]++;
+      }
+    }
+    if (newton_bond == 0) {
+      if ((m = map(atom2)) >= 0) {
+        if (count) count[m]++;
+        else {
+          bond_type[m][num_bond[m]] = itype;
+          bond_atom[m][num_bond[m]] = atom1;
+          num_bond[m]++;
+        }
+      }
+    }
+    buf = next + 1;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   process N angles read into buf from data files
+   if count is non-NULL, just count angles per atom
+   else store them with atoms
+   check that atom IDs are > 0 and <= map_tag_max
+------------------------------------------------------------------------- */
+
+void Atom::data_angles(int n, char *buf, int *count, tagint id_offset,
+                       int type_offset)
+{
+  int m,tmp,itype;
+  tagint atom1,atom2,atom3;
+  char *next;
+  int newton_bond = force->newton_bond;
+
+  for (int i = 0; i < n; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT,
+           &tmp,&itype,&atom1,&atom2,&atom3);
+    if (id_offset) {
+      atom1 += id_offset;
+      atom2 += id_offset;
+      atom3 += id_offset;
+    }
+    itype += type_offset;
+
+    if (atom1 <= 0 || atom1 > map_tag_max ||
+        atom2 <= 0 || atom2 > map_tag_max ||
+        atom3 <= 0 || atom3 > map_tag_max)
+      error->one(FLERR,"Invalid atom ID in Angles section of data file");
+    if (itype <= 0 || itype > nangletypes)
+      error->one(FLERR,"Invalid angle type in Angles section of data file");
+    if ((m = map(atom2)) >= 0) {
+      if (count) count[m]++;
+      else {
+        angle_type[m][num_angle[m]] = itype;
+        angle_atom1[m][num_angle[m]] = atom1;
+        angle_atom2[m][num_angle[m]] = atom2;
+        angle_atom3[m][num_angle[m]] = atom3;
+        num_angle[m]++;
+      }
+    }
+    if (newton_bond == 0) {
+      if ((m = map(atom1)) >= 0) {
+        if (count) count[m]++;
+        else {
+          angle_type[m][num_angle[m]] = itype;
+          angle_atom1[m][num_angle[m]] = atom1;
+          angle_atom2[m][num_angle[m]] = atom2;
+          angle_atom3[m][num_angle[m]] = atom3;
+          num_angle[m]++;
+        }
+      }
+      if ((m = map(atom3)) >= 0) {
+        if (count) count[m]++;
+        else {
+          angle_type[m][num_angle[m]] = itype;
+          angle_atom1[m][num_angle[m]] = atom1;
+          angle_atom2[m][num_angle[m]] = atom2;
+          angle_atom3[m][num_angle[m]] = atom3;
+          num_angle[m]++;
+        }
+      }
+    }
+    buf = next + 1;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   process N dihedrals read into buf from data files
+   if count is non-NULL, just count diihedrals per atom
+   else store them with atoms
+   check that atom IDs are > 0 and <= map_tag_max
+------------------------------------------------------------------------- */
+
+void Atom::data_dihedrals(int n, char *buf, int *count, tagint id_offset,
+                          int type_offset)
+{
+  int m,tmp,itype;
+  tagint atom1,atom2,atom3,atom4;
+  char *next;
+  int newton_bond = force->newton_bond;
+
+  for (int i = 0; i < n; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    sscanf(buf,"%d %d "
+           TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT,
+           &tmp,&itype,&atom1,&atom2,&atom3,&atom4);
+    if (id_offset) {
+      atom1 += id_offset;
+      atom2 += id_offset;
+      atom3 += id_offset;
+      atom4 += id_offset;
+    }
+    itype += type_offset;
+
+    if (atom1 <= 0 || atom1 > map_tag_max ||
+        atom2 <= 0 || atom2 > map_tag_max ||
+        atom3 <= 0 || atom3 > map_tag_max ||
+        atom4 <= 0 || atom4 > map_tag_max)
+      error->one(FLERR,"Invalid atom ID in Dihedrals section of data file");
+    if (itype <= 0 || itype > ndihedraltypes)
+      error->one(FLERR,
+                 "Invalid dihedral type in Dihedrals section of data file");
+    if ((m = map(atom2)) >= 0) {
+      if (count) count[m]++;
+      else {
+        dihedral_type[m][num_dihedral[m]] = itype;
+        dihedral_atom1[m][num_dihedral[m]] = atom1;
+        dihedral_atom2[m][num_dihedral[m]] = atom2;
+        dihedral_atom3[m][num_dihedral[m]] = atom3;
+        dihedral_atom4[m][num_dihedral[m]] = atom4;
+        num_dihedral[m]++;
+      }
+    }
+    if (newton_bond == 0) {
+      if ((m = map(atom1)) >= 0) {
+        if (count) count[m]++;
+        else {
+          dihedral_type[m][num_dihedral[m]] = itype;
+          dihedral_atom1[m][num_dihedral[m]] = atom1;
+          dihedral_atom2[m][num_dihedral[m]] = atom2;
+          dihedral_atom3[m][num_dihedral[m]] = atom3;
+          dihedral_atom4[m][num_dihedral[m]] = atom4;
+          num_dihedral[m]++;
+        }
+      }
+      if ((m = map(atom3)) >= 0) {
+        if (count) count[m]++;
+        else {
+          dihedral_type[m][num_dihedral[m]] = itype;
+          dihedral_atom1[m][num_dihedral[m]] = atom1;
+          dihedral_atom2[m][num_dihedral[m]] = atom2;
+          dihedral_atom3[m][num_dihedral[m]] = atom3;
+          dihedral_atom4[m][num_dihedral[m]] = atom4;
+          num_dihedral[m]++;
+        }
+      }
+      if ((m = map(atom4)) >= 0) {
+        if (count) count[m]++;
+        else {
+          dihedral_type[m][num_dihedral[m]] = itype;
+          dihedral_atom1[m][num_dihedral[m]] = atom1;
+          dihedral_atom2[m][num_dihedral[m]] = atom2;
+          dihedral_atom3[m][num_dihedral[m]] = atom3;
+          dihedral_atom4[m][num_dihedral[m]] = atom4;
+          num_dihedral[m]++;
+        }
+      }
+    }
+    buf = next + 1;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   process N impropers read into buf from data files
+   if count is non-NULL, just count impropers per atom
+   else store them with atoms
+   check that atom IDs are > 0 and <= map_tag_max
+------------------------------------------------------------------------- */
+
+void Atom::data_impropers(int n, char *buf, int *count, tagint id_offset,
+                          int type_offset)
+{
+  int m,tmp,itype;
+  tagint atom1,atom2,atom3,atom4;
+  char *next;
+  int newton_bond = force->newton_bond;
+
+  for (int i = 0; i < n; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    sscanf(buf,"%d %d "
+           TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT,
+           &tmp,&itype,&atom1,&atom2,&atom3,&atom4);
+    if (id_offset) {
+      atom1 += id_offset;
+      atom2 += id_offset;
+      atom3 += id_offset;
+      atom4 += id_offset;
+    }
+    itype += type_offset;
+
+    if (atom1 <= 0 || atom1 > map_tag_max ||
+        atom2 <= 0 || atom2 > map_tag_max ||
+        atom3 <= 0 || atom3 > map_tag_max ||
+        atom4 <= 0 || atom4 > map_tag_max)
+      error->one(FLERR,"Invalid atom ID in Impropers section of data file");
+    if (itype <= 0 || itype > nimpropertypes)
+      error->one(FLERR,
+                 "Invalid improper type in Impropers section of data file");
+    if ((m = map(atom2)) >= 0) {
+      if (count) count[m]++;
+      else {
+        improper_type[m][num_improper[m]] = itype;
+        improper_atom1[m][num_improper[m]] = atom1;
+        improper_atom2[m][num_improper[m]] = atom2;
+        improper_atom3[m][num_improper[m]] = atom3;
+        improper_atom4[m][num_improper[m]] = atom4;
+        num_improper[m]++;
+      }
+    }
+    if (newton_bond == 0) {
+      if ((m = map(atom1)) >= 0) {
+        if (count) count[m]++;
+        else {
+          improper_type[m][num_improper[m]] = itype;
+          improper_atom1[m][num_improper[m]] = atom1;
+          improper_atom2[m][num_improper[m]] = atom2;
+          improper_atom3[m][num_improper[m]] = atom3;
+          improper_atom4[m][num_improper[m]] = atom4;
+          num_improper[m]++;
+        }
+      }
+      if ((m = map(atom3)) >= 0) {
+        if (count) count[m]++;
+        else {
+          improper_type[m][num_improper[m]] = itype;
+          improper_atom1[m][num_improper[m]] = atom1;
+          improper_atom2[m][num_improper[m]] = atom2;
+          improper_atom3[m][num_improper[m]] = atom3;
+          improper_atom4[m][num_improper[m]] = atom4;
+          num_improper[m]++;
+        }
+      }
+      if ((m = map(atom4)) >= 0) {
+        if (count) count[m]++;
+        else {
+          improper_type[m][num_improper[m]] = itype;
+          improper_atom1[m][num_improper[m]] = atom1;
+          improper_atom2[m][num_improper[m]] = atom2;
+          improper_atom3[m][num_improper[m]] = atom3;
+          improper_atom4[m][num_improper[m]] = atom4;
+          num_improper[m]++;
+        }
+      }
+    }
+    buf = next + 1;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   unpack N lines from atom-style specific bonus section of data file
+   check that atom IDs are > 0 and <= map_tag_max
+   call style-specific routine to parse line
+------------------------------------------------------------------------- */
+
+void Atom::data_bonus(int n, char *buf, AtomVec *avec_bonus, tagint id_offset)
+{
+  int j,m,tagdata;
+  char *next;
+
+  next = strchr(buf,'\n');
+  *next = '\0';
+  int nwords = count_words(buf);
+  *next = '\n';
+
+  if (nwords != avec_bonus->size_data_bonus)
+    error->all(FLERR,"Incorrect bonus data format in data file");
+
+  char **values = new char*[nwords];
+
+  // loop over lines of bonus atom data
+  // tokenize the line into values
+  // if I own atom tag, unpack its values
+
+  for (int i = 0; i < n; i++) {
+    next = strchr(buf,'\n');
+
+    values[0] = strtok(buf," \t\n\r\f");
+    for (j = 1; j < nwords; j++)
+      values[j] = strtok(NULL," \t\n\r\f");
+
+    tagdata = ATOTAGINT(values[0]) + id_offset;
+    if (tagdata <= 0 || tagdata > map_tag_max)
+      error->one(FLERR,"Invalid atom ID in Bonus section of data file");
+
+    // ok to call child's data_atom_bonus() method thru parent avec_bonus,
+    // since data_bonus() was called with child ptr, and method is virtual
+
+    if ((m = map(tagdata)) >= 0) avec_bonus->data_atom_bonus(m,&values[1]);
+
+    buf = next + 1;
+  }
+
+  delete [] values;
+}
+
+/* ----------------------------------------------------------------------
+   unpack N bodies from Bodies section of data file
+   each body spans multiple lines
+   check that atom IDs are > 0 and <= map_tag_max
+   call style-specific routine to parse line
+------------------------------------------------------------------------- */
+
+void Atom::data_bodies(int n, char *buf, AtomVecBody *avec_body,
+                       tagint id_offset)
+{
+  int j,m,nvalues,tagdata,ninteger,ndouble;
+
+  int maxint = 0;
+  int maxdouble = 0;
+  int *ivalues = NULL;
+  double *dvalues = NULL;
+
+  // loop over lines of body data
+  // if I own atom tag, tokenize lines into ivalues/dvalues, call data_body()
+  // else skip values
+
+  for (int i = 0; i < n; i++) {
+    if (i == 0) tagdata = ATOTAGINT(strtok(buf," \t\n\r\f")) + id_offset;
+    else tagdata = ATOTAGINT(strtok(NULL," \t\n\r\f")) + id_offset;
+
+    if (tagdata <= 0 || tagdata > map_tag_max)
+      error->one(FLERR,"Invalid atom ID in Bodies section of data file");
+
+    ninteger = force->inumeric(FLERR,strtok(NULL," \t\n\r\f"));
+    ndouble = force->inumeric(FLERR,strtok(NULL," \t\n\r\f"));
+    
+    if ((m = map(tagdata)) >= 0) {
+      if (ninteger > maxint) {
+	delete [] ivalues;
+	maxint = ninteger;
+	ivalues = new int[maxint];
+      }
+      if (ndouble > maxdouble) {
+	delete [] dvalues;
+	maxdouble = ndouble;
+	dvalues = new double[maxdouble];
+      }
+      
+      for (j = 0; j < ninteger; j++)
+	ivalues[j] = force->inumeric(FLERR,strtok(NULL," \t\n\r\f"));
+      for (j = 0; j < ndouble; j++)
+	dvalues[j] = force->numeric(FLERR,strtok(NULL," \t\n\r\f"));
+      
+      avec_body->data_body(m,ninteger,ndouble,ivalues,dvalues);
+      
+    } else {
+      nvalues = ninteger + ndouble;    // number of values to skip
+      for (j = 0; j < nvalues; j++)
+	strtok(NULL," \t\n\r\f");
+    }
+  }
+
+  delete [] ivalues;
+  delete [] dvalues;
+}
+
+/* ----------------------------------------------------------------------
+   allocate arrays of length ntypes
+   only done after ntypes is set
+------------------------------------------------------------------------- */
+
+void Atom::allocate_type_arrays()
+{
+  if (avec->mass_type) {
+    mass = new double[ntypes+1];
+    mass_setflag = new int[ntypes+1];
+    for (int itype = 1; itype <= ntypes; itype++) mass_setflag[itype] = 0;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   set a mass and flag it as set
+   called from reading of data file
+   type_offset may be used when reading multiple data files
+------------------------------------------------------------------------- */
+
+void Atom::set_mass(const char *str, int type_offset)
+{
+  if (mass == NULL) error->all(FLERR,"Cannot set mass for this atom style");
+
+  int itype;
+  double mass_one;
+  int n = sscanf(str,"%d %lg",&itype,&mass_one);
+  if (n != 2) error->all(FLERR,"Invalid mass line in data file");
+  itype += type_offset;
+
+  if (itype < 1 || itype > ntypes)
+    error->all(FLERR,"Invalid type for mass set");
+
+  mass[itype] = mass_one;
+  mass_setflag[itype] = 1;
+
+  if (mass[itype] <= 0.0) error->all(FLERR,"Invalid mass value");
+}
+
+/* ----------------------------------------------------------------------
+   set a mass and flag it as set
+   called from EAM pair routine
+------------------------------------------------------------------------- */
+
+void Atom::set_mass(int itype, double value)
+{
+  if (mass == NULL) error->all(FLERR,"Cannot set mass for this atom style");
+  if (itype < 1 || itype > ntypes)
+    error->all(FLERR,"Invalid type for mass set");
+
+  mass[itype] = value;
+  mass_setflag[itype] = 1;
+
+  if (mass[itype] <= 0.0) error->all(FLERR,"Invalid mass value");
+}
+
+/* ----------------------------------------------------------------------
+   set one or more masses and flag them as set
+   called from reading of input script
+------------------------------------------------------------------------- */
+
+void Atom::set_mass(int narg, char **arg)
+{
+  if (mass == NULL) error->all(FLERR,"Cannot set mass for this atom style");
+
+  int lo,hi;
+  force->bounds(arg[0],ntypes,lo,hi);
+  if (lo < 1 || hi > ntypes) error->all(FLERR,"Invalid type for mass set");
+
+  for (int itype = lo; itype <= hi; itype++) {
+    mass[itype] = atof(arg[1]);
+    mass_setflag[itype] = 1;
+
+    if (mass[itype] <= 0.0) error->all(FLERR,"Invalid mass value");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   set all masses as read in from restart file
+------------------------------------------------------------------------- */
+
+void Atom::set_mass(double *values)
+{
+  for (int itype = 1; itype <= ntypes; itype++) {
+    mass[itype] = values[itype];
+    mass_setflag[itype] = 1;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   check that all masses have been set
+------------------------------------------------------------------------- */
+
+void Atom::check_mass()
+{
+  if (mass == NULL) return;
+  for (int itype = 1; itype <= ntypes; itype++)
+    if (mass_setflag[itype] == 0) error->all(FLERR,"All masses are not set");
+}
+
+/* ----------------------------------------------------------------------
+   check that radii of all particles of itype are the same
+   return 1 if true, else return 0
+   also return the radius value for that type
+------------------------------------------------------------------------- */
+
+int Atom::radius_consistency(int itype, double &rad)
+{
+  double value = -1.0;
+  int flag = 0;
+  for (int i = 0; i < nlocal; i++) {
+    if (type[i] != itype) continue;
+    if (value < 0.0) value = radius[i];
+    else if (value != radius[i]) flag = 1;
+  }
+
+  int flagall;
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall) return 0;
+
+  MPI_Allreduce(&value,&rad,1,MPI_DOUBLE,MPI_MAX,world);
+  return 1;
+}
+
+/* ----------------------------------------------------------------------
+   check that shape of all particles of itype are the same
+   return 1 if true, else return 0
+   also return the 3 shape params for itype
+------------------------------------------------------------------------- */
+
+int Atom::shape_consistency(int itype,
+                            double &shapex, double &shapey, double &shapez)
+{
+  double zero[3] = {0.0, 0.0, 0.0};
+  double one[3] = {-1.0, -1.0, -1.0};
+  double *shape;
+
+  AtomVecEllipsoid *avec_ellipsoid =
+    (AtomVecEllipsoid *) style_match("ellipsoid");
+  AtomVecEllipsoid::Bonus *bonus = avec_ellipsoid->bonus;
+
+  int flag = 0;
+  for (int i = 0; i < nlocal; i++) {
+    if (type[i] != itype) continue;
+    if (ellipsoid[i] < 0) shape = zero;
+    else shape = bonus[ellipsoid[i]].shape;
+
+    if (one[0] < 0.0) {
+      one[0] = shape[0];
+      one[1] = shape[1];
+      one[2] = shape[2];
+    } else if (one[0] != shape[0] || one[1] != shape[1] || one[2] != shape[2])
+      flag = 1;
+  }
+
+  int flagall;
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall) return 0;
+
+  double oneall[3];
+  MPI_Allreduce(one,oneall,3,MPI_DOUBLE,MPI_MAX,world);
+  shapex = oneall[0];
+  shapey = oneall[1];
+  shapez = oneall[2];
+  return 1;
+}
+
+/* ----------------------------------------------------------------------
+   add a new molecule template = set of molecules
+------------------------------------------------------------------------- */
+
+void Atom::add_molecule(int narg, char **arg)
+{
+  if (narg < 1) error->all(FLERR,"Illegal molecule command");
+
+  if (find_molecule(arg[0]) >= 0)
+    error->all(FLERR,"Reuse of molecule template ID");
+
+  // 1st molecule in set stores nset = # of mols, others store nset = 0
+  // ifile = count of molecules in set
+  // index = argument index where next molecule starts, updated by constructor
+
+  int ifile = 1;
+  int index = 1;
+  while (1) {
+    molecules = (Molecule **)
+      memory->srealloc(molecules,(nmolecule+1)*sizeof(Molecule *),
+                       "atom::molecules");
+    molecules[nmolecule] = new Molecule(lmp,narg,arg,index);
+    molecules[nmolecule]->nset = 0;
+    molecules[nmolecule-ifile+1]->nset++;
+    nmolecule++;
+    if (molecules[nmolecule-1]->last) break;
+    ifile++;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   find first molecule in set with template ID
+   return -1 if does not exist
+------------------------------------------------------------------------- */
+
+int Atom::find_molecule(char *id)
+{
+  int imol;
+  for (imol = 0; imol < nmolecule; imol++)
+    if (strcmp(id,molecules[imol]->id) == 0) return imol;
+  return -1;
+}
+
+/* ----------------------------------------------------------------------
+   add info to current atom ilocal from molecule template onemol and its iatom
+   offset = atom ID preceeding IDs of atoms in this molecule
+   called by fixes and commands that add molecules
+------------------------------------------------------------------------- */
+
+void Atom::add_molecule_atom(Molecule *onemol, int iatom,
+                             int ilocal, tagint offset)
+{
+  if (onemol->qflag && q_flag) q[ilocal] = onemol->q[iatom];
+  if (onemol->radiusflag && radius_flag) radius[ilocal] = onemol->radius[iatom];
+  if (onemol->rmassflag && rmass_flag) rmass[ilocal] = onemol->rmass[iatom];
+  if (onemol->replambdaHflag && replambdaH_flag) replambdaH[ilocal] = onemol->replambdaH[iatom];
+  if (onemol->moltypeHflag && moltypeH_flag) moltypeH[ilocal] = onemol->moltypeH[iatom];
+  else if (rmass_flag)
+    rmass[ilocal] = 4.0*MY_PI/3.0 *
+      radius[ilocal]*radius[ilocal]*radius[ilocal];
+  if (onemol->bodyflag) {
+    body[ilocal] = 0;     // as if a body read from data file
+    onemol->avec_body->data_body(ilocal,onemol->nibody,onemol->ndbody,
+				 onemol->ibodyparams,onemol->dbodyparams);
+    onemol->avec_body->set_quat(ilocal,onemol->quat_external);
+  }
+  
+  if (molecular != 1) return;
+
+  // add bond topology info
+  // for molecular atom styles, but not atom style template
+
+  if (avec->bonds_allow) {
+    num_bond[ilocal] = onemol->num_bond[iatom];
+    for (int i = 0; i < num_bond[ilocal]; i++) {
+      bond_type[ilocal][i] = onemol->bond_type[iatom][i];
+      bond_atom[ilocal][i] = onemol->bond_atom[iatom][i] + offset;
+    }
+  }
+
+  if (avec->angles_allow) {
+    num_angle[ilocal] = onemol->num_angle[iatom];
+    for (int i = 0; i < num_angle[ilocal]; i++) {
+      angle_type[ilocal][i] = onemol->angle_type[iatom][i];
+      angle_atom1[ilocal][i] = onemol->angle_atom1[iatom][i] + offset;
+      angle_atom2[ilocal][i] = onemol->angle_atom2[iatom][i] + offset;
+      angle_atom3[ilocal][i] = onemol->angle_atom3[iatom][i] + offset;
+    }
+  }
+
+  if (avec->dihedrals_allow) {
+    num_dihedral[ilocal] = onemol->num_dihedral[iatom];
+    for (int i = 0; i < num_dihedral[ilocal]; i++) {
+      dihedral_type[ilocal][i] = onemol->dihedral_type[iatom][i];
+      dihedral_atom1[ilocal][i] = onemol->dihedral_atom1[iatom][i] + offset;
+      dihedral_atom2[ilocal][i] = onemol->dihedral_atom2[iatom][i] + offset;
+      dihedral_atom3[ilocal][i] = onemol->dihedral_atom3[iatom][i] + offset;
+      dihedral_atom4[ilocal][i] = onemol->dihedral_atom4[iatom][i] + offset;
+    }
+  }
+
+  if (avec->impropers_allow) {
+    num_improper[ilocal] = onemol->num_improper[iatom];
+    for (int i = 0; i < num_improper[ilocal]; i++) {
+      improper_type[ilocal][i] = onemol->improper_type[iatom][i];
+      improper_atom1[ilocal][i] = onemol->improper_atom1[iatom][i] + offset;
+      improper_atom2[ilocal][i] = onemol->improper_atom2[iatom][i] + offset;
+      improper_atom3[ilocal][i] = onemol->improper_atom3[iatom][i] + offset;
+      improper_atom4[ilocal][i] = onemol->improper_atom4[iatom][i] + offset;
+    }
+  }
+
+  if (onemol->specialflag) {
+    nspecial[ilocal][0] = onemol->nspecial[iatom][0];
+    nspecial[ilocal][1] = onemol->nspecial[iatom][1];
+    int n = nspecial[ilocal][2] = onemol->nspecial[iatom][2];
+    for (int i = 0; i < n; i++)
+      special[ilocal][i] = onemol->special[iatom][i] + offset;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   reorder owned atoms so those in firstgroup appear first
+   called by comm->exchange() if atom_modify first group is set
+   only owned atoms exist at this point, no ghost atoms
+------------------------------------------------------------------------- */
+
+void Atom::first_reorder()
+{
+  // insure there is one extra atom location at end of arrays for swaps
+
+  if (nlocal == nmax) avec->grow(0);
+
+  // loop over owned atoms
+  // nfirst = index of first atom not in firstgroup
+  // when find firstgroup atom out of place, swap it with atom nfirst
+
+  int bitmask = group->bitmask[firstgroup];
+  nfirst = 0;
+  while (nfirst < nlocal && mask[nfirst] & bitmask) nfirst++;
+
+  for (int i = 0; i < nlocal; i++) {
+    if (mask[i] & bitmask && i > nfirst) {
+      avec->copy(i,nlocal,0);
+      avec->copy(nfirst,i,0);
+      avec->copy(nlocal,nfirst,0);
+      while (nfirst < nlocal && mask[nfirst] & bitmask) nfirst++;
+    }
+  }
+}
+
+/* ----------------------------------------------------------------------
+   perform spatial sort of atoms within my sub-domain
+   always called between comm->exchange() and comm->borders()
+   don't have to worry about clearing/setting atom->map since done in comm
+------------------------------------------------------------------------- */
+
+void Atom::sort()
+{
+  int i,m,n,ix,iy,iz,ibin,empty;
+
+  // set next timestep for sorting to take place
+
+  nextsort = (update->ntimestep/sortfreq)*sortfreq + sortfreq;
+
+  // download data from GPU if necessary
+
+  if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->downloadAll();
+
+  // re-setup sort bins if needed
+
+  if (domain->box_change) setup_sort_bins();
+  if (nbins == 1) return;
+
+  // reallocate per-atom vectors if needed
+
+  if (nlocal > maxnext) {
+    memory->destroy(next);
+    memory->destroy(permute);
+    maxnext = atom->nmax;
+    memory->create(next,maxnext,"atom:next");
+    memory->create(permute,maxnext,"atom:permute");
+  }
+
+  // insure there is one extra atom location at end of arrays for swaps
+
+  if (nlocal == nmax) avec->grow(0);
+
+  // bin atoms in reverse order so linked list will be in forward order
+
+  for (i = 0; i < nbins; i++) binhead[i] = -1;
+
+  for (i = nlocal-1; i >= 0; i--) {
+    ix = static_cast<int> ((x[i][0]-bboxlo[0])*bininvx);
+    iy = static_cast<int> ((x[i][1]-bboxlo[1])*bininvy);
+    iz = static_cast<int> ((x[i][2]-bboxlo[2])*bininvz);
+    ix = MAX(ix,0);
+    iy = MAX(iy,0);
+    iz = MAX(iz,0);
+    ix = MIN(ix,nbinx-1);
+    iy = MIN(iy,nbiny-1);
+    iz = MIN(iz,nbinz-1);
+    ibin = iz*nbiny*nbinx + iy*nbinx + ix;
+    next[i] = binhead[ibin];
+    binhead[ibin] = i;
+  }
+
+  // permute = desired permutation of atoms
+  // permute[I] = J means Ith new atom will be Jth old atom
+
+  n = 0;
+  for (m = 0; m < nbins; m++) {
+    i = binhead[m];
+    while (i >= 0) {
+      permute[n++] = i;
+      i = next[i];
+    }
+  }
+
+  // current = current permutation, just reuse next vector
+  // current[I] = J means Ith current atom is Jth old atom
+
+  int *current = next;
+  for (i = 0; i < nlocal; i++) current[i] = i;
+
+  // reorder local atom list, when done, current = permute
+  // perform "in place" using copy() to extra atom location at end of list
+  // inner while loop processes one cycle of the permutation
+  // copy before inner-loop moves an atom to end of atom list
+  // copy after inner-loop moves atom at end of list back into list
+  // empty = location in atom list that is currently empty
+
+  for (i = 0; i < nlocal; i++) {
+    if (current[i] == permute[i]) continue;
+    avec->copy(i,nlocal,0);
+    empty = i;
+    while (permute[empty] != i) {
+      avec->copy(permute[empty],empty,0);
+      empty = current[empty] = permute[empty];
+    }
+    avec->copy(nlocal,empty,0);
+    current[empty] = permute[empty];
+  }
+
+  // upload data back to GPU if necessary
+
+  if (lmp->cuda && !lmp->cuda->oncpu) lmp->cuda->uploadAll();
+
+  // sanity check that current = permute
+
+  //int flag = 0;
+  //for (i = 0; i < nlocal; i++)
+  //  if (current[i] != permute[i]) flag = 1;
+  //int flagall;
+  //MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  //if (flagall) error->all(FLERR,"Atom sort did not operate correctly");
+}
+
+/* ----------------------------------------------------------------------
+   setup bins for spatial sorting of atoms
+------------------------------------------------------------------------- */
+
+void Atom::setup_sort_bins()
+{
+  // binsize:
+  // user setting if explicitly set
+  // 1/2 of neighbor cutoff for non-CUDA
+  // CUDA_CHUNK atoms/proc for CUDA
+  // check if neighbor cutoff = 0.0
+
+  double binsize;
+  if (userbinsize > 0.0) binsize = userbinsize;
+  else if (!lmp->cuda) binsize = 0.5 * neighbor->cutneighmax;
+  else {
+    if (domain->dimension == 3) {
+      double vol = (domain->boxhi[0]-domain->boxlo[0]) *
+        (domain->boxhi[1]-domain->boxlo[1]) *
+        (domain->boxhi[2]-domain->boxlo[2]);
+      binsize = pow(1.0*CUDA_CHUNK/natoms*vol,1.0/3.0);
+    } else {
+      double area = (domain->boxhi[0]-domain->boxlo[0]) *
+        (domain->boxhi[1]-domain->boxlo[1]);
+      binsize = pow(1.0*CUDA_CHUNK/natoms*area,1.0/2.0);
+    }
+  }
+  if (binsize == 0.0) error->all(FLERR,"Atom sorting has bin size = 0.0");
+
+  double bininv = 1.0/binsize;
+
+  // nbin xyz = local bins
+  // bbox lo/hi = bounding box of my sub-domain
+
+  if (domain->triclinic)
+    domain->bbox(domain->sublo_lamda,domain->subhi_lamda,bboxlo,bboxhi);
+  else {
+    bboxlo[0] = domain->sublo[0];
+    bboxlo[1] = domain->sublo[1];
+    bboxlo[2] = domain->sublo[2];
+    bboxhi[0] = domain->subhi[0];
+    bboxhi[1] = domain->subhi[1];
+    bboxhi[2] = domain->subhi[2];
+  }
+
+  nbinx = static_cast<int> ((bboxhi[0]-bboxlo[0]) * bininv);
+  nbiny = static_cast<int> ((bboxhi[1]-bboxlo[1]) * bininv);
+  nbinz = static_cast<int> ((bboxhi[2]-bboxlo[2]) * bininv);
+  if (domain->dimension == 2) nbinz = 1;
+
+  if (nbinx == 0) nbinx = 1;
+  if (nbiny == 0) nbiny = 1;
+  if (nbinz == 0) nbinz = 1;
+
+  bininvx = nbinx / (bboxhi[0]-bboxlo[0]);
+  bininvy = nbiny / (bboxhi[1]-bboxlo[1]);
+  bininvz = nbinz / (bboxhi[2]-bboxlo[2]);
+
+  if (1.0*nbinx*nbiny*nbinz > INT_MAX)
+    error->one(FLERR,"Too many atom sorting bins");
+
+  nbins = nbinx*nbiny*nbinz;
+
+  // reallocate per-bin memory if needed
+
+  if (nbins > maxbin) {
+    memory->destroy(binhead);
+    maxbin = nbins;
+    memory->create(binhead,maxbin,"atom:binhead");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   register a callback to a fix so it can manage atom-based arrays
+   happens when fix is created
+   flag = 0 for grow, 1 for restart, 2 for border comm
+------------------------------------------------------------------------- */
+
+void Atom::add_callback(int flag)
+{
+  int ifix;
+
+  // find the fix
+  // if find NULL ptr:
+  //   it's this one, since it is being replaced and has just been deleted
+  //   at this point in re-creation
+  // if don't find NULL ptr:
+  //   i is set to nfix = new one currently being added at end of list
+
+  for (ifix = 0; ifix < modify->nfix; ifix++)
+    if (modify->fix[ifix] == NULL) break;
+
+  // add callback to lists, reallocating if necessary
+
+  if (flag == 0) {
+    if (nextra_grow == nextra_grow_max) {
+      nextra_grow_max += DELTA;
+      memory->grow(extra_grow,nextra_grow_max,"atom:extra_grow");
+    }
+    extra_grow[nextra_grow] = ifix;
+    nextra_grow++;
+  } else if (flag == 1) {
+    if (nextra_restart == nextra_restart_max) {
+      nextra_restart_max += DELTA;
+      memory->grow(extra_restart,nextra_restart_max,"atom:extra_restart");
+    }
+    extra_restart[nextra_restart] = ifix;
+    nextra_restart++;
+  } else if (flag == 2) {
+    if (nextra_border == nextra_border_max) {
+      nextra_border_max += DELTA;
+      memory->grow(extra_border,nextra_border_max,"atom:extra_border");
+    }
+    extra_border[nextra_border] = ifix;
+    nextra_border++;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   unregister a callback to a fix
+   happens when fix is deleted, called by its destructor
+   flag = 0 for grow, 1 for restart
+------------------------------------------------------------------------- */
+
+void Atom::delete_callback(const char *id, int flag)
+{
+  int ifix;
+  for (ifix = 0; ifix < modify->nfix; ifix++)
+    if (strcmp(id,modify->fix[ifix]->id) == 0) break;
+
+  // compact the list of callbacks
+
+  if (flag == 0) {
+    int match;
+    for (match = 0; match < nextra_grow; match++)
+      if (extra_grow[match] == ifix) break;
+    for (int i = match; i < nextra_grow-1; i++)
+      extra_grow[i] = extra_grow[i+1];
+    nextra_grow--;
+
+  } else if (flag == 1) {
+    int match;
+    for (match = 0; match < nextra_restart; match++)
+      if (extra_restart[match] == ifix) break;
+    for (int i = match; i < nextra_restart-1; i++)
+      extra_restart[i] = extra_restart[i+1];
+    nextra_restart--;
+
+  } else if (flag == 2) {
+    int match;
+    for (match = 0; match < nextra_border; match++)
+      if (extra_border[match] == ifix) break;
+    for (int i = match; i < nextra_border-1; i++)
+      extra_border[i] = extra_border[i+1];
+    nextra_border--;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   decrement ptrs in callback lists to fixes beyond the deleted ifix
+   happens after fix is deleted
+------------------------------------------------------------------------- */
+
+void Atom::update_callback(int ifix)
+{
+  for (int i = 0; i < nextra_grow; i++)
+    if (extra_grow[i] > ifix) extra_grow[i]--;
+  for (int i = 0; i < nextra_restart; i++)
+    if (extra_restart[i] > ifix) extra_restart[i]--;
+  for (int i = 0; i < nextra_border; i++)
+    if (extra_border[i] > ifix) extra_border[i]--;
+}
+
+/* ----------------------------------------------------------------------
+   find custom per-atom vector with name
+   return index if found, and flag = 0/1 for int/double
+   return -1 if not found
+------------------------------------------------------------------------- */
+
+int Atom::find_custom(char *name, int &flag)
+{
+  for (int i = 0; i < nivector; i++)
+    if (iname[i] && strcmp(iname[i],name) == 0) {
+      flag = 0;
+      return i;
+    }
+
+  for (int i = 0; i < ndvector; i++)
+    if (dname[i] && strcmp(dname[i],name) == 0) {
+      flag = 1;
+      return i;
+    }
+
+  return -1;
+}
+
+/* ----------------------------------------------------------------------
+   add a custom variable with name of type flag = 0/1 for int/double
+   assumes name does not already exist
+   return index in ivector or dvector of its location
+------------------------------------------------------------------------- */
+
+int Atom::add_custom(char *name, int flag)
+{
+  int index;
+
+  if (flag == 0) {
+    index = nivector;
+    nivector++;
+    iname = (char **) memory->srealloc(iname,nivector*sizeof(char *),
+                                       "atom:iname");
+    int n = strlen(name) + 1;
+    iname[index] = new char[n];
+    strcpy(iname[index],name);
+    ivector = (int **) memory->srealloc(ivector,nivector*sizeof(int *),
+                                        "atom:ivector");
+    memory->create(ivector[index],nmax,"atom:ivector");
+  } else {
+    index = ndvector;
+    ndvector++;
+    dname = (char **) memory->srealloc(dname,ndvector*sizeof(char *),
+                                       "atom:dname");
+    int n = strlen(name) + 1;
+    dname[index] = new char[n];
+    strcpy(dname[index],name);
+    dvector = (double **) memory->srealloc(dvector,ndvector*sizeof(double *),
+                                           "atom:dvector");
+    memory->create(dvector[index],nmax,"atom:dvector");
+  }
+
+  return index;
+}
+
+/* ----------------------------------------------------------------------
+   remove a custom variable of type flag = 0/1 for int/double at index
+   free memory for vector and name and set ptrs to NULL
+   ivector/dvector and iname/dname lists never shrink
+------------------------------------------------------------------------- */
+
+void Atom::remove_custom(int flag, int index)
+{
+  if (flag == 0) {
+    memory->destroy(ivector[index]);
+    ivector[index] = NULL;
+    delete [] iname[index];
+    iname[index] = NULL;
+  } else {
+    memory->destroy(dvector[index]);
+    dvector[index] = NULL;
+    delete [] dname[index];
+    dname[index] = NULL;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   return a pointer to a named internal variable
+   if don't recognize name, return NULL
+   customize by adding names
+------------------------------------------------------------------------- */
+
+void *Atom::extract(char *name)
+{
+  if (strcmp(name,"mass") == 0) return (void *) mass;
+
+  if (strcmp(name,"id") == 0) return (void *) tag;
+  if (strcmp(name,"type") == 0) return (void *) type;
+  if (strcmp(name,"mask") == 0) return (void *) mask;
+  if (strcmp(name,"image") == 0) return (void *) image;
+  if (strcmp(name,"x") == 0) return (void *) x;
+  if (strcmp(name,"v") == 0) return (void *) v;
+  if (strcmp(name,"f") == 0) return (void *) f;
+  if (strcmp(name,"molecule") == 0) return (void *) molecule;
+  if (strcmp(name,"q") == 0) return (void *) q;
+  if (strcmp(name,"lambdaH") == 0) return (void *) lambdaH;
+  if (strcmp(name,"gradlambdaH") == 0) return (void *) gradlambdaH;
+  if (strcmp(name,"replambdaH") == 0) return (void *) replambdaH;
+  if (strcmp(name,"mu") == 0) return (void *) mu;
+  if (strcmp(name,"omega") == 0) return (void *) omega;
+  if (strcmp(name,"angmom") == 0) return (void *) angmom;
+  if (strcmp(name,"torque") == 0) return (void *) torque;
+  if (strcmp(name,"radius") == 0) return (void *) radius;
+  if (strcmp(name,"rmass") == 0) return (void *) rmass;
+  if (strcmp(name,"ellipsoid") == 0) return (void *) ellipsoid;
+  if (strcmp(name,"line") == 0) return (void *) line;
+  if (strcmp(name,"tri") == 0) return (void *) tri;
+
+  if (strcmp(name,"vfrac") == 0) return (void *) vfrac;
+  if (strcmp(name,"s0") == 0) return (void *) s0;
+  if (strcmp(name,"x0") == 0) return (void *) x0;
+
+  if (strcmp(name,"spin") == 0) return (void *) spin;
+  if (strcmp(name,"eradius") == 0) return (void *) eradius;
+  if (strcmp(name,"ervel") == 0) return (void *) ervel;
+  if (strcmp(name,"erforce") == 0) return (void *) erforce;
+  if (strcmp(name,"ervelforce") == 0) return (void *) ervelforce;
+  if (strcmp(name,"cs") == 0) return (void *) cs;
+  if (strcmp(name,"csforce") == 0) return (void *) csforce;
+  if (strcmp(name,"vforce") == 0) return (void *) vforce;
+  if (strcmp(name,"etag") == 0) return (void *) etag;
+
+  if (strcmp(name,"rho") == 0) return (void *) rho;
+  if (strcmp(name,"drho") == 0) return (void *) drho;
+  if (strcmp(name,"e") == 0) return (void *) e;
+  if (strcmp(name,"de") == 0) return (void *) de;
+  if (strcmp(name,"cv") == 0) return (void *) cv;
+  if (strcmp(name,"vest") == 0) return (void *) vest;
+
+  if (strcmp(name, "contact_radius") == 0) return (void *) contact_radius;
+  if (strcmp(name, "smd_data_9") == 0) return (void *) smd_data_9;
+  if (strcmp(name, "smd_stress") == 0) return (void *) smd_stress;
+  if (strcmp(name, "eff_plastic_strain") == 0)
+    return (void *) eff_plastic_strain;
+  if (strcmp(name, "eff_plastic_strain_rate") == 0)
+    return (void *) eff_plastic_strain_rate;
+  if (strcmp(name, "damage") == 0) return (void *) damage;
+
+  if (strcmp(name,"dpdTheta") == 0) return (void *) dpdTheta;
+
+  return NULL;
+}
+
+/* ----------------------------------------------------------------------
+   return # of bytes of allocated memory
+   call to avec tallies per-atom vectors
+   add in global to local mapping storage
+------------------------------------------------------------------------- */
+
+bigint Atom::memory_usage()
+{
+  memlength = DELTA_MEMSTR;
+  memory->create(memstr,memlength,"atom:memstr");
+  memstr[0] = '\0';
+  bigint bytes = avec->memory_usage();
+  memory->destroy(memstr);
+
+  bytes += max_same*sizeof(int);
+  if (map_style == 1 && map_tag_max >= 0)
+    bytes += memory->usage(map_array,map_maxarray);
+  else if (map_style == 2 && map_nhash >=0) {
+    bytes += map_nbucket*sizeof(int);
+    bytes += map_nhash*sizeof(HashElem);
+  }
+  if (maxnext) {
+    bytes += memory->usage(next,maxnext);
+    bytes += memory->usage(permute,maxnext);
+  }
+
+  return bytes;
+}
+
+/* ----------------------------------------------------------------------
+   accumulate per-atom vec names in memstr, padded by spaces
+   return 1 if padded str is not already in memlist, else 0
+------------------------------------------------------------------------- */
+
+int Atom::memcheck(const char *str)
+{
+  int n = strlen(str) + 3;
+  char *padded = new char[n];
+  strcpy(padded," ");
+  strcat(padded,str);
+  strcat(padded," ");
+
+  if (strstr(memstr,padded)) {
+    delete [] padded;
+    return 0;
+  }
+
+  if (strlen(memstr) + n >= memlength) {
+    memlength += DELTA_MEMSTR;
+    memory->grow(memstr,memlength,"atom:memstr");
+  }
+
+  strcat(memstr,padded);
+  delete [] padded;
+  return 1;
+}
diff --git a/src/USER-HADRESS/atom.h b/src/USER-HADRESS/atom.h
new file mode 100644
index 000000000..1675e7fe2
--- /dev/null
+++ b/src/USER-HADRESS/atom.h
@@ -0,0 +1,519 @@
+/* -*- 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_ATOM_H
+#define LMP_ATOM_H
+
+#include "pointers.h"
+
+namespace LAMMPS_NS {
+
+class Atom : protected Pointers {
+ public:
+  char *atom_style;
+  class AtomVec *avec;
+
+  // atom counts
+
+  bigint natoms;                // total # of atoms in system, could be 0
+                                // natoms may not be current if atoms lost
+  int nlocal,nghost;            // # of owned and ghost atoms on this proc
+  int nmax;                     // max # of owned+ghost in arrays on this proc
+  int tag_enable;               // 0/1 if atom ID tags are defined
+  int molecular;                // 0 = atomic, 1 = standard molecular system,
+                                // 2 = molecule template system
+
+  bigint nbonds,nangles,ndihedrals,nimpropers;
+  int ntypes,nbondtypes,nangletypes,ndihedraltypes,nimpropertypes;
+  int bond_per_atom,angle_per_atom,dihedral_per_atom,improper_per_atom;
+  int extra_bond_per_atom,extra_angle_per_atom;
+  int extra_dihedral_per_atom,extra_improper_per_atom;
+
+  int firstgroup;               // store atoms in this group first, -1 if unset
+  int nfirst;                   // # of atoms in first group on this proc
+  char *firstgroupname;         // group-ID to store first, NULL if unset
+
+  // per-atom arrays
+  // customize by adding new array
+
+  tagint *tag;
+  int *type,*mask;
+  imageint *image;
+  double **x,**v,**f;
+
+  tagint *molecule;
+  int *molindex,*molatom;
+
+  double *q,**mu;
+  double *lambdaH,**gradlambdaH;
+  int *replambdaH;
+  int *moltypeH;
+  int nmoltypesH;
+  double **comH;
+
+  double **omega,**angmom,**torque;
+  double *radius,*rmass;
+  int *ellipsoid,*line,*tri,*body;
+
+  // PERI package
+
+  double *vfrac,*s0;
+  double **x0;
+
+  // USER-EFF and USER-AWPMD packages
+
+  int *spin;
+  double *eradius,*ervel,*erforce,*ervelforce;
+  double *cs,*csforce,*vforce;
+  int *etag;
+
+  // USER-SPH package
+
+  double *rho,*drho,*e,*de,*cv;
+  double **vest;
+
+  // USER-SMD package
+
+  double *contact_radius;
+  double **smd_data_9;
+  double **smd_stress;
+  double *eff_plastic_strain;
+  double *eff_plastic_strain_rate;
+  double *damage;
+
+  // USER-DPD package
+
+  double *uCond, *uMech, *uChem, *uCGnew, *uCG;
+  double *duCond, *duMech, *duChem;
+  double *dpdTheta;
+
+  // molecular info
+
+  int **nspecial;               // 0,1,2 = cummulative # of 1-2,1-3,1-4 neighs
+  tagint **special;             // IDs of 1-2,1-3,1-4 neighs of each atom
+  int maxspecial;               // special[nlocal][maxspecial]
+
+  int *num_bond;
+  int **bond_type;
+  tagint **bond_atom;
+
+  int *num_angle;
+  int **angle_type;
+  tagint **angle_atom1,**angle_atom2,**angle_atom3;
+
+  int *num_dihedral;
+  int **dihedral_type;
+  tagint **dihedral_atom1,**dihedral_atom2,**dihedral_atom3,**dihedral_atom4;
+
+  int *num_improper;
+  int **improper_type;
+  tagint **improper_atom1,**improper_atom2,**improper_atom3,**improper_atom4;
+
+  // custom arrays used by fix property/atom
+
+  int **ivector;
+  double **dvector;
+  char **iname,**dname;
+  int nivector,ndvector;
+
+  // used by USER-CUDA to flag used per-atom arrays
+
+  unsigned int datamask;
+  unsigned int datamask_ext;
+
+  // atom style and per-atom array existence flags
+  // customize by adding new flag
+
+  int sphere_flag,ellipsoid_flag,line_flag,tri_flag,body_flag;
+  int peri_flag,electron_flag;
+  int ecp_flag;
+  int wavepacket_flag,sph_flag;
+
+  int molecule_flag,molindex_flag,molatom_flag;
+  int q_flag,mu_flag;
+  int replambdaH_flag, moltypeH_flag;
+  int rmass_flag,radius_flag,omega_flag,torque_flag,angmom_flag;
+  int vfrac_flag,spin_flag,eradius_flag,ervel_flag,erforce_flag;
+  int cs_flag,csforce_flag,vforce_flag,ervelforce_flag,etag_flag;
+  int rho_flag,e_flag,cv_flag,vest_flag;
+  int dpd_flag;
+
+  // USER-SMD package
+
+  int smd_flag;
+  int contact_radius_flag;
+  int smd_data_9_flag;
+  int smd_stress_flag;
+  int x0_flag;
+  int eff_plastic_strain_flag;
+  int eff_plastic_strain_rate_flag;
+  int damage_flag;
+
+  // Peridynamics scale factor, used by dump cfg
+
+  double pdscale;
+
+  // molecule templates
+  // each template can be a set of consecutive molecules
+  // each with same ID (stored in molecules)
+  // 1st molecule in template stores nset = # in set
+
+  int nmolecule;
+  class Molecule **molecules;
+
+  // extra peratom info in restart file destined for fix & diag
+
+  double **extra;
+
+  // per-type arrays
+
+  double *mass;
+  int *mass_setflag;
+
+  // callback ptrs for atom arrays managed by fix classes
+
+  int nextra_grow,nextra_restart,nextra_border;  // # of callbacks of each type
+  int *extra_grow,*extra_restart,*extra_border;  // index of fix to callback to
+  int nextra_grow_max,nextra_restart_max;        // size of callback lists
+  int nextra_border_max;
+  int nextra_store;
+
+  int map_style;                  // style of atom map: 0=none, 1=array, 2=hash
+  int map_user;                   // user selected style = same 0,1,2
+  tagint map_tag_max;             // max atom ID that map() is setup for
+
+  // spatial sorting of atoms
+
+  int sortfreq;             // sort atoms every this many steps, 0 = off
+  bigint nextsort;          // next timestep to sort on
+  double userbinsize;       // requested sort bin size
+
+  // indices of atoms with same ID
+
+  int *sametag;      // sametag[I] = next atom with same ID, -1 if no more
+
+  // functions
+
+  Atom(class LAMMPS *);
+  ~Atom();
+
+  void settings(class Atom *);
+  void create_avec(const char *, int, char **, int);
+  virtual class AtomVec *new_avec(const char *, int, int &);
+  void init();
+  void setup();
+
+  class AtomVec *style_match(const char *);
+  void modify_params(int, char **);
+  void tag_check();
+  void tag_extend();
+  int tag_consecutive();
+
+  int parse_data(const char *);
+  int count_words(const char *);
+  int count_words(const char *, char *);
+
+  void deallocate_topology();
+
+  void data_atoms(int, char *, tagint, int, int, double *);
+  void data_vels(int, char *, tagint);
+
+  void data_bonds(int, char *, int *, tagint, int);
+  void data_angles(int, char *, int *, tagint, int);
+  void data_dihedrals(int, char *, int *, tagint, int);
+  void data_impropers(int, char *, int *, tagint, int);
+
+  void data_bonus(int, char *, class AtomVec *, tagint);
+  void data_bodies(int, char *, class AtomVecBody *, tagint);
+
+  virtual void allocate_type_arrays();
+  void set_mass(const char *, int);
+  void set_mass(int, double);
+  void set_mass(int, char **);
+  void set_mass(double *);
+  void check_mass();
+
+  int radius_consistency(int, double &);
+  int shape_consistency(int, double &, double &, double &);
+
+  void add_molecule(int, char **);
+  int find_molecule(char *);
+  void add_molecule_atom(class Molecule *, int, int, tagint);
+
+  void first_reorder();
+  virtual void sort();
+
+  void add_callback(int);
+  void delete_callback(const char *, int);
+  void update_callback(int);
+
+  int find_custom(char *, int &);
+  int add_custom(char *, int);
+  void remove_custom(int, int);
+
+  virtual void sync_modify(ExecutionSpace, unsigned int, unsigned int) {}
+
+  void *extract(char *);
+
+  inline int* get_map_array() {return map_array;};
+  inline int get_map_size() {return map_tag_max+1;};
+
+  bigint memory_usage();
+  int memcheck(const char *);
+
+  // functions for global to local ID mapping
+  // map lookup function inlined for efficiency
+  // return -1 if no map defined
+
+  inline int map(tagint global) {
+    if (map_style == 1) return map_array[global];
+    else if (map_style == 2) return map_find_hash(global);
+    else return -1;
+  };
+
+  void map_init(int check = 1);
+  void map_clear();
+  void map_set();
+  void map_one(tagint, int);
+  int map_style_set();
+  void map_delete();
+  int map_find_hash(tagint);
+
+ protected:
+
+  // global to local ID mapping
+
+  int *map_array;       // direct map via array that holds map_tag_max
+  int map_maxarray;     // allocated size of map_array (1 larger than this)
+
+  struct HashElem {     // hashed map
+    tagint global;      // key to search on = global ID
+    int local;          // value associated with key = local index
+    int next;           // next entry in this bucket, -1 if last
+  };
+  int map_nhash;        // # of entries hash table can hold
+  int map_nused;        // # of actual entries in hash table
+  int map_free;         // ptr to 1st unused entry in hash table
+  int map_nbucket;      // # of hash buckets
+  int *map_bucket;      // ptr to 1st entry in each bucket
+  HashElem *map_hash;   // hash table
+
+  int max_same;         // allocated size of sametag
+
+  // spatial sorting of atoms
+
+  int nbins;                      // # of sorting bins
+  int nbinx,nbiny,nbinz;          // bins in each dimension
+  int maxbin;                     // max # of bins
+  int maxnext;                    // max size of next,permute
+  int *binhead;                   // 1st atom in each bin
+  int *next;                      // next atom in bin
+  int *permute;                   // permutation vector
+  double bininvx,bininvy,bininvz; // inverse actual bin sizes
+  double bboxlo[3],bboxhi[3];     // bounding box of my sub-domain
+
+  int memlength;                  // allocated size of memstr
+  char *memstr;                   // string of array names already counted
+
+  void setup_sort_bins();
+  int next_prime(int);
+};
+
+}
+
+#endif
+
+/* ERROR/WARNING messages:
+
+E: Atom IDs must be used for molecular systems
+
+Atom IDs are used to identify and find partner atoms in bonds.
+
+E: Unknown atom style
+
+The choice of atom style is unknown.
+
+E: Could not find atom_modify first group ID
+
+Self-explanatory.
+
+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: Atom_modify id command after simulation box is defined
+
+The atom_modify id command cannot be used after a read_data,
+read_restart, or create_box command.
+
+E: Atom_modify map command after simulation box is defined
+
+The atom_modify map command cannot be used after a read_data,
+read_restart, or create_box command.
+
+E: Atom_modify sort and first options cannot be used together
+
+Self-explanatory.
+
+E: One or more Atom IDs is negative
+
+Atom IDs must be positive integers.
+
+E: One or more atom IDs is too big
+
+The limit on atom IDs is set by the SMALLBIG, BIGBIG, SMALLSMALL
+setting in your Makefile.  See Section_start 2.2 of the manual for
+more details.
+
+E: One or more atom IDs is zero
+
+Either all atoms IDs must be zero or none of them.
+
+E: Non-zero atom IDs with atom_modify id = no
+
+Self-explanatory.
+
+E: All atom IDs = 0 but atom_modify id = yes
+
+Self-explanatory.
+
+E: Duplicate atom IDs exist
+
+Self-explanatory.
+
+E: New atom IDs exceed maximum allowed ID
+
+See the setting for tagint in the src/lmptype.h file.
+
+E: Incorrect atom format in data file
+
+Number of values per atom line in the data file is not consistent with
+the atom style.
+
+E: Invalid atom type in Atoms section of data file
+
+Atom types must range from 1 to specified # of types.
+
+E: Incorrect velocity format in data file
+
+Each atom style defines a format for the Velocity section
+of the data file.  The read-in lines do not match.
+
+E: Invalid atom ID in Velocities section of data file
+
+Atom IDs must be positive integers and within range of defined
+atoms.
+
+E: Invalid atom ID in Bonds section of data file
+
+Atom IDs must be positive integers and within range of defined
+atoms.
+
+E: Invalid bond type in Bonds section of data file
+
+Bond type must be positive integer and within range of specified bond
+types.
+
+E: Invalid atom ID in Angles section of data file
+
+Atom IDs must be positive integers and within range of defined
+atoms.
+
+E: Invalid angle type in Angles section of data file
+
+Angle type must be positive integer and within range of specified angle
+types.
+
+E: Invalid atom ID in Dihedrals section of data file
+
+Atom IDs must be positive integers and within range of defined
+atoms.
+
+E: Invalid dihedral type in Dihedrals section of data file
+
+Dihedral type must be positive integer and within range of specified
+dihedral types.
+
+E: Invalid atom ID in Impropers section of data file
+
+Atom IDs must be positive integers and within range of defined
+atoms.
+
+E: Invalid improper type in Impropers section of data file
+
+Improper type must be positive integer and within range of specified
+improper types.
+
+E: Incorrect bonus data format in data file
+
+See the read_data doc page for a description of how various kinds of
+bonus data must be formatted for certain atom styles.
+
+E: Invalid atom ID in Bonus section of data file
+
+Atom IDs must be positive integers and within range of defined
+atoms.
+
+E: Invalid atom ID in Bodies section of data file
+
+Atom IDs must be positive integers and within range of defined
+atoms.
+
+E: Cannot set mass for this atom style
+
+This atom style does not support mass settings for each atom type.
+Instead they are defined on a per-atom basis in the data file.
+
+E: Invalid mass line in data file
+
+Self-explanatory.
+
+E: Invalid type for mass set
+
+Mass command must set a type from 1-N where N is the number of atom
+types.
+
+E: Invalid mass value
+
+Self-explanatory.
+
+E: All masses are not set
+
+For atom styles that define masses for each atom type, all masses must
+be set in the data file or by the mass command before running a
+simulation.  They must also be set before using the velocity
+command.
+
+E: Reuse of molecule template ID
+
+The template IDs must be unique.
+
+E: Atom sort did not operate correctly
+
+This is an internal LAMMPS error.  Please report it to the
+developers.
+
+E: Atom sorting has bin size = 0.0
+
+The neighbor cutoff is being used as the bin size, but it is zero.
+Thus you must explicitly list a bin size in the atom_modify sort
+command or turn off sorting.
+
+E: Too many atom sorting bins
+
+This is likely due to an immense simulation box that has blown up
+to a large size.
+
+*/
diff --git a/src/USER-HADRESS/atom_vec_full_hars.cpp b/src/USER-HADRESS/atom_vec_full_hars.cpp
new file mode 100644
index 000000000..fe01c0fa9
--- /dev/null
+++ b/src/USER-HADRESS/atom_vec_full_hars.cpp
@@ -0,0 +1,1352 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain rights in this software.  This software is distributed under
+   the GNU General Public License.
+
+   See the README file in the top-level LAMMPS directory.
+------------------------------------------------------------------------- */
+
+#include "stdlib.h"
+#include "atom_vec_full_hars.h"
+#include "atom.h"
+#include "comm.h"
+#include "domain.h"
+#include "modify.h"
+#include "fix.h"
+#include "memory.h"
+#include "error.h"
+
+using namespace LAMMPS_NS;
+
+/* ---------------------------------------------------------------------- */
+
+AtomVecFullHars::AtomVecFullHars(LAMMPS *lmp) : AtomVec(lmp)
+{
+  molecular = 1;
+  bonds_allow = angles_allow = dihedrals_allow = impropers_allow = 1;
+  mass_type = 1;
+
+  comm_x_only = comm_f_only = 0;
+  size_forward = 10;
+  size_reverse = 3;
+  size_border = 17;
+  size_velocity = 3;
+  size_data_atom = 9;
+  size_data_vel = 4;
+  xcol_data = 7;
+
+  atom->molecule_flag = atom->q_flag = 1;
+  atom->replambdaH_flag = 1;
+  atom->moltypeH_flag = 1;
+
+}
+
+/* ----------------------------------------------------------------------
+   grow atom arrays
+   n = 0 grows arrays by a chunk
+   n > 0 allocates arrays to size n
+------------------------------------------------------------------------- */
+
+void AtomVecFullHars::grow(int n)
+{
+  if (n == 0) grow_nmax();
+  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,3,"atom:x");
+  v = memory->grow(atom->v,nmax,3,"atom:v");
+  f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
+
+  q = memory->grow(atom->q,nmax,"atom:q");
+  lambdaH = memory->grow(atom->lambdaH,nmax,"atom:lambdaH");
+  gradlambdaH = memory->grow(atom->gradlambdaH,nmax,3,"atom:gradlambdaH");
+  replambdaH = memory->grow(atom->replambdaH,nmax,"atom:replambdaH");
+  moltypeH = memory->grow(atom->moltypeH,nmax,"atom:moltypeH");
+  comH = memory->grow(atom->comH,nmax,3,"atom:comH");
+
+  molecule = memory->grow(atom->molecule,nmax,"atom:molecule");
+
+  nspecial = memory->grow(atom->nspecial,nmax,3,"atom:nspecial");
+  special = memory->grow(atom->special,nmax,atom->maxspecial,"atom:special");
+
+  num_bond = memory->grow(atom->num_bond,nmax,"atom:num_bond");
+  bond_type = memory->grow(atom->bond_type,nmax,atom->bond_per_atom,
+                           "atom:bond_type");
+  bond_atom = memory->grow(atom->bond_atom,nmax,atom->bond_per_atom,
+                           "atom:bond_atom");
+
+  num_angle = memory->grow(atom->num_angle,nmax,"atom:num_angle");
+  angle_type = memory->grow(atom->angle_type,nmax,atom->angle_per_atom,
+                            "atom:angle_type");
+  angle_atom1 = memory->grow(atom->angle_atom1,nmax,atom->angle_per_atom,
+                             "atom:angle_atom1");
+  angle_atom2 = memory->grow(atom->angle_atom2,nmax,atom->angle_per_atom,
+                             "atom:angle_atom2");
+  angle_atom3 = memory->grow(atom->angle_atom3,nmax,atom->angle_per_atom,
+                             "atom:angle_atom3");
+
+  num_dihedral = memory->grow(atom->num_dihedral,nmax,"atom:num_dihedral");
+  dihedral_type = memory->grow(atom->dihedral_type,nmax,
+                               atom->dihedral_per_atom,"atom:dihedral_type");
+  dihedral_atom1 =
+    memory->grow(atom->dihedral_atom1,nmax,atom->dihedral_per_atom,
+                 "atom:dihedral_atom1");
+  dihedral_atom2 =
+    memory->grow(atom->dihedral_atom2,nmax,atom->dihedral_per_atom,
+                 "atom:dihedral_atom2");
+  dihedral_atom3 =
+    memory->grow(atom->dihedral_atom3,nmax,atom->dihedral_per_atom,
+                 "atom:dihedral_atom3");
+  dihedral_atom4 =
+    memory->grow(atom->dihedral_atom4,nmax,atom->dihedral_per_atom,
+                 "atom:dihedral_atom4");
+
+  num_improper = memory->grow(atom->num_improper,nmax,"atom:num_improper");
+  improper_type =
+    memory->grow(atom->improper_type,nmax,atom->improper_per_atom,
+                 "atom:improper_type");
+  improper_atom1 =
+    memory->grow(atom->improper_atom1,nmax,atom->improper_per_atom,
+                 "atom:improper_atom1");
+  improper_atom2 =
+    memory->grow(atom->improper_atom2,nmax,atom->improper_per_atom,
+                 "atom:improper_atom2");
+  improper_atom3 =
+    memory->grow(atom->improper_atom3,nmax,atom->improper_per_atom,
+                 "atom:improper_atom3");
+  improper_atom4 =
+    memory->grow(atom->improper_atom4,nmax,atom->improper_per_atom,
+                 "atom:improper_atom4");
+
+  if (atom->nextra_grow)
+    for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
+      modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
+}
+
+/* ----------------------------------------------------------------------
+   reset local array ptrs
+------------------------------------------------------------------------- */
+
+void AtomVecFullHars::grow_reset()
+{
+  tag = atom->tag; type = atom->type;
+  mask = atom->mask; image = atom->image;
+  x = atom->x; v = atom->v; f = atom->f; comH = atom->comH;
+  q = atom->q; lambdaH = atom->lambdaH;gradlambdaH = atom->gradlambdaH;
+  replambdaH = atom->replambdaH;moltypeH = atom->moltypeH;molecule = atom->molecule;
+  nspecial = atom->nspecial; special = atom->special;
+  num_bond = atom->num_bond; bond_type = atom->bond_type;
+  bond_atom = atom->bond_atom;
+  num_angle = atom->num_angle; angle_type = atom->angle_type;
+  angle_atom1 = atom->angle_atom1; angle_atom2 = atom->angle_atom2;
+  angle_atom3 = atom->angle_atom3;
+  num_dihedral = atom->num_dihedral; dihedral_type = atom->dihedral_type;
+  dihedral_atom1 = atom->dihedral_atom1; dihedral_atom2 = atom->dihedral_atom2;
+  dihedral_atom3 = atom->dihedral_atom3; dihedral_atom4 = atom->dihedral_atom4;
+  num_improper = atom->num_improper; improper_type = atom->improper_type;
+  improper_atom1 = atom->improper_atom1; improper_atom2 = atom->improper_atom2;
+  improper_atom3 = atom->improper_atom3; improper_atom4 = atom->improper_atom4;
+}
+
+/* ----------------------------------------------------------------------
+   copy atom I info to atom J
+------------------------------------------------------------------------- */
+
+void AtomVecFullHars::copy(int i, int j, int delflag)
+{
+  int k;
+
+  tag[j] = tag[i];
+  type[j] = type[i];
+  mask[j] = mask[i];
+  image[j] = image[i];
+  x[j][0] = x[i][0];
+  x[j][1] = x[i][1];
+  x[j][2] = x[i][2];
+  v[j][0] = v[i][0];
+  v[j][1] = v[i][1];
+  v[j][2] = v[i][2];
+
+  comH[j][0] = comH[i][0];
+  comH[j][1] = comH[i][1];
+  comH[j][2] = comH[i][2];
+
+  q[j] = q[i];
+  lambdaH[j] = lambdaH[i];
+  gradlambdaH[j][0] = gradlambdaH[i][0];
+  gradlambdaH[j][1] = gradlambdaH[i][1];
+  gradlambdaH[j][2] = gradlambdaH[i][2];
+  replambdaH[j] = replambdaH[i];
+  moltypeH[j] = moltypeH[i];
+  molecule[j] = molecule[i];
+
+
+  num_bond[j] = num_bond[i];
+  for (k = 0; k < num_bond[j]; k++) {
+    bond_type[j][k] = bond_type[i][k];
+    bond_atom[j][k] = bond_atom[i][k];
+  }
+
+  num_angle[j] = num_angle[i];
+  for (k = 0; k < num_angle[j]; k++) {
+    angle_type[j][k] = angle_type[i][k];
+    angle_atom1[j][k] = angle_atom1[i][k];
+    angle_atom2[j][k] = angle_atom2[i][k];
+    angle_atom3[j][k] = angle_atom3[i][k];
+  }
+
+  num_dihedral[j] = num_dihedral[i];
+  for (k = 0; k < num_dihedral[j]; k++) {
+    dihedral_type[j][k] = dihedral_type[i][k];
+    dihedral_atom1[j][k] = dihedral_atom1[i][k];
+    dihedral_atom2[j][k] = dihedral_atom2[i][k];
+    dihedral_atom3[j][k] = dihedral_atom3[i][k];
+    dihedral_atom4[j][k] = dihedral_atom4[i][k];
+  }
+
+  num_improper[j] = num_improper[i];
+  for (k = 0; k < num_improper[j]; k++) {
+    improper_type[j][k] = improper_type[i][k];
+    improper_atom1[j][k] = improper_atom1[i][k];
+    improper_atom2[j][k] = improper_atom2[i][k];
+    improper_atom3[j][k] = improper_atom3[i][k];
+    improper_atom4[j][k] = improper_atom4[i][k];
+  }
+
+  nspecial[j][0] = nspecial[i][0];
+  nspecial[j][1] = nspecial[i][1];
+  nspecial[j][2] = nspecial[i][2];
+  for (k = 0; k < nspecial[j][2]; k++) special[j][k] = special[i][k];
+
+  if (atom->nextra_grow)
+    for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
+      modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j,delflag);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int AtomVecFullHars::pack_comm(int n, int *list, double *buf,
+                           int pbc_flag, int *pbc)
+{
+  int i,j,m;
+  double dx,dy,dz;
+
+  m = 0;
+  if (pbc_flag == 0) {
+    for (i = 0; i < n; i++) {
+      j = list[i];
+      buf[m++] = x[j][0];
+      buf[m++] = x[j][1];
+      buf[m++] = x[j][2];
+      buf[m++] = lambdaH[j];
+      buf[m++] = gradlambdaH[j][0];
+      buf[m++] = gradlambdaH[j][1];
+      buf[m++] = gradlambdaH[j][2];
+      buf[m++] = comH[j][0];
+      buf[m++] = comH[j][1];
+      buf[m++] = comH[j][2];
+
+    }
+  } else {
+    if (domain->triclinic == 0) {
+      dx = pbc[0]*domain->xprd;
+      dy = pbc[1]*domain->yprd;
+      dz = pbc[2]*domain->zprd;
+    } else {
+      dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
+      dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
+      dz = pbc[2]*domain->zprd;
+    }
+    for (i = 0; i < n; i++) {
+      j = list[i];
+      buf[m++] = x[j][0] + dx;
+      buf[m++] = x[j][1] + dy;
+      buf[m++] = x[j][2] + dz;
+      buf[m++] = lambdaH[j];
+      buf[m++] = gradlambdaH[j][0];
+      buf[m++] = gradlambdaH[j][1];
+      buf[m++] = gradlambdaH[j][2];
+      buf[m++] = comH[j][0];
+      buf[m++] = comH[j][1];
+      buf[m++] = comH[j][2];
+
+
+    }
+  }
+  return m;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int AtomVecFullHars::pack_comm_vel(int n, int *list, double *buf,
+                               int pbc_flag, int *pbc)
+{
+  int i,j,m;
+  double dx,dy,dz,dvx,dvy,dvz;
+
+  m = 0;
+  if (pbc_flag == 0) {
+    for (i = 0; i < n; i++) {
+      j = list[i];
+      buf[m++] = x[j][0];
+      buf[m++] = x[j][1];
+      buf[m++] = x[j][2];
+      buf[m++] = lambdaH[j];
+      buf[m++] = gradlambdaH[j][0];
+      buf[m++] = gradlambdaH[j][1];
+      buf[m++] = gradlambdaH[j][2];
+      buf[m++] = comH[j][0];
+      buf[m++] = comH[j][1];
+      buf[m++] = comH[j][2];
+
+      buf[m++] = v[j][0];
+      buf[m++] = v[j][1];
+      buf[m++] = v[j][2];
+
+    }
+  } else {
+    if (domain->triclinic == 0) {
+      dx = pbc[0]*domain->xprd;
+      dy = pbc[1]*domain->yprd;
+      dz = pbc[2]*domain->zprd;
+    } else {
+      dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
+      dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
+      dz = pbc[2]*domain->zprd;
+    }
+    if (!deform_vremap) {
+      for (i = 0; i < n; i++) {
+        j = list[i];
+        buf[m++] = x[j][0] + dx;
+        buf[m++] = x[j][1] + dy;
+        buf[m++] = x[j][2] + dz;
+        buf[m++] = lambdaH[j];
+        buf[m++] = gradlambdaH[j][0];
+        buf[m++] = gradlambdaH[j][1];
+        buf[m++] = gradlambdaH[j][2];
+        buf[m++] = comH[j][0];
+        buf[m++] = comH[j][1];
+        buf[m++] = comH[j][2];
+
+        buf[m++] = v[j][0];
+        buf[m++] = v[j][1];
+        buf[m++] = v[j][2];
+      }
+    } else {
+      dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
+      dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
+      dvz = pbc[2]*h_rate[2];
+      for (i = 0; i < n; i++) {
+        j = list[i];
+        buf[m++] = x[j][0] + dx;
+        buf[m++] = x[j][1] + dy;
+        buf[m++] = x[j][2] + dz;
+        buf[m++] = lambdaH[j];
+        buf[m++] = gradlambdaH[j][0];
+        buf[m++] = gradlambdaH[j][1];
+        buf[m++] = gradlambdaH[j][2];
+        buf[m++] = comH[j][0];
+        buf[m++] = comH[j][1];
+        buf[m++] = comH[j][2];
+
+
+
+        if (mask[i] & deform_groupbit) {
+          buf[m++] = v[j][0] + dvx;
+          buf[m++] = v[j][1] + dvy;
+          buf[m++] = v[j][2] + dvz;
+        } else {
+          buf[m++] = v[j][0];
+          buf[m++] = v[j][1];
+          buf[m++] = v[j][2];
+        }
+      }
+    }
+  }
+  return m;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void AtomVecFullHars::unpack_comm(int n, int first, double *buf)
+{
+  int i,m,last;
+
+  m = 0;
+  last = first + n;
+  for (i = first; i < last; i++) {
+    x[i][0] = buf[m++];
+    x[i][1] = buf[m++];
+    x[i][2] = buf[m++];
+    lambdaH[i] = buf[m++];
+    gradlambdaH[i][0] = buf[m++];
+    gradlambdaH[i][1] = buf[m++];
+    gradlambdaH[i][2] = buf[m++];
+    comH[i][0] = buf[m++];
+    comH[i][1] = buf[m++];
+    comH[i][2] = buf[m++];
+
+
+
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void AtomVecFullHars::unpack_comm_vel(int n, int first, double *buf)
+{
+  int i,m,last;
+
+  m = 0;
+  last = first + n;
+  for (i = first; i < last; i++) {
+    x[i][0] = buf[m++];
+    x[i][1] = buf[m++];
+    x[i][2] = buf[m++];
+    lambdaH[i] = buf[m++];
+    gradlambdaH[i][0] = buf[m++];
+    gradlambdaH[i][1] = buf[m++];
+    gradlambdaH[i][2] = buf[m++];
+    comH[i][0] = buf[m++];
+    comH[i][1] = buf[m++];
+    comH[i][2] = buf[m++];
+
+    v[i][0] = buf[m++];
+    v[i][1] = buf[m++];
+    v[i][2] = buf[m++];
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+int AtomVecFullHars::pack_reverse(int n, int first, double *buf)
+{
+  int i,m,last;
+
+  m = 0;
+  last = first + n;
+  for (i = first; i < last; i++) {
+    buf[m++] = f[i][0];
+    buf[m++] = f[i][1];
+    buf[m++] = f[i][2];
+
+  }
+  return m;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void AtomVecFullHars::unpack_reverse(int n, int *list, double *buf)
+{
+  int i,j,m;
+
+  m = 0;
+  for (i = 0; i < n; i++) {
+    j = list[i];
+    f[j][0] += buf[m++];
+    f[j][1] += buf[m++];
+    f[j][2] += buf[m++];
+
+
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+int AtomVecFullHars::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++] = ubuf(tag[j]).d;
+      buf[m++] = ubuf(type[j]).d;
+      buf[m++] = ubuf(mask[j]).d;
+      buf[m++] = q[j];
+      buf[m++] = lambdaH[j];
+      buf[m++] = gradlambdaH[j][0];
+      buf[m++] = gradlambdaH[j][1];
+      buf[m++] = gradlambdaH[j][2];
+      buf[m++] = comH[j][0];
+      buf[m++] = comH[j][1];
+      buf[m++] = comH[j][2];
+
+      buf[m++] = ubuf(replambdaH[j]).d;
+      buf[m++] = ubuf(moltypeH[j]).d;
+
+      buf[m++] = ubuf(molecule[j]).d;
+    }
+  } 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++] = ubuf(tag[j]).d;
+      buf[m++] = ubuf(type[j]).d;
+      buf[m++] = ubuf(mask[j]).d;
+      buf[m++] = q[j];
+      buf[m++] = lambdaH[j];
+      buf[m++] = gradlambdaH[j][0];
+      buf[m++] = gradlambdaH[j][1];
+      buf[m++] = gradlambdaH[j][2];
+      buf[m++] = comH[j][0];
+      buf[m++] = comH[j][1];
+      buf[m++] = comH[j][2];
+
+      buf[m++] = ubuf(replambdaH[j]).d;
+      buf[m++] = ubuf(moltypeH[j]).d;
+
+      buf[m++] = ubuf(molecule[j]).d;
+    }
+  }
+
+  if (atom->nextra_border)
+    for (int iextra = 0; iextra < atom->nextra_border; iextra++)
+      m += modify->fix[atom->extra_border[iextra]]->pack_border(n,list,&buf[m]);
+
+  return m;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int AtomVecFullHars::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++] = ubuf(tag[j]).d;
+      buf[m++] = ubuf(type[j]).d;
+      buf[m++] = ubuf(mask[j]).d;
+      buf[m++] = q[j];
+      buf[m++] = lambdaH[j];
+      buf[m++] = gradlambdaH[j][0];
+      buf[m++] = gradlambdaH[j][1];
+      buf[m++] = gradlambdaH[j][2];
+      buf[m++] = comH[j][0];
+      buf[m++] = comH[j][1];
+      buf[m++] = comH[j][2];
+
+      buf[m++] = ubuf(replambdaH[j]).d;
+      buf[m++] = ubuf(moltypeH[j]).d;
+
+      buf[m++] = ubuf(molecule[j]).d;
+      buf[m++] = v[j][0];
+      buf[m++] = v[j][1];
+      buf[m++] = v[j][2];
+    }
+  } else {
+    if (domain->triclinic == 0) {
+      dx = pbc[0]*domain->xprd;
+      dy = pbc[1]*domain->yprd;
+      dz = pbc[2]*domain->zprd;
+    } else {
+      dx = pbc[0];
+      dy = pbc[1];
+      dz = pbc[2];
+    }
+    if (!deform_vremap) {
+      for (i = 0; i < n; i++) {
+        j = list[i];
+        buf[m++] = x[j][0] + dx;
+        buf[m++] = x[j][1] + dy;
+        buf[m++] = x[j][2] + dz;
+        buf[m++] = ubuf(tag[j]).d;
+        buf[m++] = ubuf(type[j]).d;
+        buf[m++] = ubuf(mask[j]).d;
+        buf[m++] = q[j];
+        buf[m++] = lambdaH[j];
+        buf[m++] = gradlambdaH[j][0];
+        buf[m++] = gradlambdaH[j][1];
+        buf[m++] = gradlambdaH[j][2];
+        buf[m++] = comH[j][0];
+        buf[m++] = comH[j][1];
+        buf[m++] = comH[j][2];
+
+        buf[m++] = ubuf(replambdaH[j]).d;
+        buf[m++] = ubuf(moltypeH[j]).d;
+
+        buf[m++] = ubuf(molecule[j]).d;
+        buf[m++] = v[j][0];
+        buf[m++] = v[j][1];
+        buf[m++] = v[j][2];
+      }
+    } else {
+      dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
+      dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
+      dvz = pbc[2]*h_rate[2];
+      for (i = 0; i < n; i++) {
+        j = list[i];
+        buf[m++] = x[j][0] + dx;
+        buf[m++] = x[j][1] + dy;
+        buf[m++] = x[j][2] + dz;
+        buf[m++] = ubuf(tag[j]).d;
+        buf[m++] = ubuf(type[j]).d;
+        buf[m++] = ubuf(mask[j]).d;
+        buf[m++] = q[j];
+        buf[m++] = lambdaH[j];
+        buf[m++] = gradlambdaH[j][0];
+        buf[m++] = gradlambdaH[j][1];
+        buf[m++] = gradlambdaH[j][2];
+        buf[m++] = comH[j][0];
+        buf[m++] = comH[j][1];
+        buf[m++] = comH[j][2];
+
+        buf[m++] = ubuf(replambdaH[j]).d;
+        buf[m++] = ubuf(moltypeH[j]).d;
+
+        buf[m++] = ubuf(molecule[j]).d;
+        if (mask[i] & deform_groupbit) {
+          buf[m++] = v[j][0] + dvx;
+          buf[m++] = v[j][1] + dvy;
+          buf[m++] = v[j][2] + dvz;
+        } else {
+          buf[m++] = v[j][0];
+          buf[m++] = v[j][1];
+          buf[m++] = v[j][2];
+        }
+      }
+    }
+  }
+
+  if (atom->nextra_border)
+    for (int iextra = 0; iextra < atom->nextra_border; iextra++)
+      m += modify->fix[atom->extra_border[iextra]]->pack_border(n,list,&buf[m]);
+
+  return m;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int AtomVecFullHars::pack_border_hybrid(int n, int *list, double *buf)
+{
+  int i,j,m;
+
+  m = 0;
+  for (i = 0; i < n; i++) {
+    j = list[i];
+    buf[m++] = q[j];
+    buf[m++] = ubuf(replambdaH[j]).d;
+    buf[m++] = ubuf(moltypeH[j]).d;
+    buf[m++] = ubuf(molecule[j]).d;
+  }
+  return m;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void AtomVecFullHars::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] = (tagint) ubuf(buf[m++]).i;
+    type[i] = (int) ubuf(buf[m++]).i;
+    mask[i] = (int) ubuf(buf[m++]).i;
+    q[i] = buf[m++];
+    lambdaH[i] = buf[m++];
+    gradlambdaH[i][0] = buf[m++];
+    gradlambdaH[i][1] = buf[m++];
+    gradlambdaH[i][2] = buf[m++];
+    comH[i][0] = buf[m++];
+    comH[i][1] = buf[m++];
+    comH[i][2] = buf[m++];
+
+    replambdaH[i] = (int) ubuf(buf[m++]).i;
+    moltypeH[i] = (int) ubuf(buf[m++]).i;
+
+    molecule[i] = (tagint) ubuf(buf[m++]).i;
+
+  }
+
+  if (atom->nextra_border)
+    for (int iextra = 0; iextra < atom->nextra_border; iextra++)
+      m += modify->fix[atom->extra_border[iextra]]->
+        unpack_border(n,first,&buf[m]);
+}
+
+/* ---------------------------------------------------------------------- */
+
+void AtomVecFullHars::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] = (tagint) ubuf(buf[m++]).i;
+    type[i] = (int) ubuf(buf[m++]).i;
+    mask[i] = (int) ubuf(buf[m++]).i;
+    q[i] = buf[m++];
+    lambdaH[i] = buf[m++];
+    gradlambdaH[i][0] = buf[m++];
+    gradlambdaH[i][1] = buf[m++];
+    gradlambdaH[i][2] = buf[m++];
+    comH[i][0] = buf[m++];
+    comH[i][1] = buf[m++];
+    comH[i][2] = buf[m++];
+
+    replambdaH[i] = (int) ubuf(buf[m++]).i;
+    moltypeH[i] = (int) ubuf(buf[m++]).i;
+
+    molecule[i] = (tagint) ubuf(buf[m++]).i;
+    v[i][0] = buf[m++];
+    v[i][1] = buf[m++];
+    v[i][2] = buf[m++];
+  }
+
+  if (atom->nextra_border)
+    for (int iextra = 0; iextra < atom->nextra_border; iextra++)
+      m += modify->fix[atom->extra_border[iextra]]->
+        unpack_border(n,first,&buf[m]);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int AtomVecFullHars::unpack_border_hybrid(int n, int first, double *buf)
+{
+  int i,m,last;
+
+  m = 0;
+  last = first + n;
+  for (i = first; i < last; i++) {
+    q[i] = buf[m++];
+    replambdaH[i] = (int) ubuf(buf[m++]).i;
+    moltypeH[i] = (int) ubuf(buf[m++]).i;
+    molecule[i] = (tagint) ubuf(buf[m++]).i;
+  }
+  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 AtomVecFullHars::pack_exchange(int i, double *buf)
+{
+  int k;
+
+  int m = 1;
+  buf[m++] = x[i][0];
+  buf[m++] = x[i][1];
+  buf[m++] = x[i][2];
+  buf[m++] = v[i][0];
+  buf[m++] = v[i][1];
+  buf[m++] = v[i][2];
+  buf[m++] = ubuf(tag[i]).d;
+  buf[m++] = ubuf(type[i]).d;
+  buf[m++] = ubuf(mask[i]).d;
+  buf[m++] = ubuf(image[i]).d;
+
+  buf[m++] = q[i];
+  buf[m++] = lambdaH[i];
+  buf[m++] = gradlambdaH[i][0];
+  buf[m++] = gradlambdaH[i][1];
+  buf[m++] = gradlambdaH[i][2];
+  buf[m++] = comH[i][0];
+  buf[m++] = comH[i][1];
+  buf[m++] = comH[i][2];
+
+  buf[m++] = ubuf(replambdaH[i]).d;
+  buf[m++] = ubuf(moltypeH[i]).d;
+
+  buf[m++] = ubuf(molecule[i]).d;
+
+  buf[m++] = ubuf(num_bond[i]).d;
+  for (k = 0; k < num_bond[i]; k++) {
+    buf[m++] = ubuf(bond_type[i][k]).d;
+    buf[m++] = ubuf(bond_atom[i][k]).d;
+  }
+
+  buf[m++] = ubuf(num_angle[i]).d;
+  for (k = 0; k < num_angle[i]; k++) {
+    buf[m++] = ubuf(angle_type[i][k]).d;
+    buf[m++] = ubuf(angle_atom1[i][k]).d;
+    buf[m++] = ubuf(angle_atom2[i][k]).d;
+    buf[m++] = ubuf(angle_atom3[i][k]).d;
+  }
+
+  buf[m++] = ubuf(num_dihedral[i]).d;
+  for (k = 0; k < num_dihedral[i]; k++) {
+    buf[m++] = ubuf(dihedral_type[i][k]).d;
+    buf[m++] = ubuf(dihedral_atom1[i][k]).d;
+    buf[m++] = ubuf(dihedral_atom2[i][k]).d;
+    buf[m++] = ubuf(dihedral_atom3[i][k]).d;
+    buf[m++] = ubuf(dihedral_atom4[i][k]).d;
+  }
+
+  buf[m++] = ubuf(num_improper[i]).d;
+  for (k = 0; k < num_improper[i]; k++) {
+    buf[m++] = ubuf(improper_type[i][k]).d;
+    buf[m++] = ubuf(improper_atom1[i][k]).d;
+    buf[m++] = ubuf(improper_atom2[i][k]).d;
+    buf[m++] = ubuf(improper_atom3[i][k]).d;
+    buf[m++] = ubuf(improper_atom4[i][k]).d;
+  }
+
+  buf[m++] = ubuf(nspecial[i][0]).d;
+  buf[m++] = ubuf(nspecial[i][1]).d;
+  buf[m++] = ubuf(nspecial[i][2]).d;
+  for (k = 0; k < nspecial[i][2]; k++) buf[m++] = ubuf(special[i][k]).d;
+
+  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 AtomVecFullHars::unpack_exchange(double *buf)
+{
+  int k;
+
+  int nlocal = atom->nlocal;
+  if (nlocal == nmax) grow(0);
+
+  int m = 1;
+  x[nlocal][0] = buf[m++];
+  x[nlocal][1] = buf[m++];
+  x[nlocal][2] = buf[m++];
+  v[nlocal][0] = buf[m++];
+  v[nlocal][1] = buf[m++];
+  v[nlocal][2] = buf[m++];
+  tag[nlocal] = (tagint) ubuf(buf[m++]).i;
+  type[nlocal] = (int) ubuf(buf[m++]).i;
+  mask[nlocal] = (int) ubuf(buf[m++]).i;
+  image[nlocal] = (imageint) ubuf(buf[m++]).i;
+
+  q[nlocal] = buf[m++];
+  lambdaH[nlocal] = buf[m++];
+  gradlambdaH[nlocal][0] = buf[m++];
+  gradlambdaH[nlocal][1] = buf[m++];
+  gradlambdaH[nlocal][2] = buf[m++];
+  comH[nlocal][0] = buf[m++];
+  comH[nlocal][1] = buf[m++];
+  comH[nlocal][2] = buf[m++];
+
+  replambdaH[nlocal] = (int) ubuf(buf[m++]).i;
+  moltypeH[nlocal] = (int) ubuf(buf[m++]).i;
+
+  molecule[nlocal] = (tagint) ubuf(buf[m++]).i;
+
+  num_bond[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_bond[nlocal]; k++) {
+    bond_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    bond_atom[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  num_angle[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_angle[nlocal]; k++) {
+    angle_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    angle_atom1[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    angle_atom2[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    angle_atom3[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  num_dihedral[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_dihedral[nlocal]; k++) {
+    dihedral_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    dihedral_atom1[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    dihedral_atom2[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    dihedral_atom3[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    dihedral_atom4[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  num_improper[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_improper[nlocal]; k++) {
+    improper_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    improper_atom1[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    improper_atom2[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    improper_atom3[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    improper_atom4[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  nspecial[nlocal][0] = (int) ubuf(buf[m++]).i;
+  nspecial[nlocal][1] = (int) ubuf(buf[m++]).i;
+  nspecial[nlocal][2] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < nspecial[nlocal][2]; k++)
+    special[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+
+  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 AtomVecFullHars::size_restart()
+{
+  int i;
+
+  int nlocal = atom->nlocal;
+  int n = 0;
+  for (i = 0; i < nlocal; i++)
+    n += 17 + 2*num_bond[i] + 4*num_angle[i] +
+      5*num_dihedral[i] + 5*num_improper[i]+9;
+
+  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 AtomVecFullHars::pack_restart(int i, double *buf)
+{
+  int k;
+
+  int m = 1;
+  buf[m++] = x[i][0];
+  buf[m++] = x[i][1];
+  buf[m++] = x[i][2];
+  buf[m++] = ubuf(tag[i]).d;
+  buf[m++] = ubuf(type[i]).d;
+  buf[m++] = ubuf(mask[i]).d;
+  buf[m++] = ubuf(image[i]).d;
+  buf[m++] = v[i][0];
+  buf[m++] = v[i][1];
+  buf[m++] = v[i][2];
+
+  buf[m++] = q[i];
+  buf[m++] = lambdaH[i];
+  buf[m++] = gradlambdaH[i][0];
+  buf[m++] = gradlambdaH[i][1];
+  buf[m++] = gradlambdaH[i][2];
+  buf[m++] = comH[i][0];
+  buf[m++] = comH[i][1];
+  buf[m++] = comH[i][2];
+
+  buf[m++] = ubuf(replambdaH[i]).d;
+  buf[m++] = ubuf(moltypeH[i]).d;
+  buf[m++] = ubuf(molecule[i]).d;
+
+  buf[m++] = ubuf(num_bond[i]).d;
+  for (k = 0; k < num_bond[i]; k++) {
+    buf[m++] = ubuf(MAX(bond_type[i][k],-bond_type[i][k])).d;
+    buf[m++] = ubuf(bond_atom[i][k]).d;
+  }
+
+  buf[m++] = ubuf(num_angle[i]).d;
+  for (k = 0; k < num_angle[i]; k++) {
+    buf[m++] = ubuf(MAX(angle_type[i][k],-angle_type[i][k])).d;
+    buf[m++] = ubuf(angle_atom1[i][k]).d;
+    buf[m++] = ubuf(angle_atom2[i][k]).d;
+    buf[m++] = ubuf(angle_atom3[i][k]).d;
+  }
+
+  buf[m++] = ubuf(num_dihedral[i]).d;
+  for (k = 0; k < num_dihedral[i]; k++) {
+    buf[m++] = ubuf(MAX(dihedral_type[i][k],-dihedral_type[i][k])).d;
+    buf[m++] = ubuf(dihedral_atom1[i][k]).d;
+    buf[m++] = ubuf(dihedral_atom2[i][k]).d;
+    buf[m++] = ubuf(dihedral_atom3[i][k]).d;
+    buf[m++] = ubuf(dihedral_atom4[i][k]).d;
+  }
+
+  buf[m++] = ubuf(num_improper[i]).d;
+  for (k = 0; k < num_improper[i]; k++) {
+    buf[m++] = ubuf(MAX(improper_type[i][k],-improper_type[i][k])).d;
+    buf[m++] = ubuf(improper_atom1[i][k]).d;
+    buf[m++] = ubuf(improper_atom2[i][k]).d;
+    buf[m++] = ubuf(improper_atom3[i][k]).d;
+    buf[m++] = ubuf(improper_atom4[i][k]).d;
+  }
+
+  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 AtomVecFullHars::unpack_restart(double *buf)
+{
+  int k;
+
+  int nlocal = atom->nlocal;
+  if (nlocal == nmax) {
+    grow(0);
+    if (atom->nextra_store)
+      memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
+  }
+
+  int m = 1;
+  x[nlocal][0] = buf[m++];
+  x[nlocal][1] = buf[m++];
+  x[nlocal][2] = buf[m++];
+  tag[nlocal] = (tagint) ubuf(buf[m++]).i;
+  type[nlocal] = (int) ubuf(buf[m++]).i;
+  mask[nlocal] = (int) ubuf(buf[m++]).i;
+  image[nlocal] = (imageint) ubuf(buf[m++]).i;
+  v[nlocal][0] = buf[m++];
+  v[nlocal][1] = buf[m++];
+  v[nlocal][2] = buf[m++];
+
+  q[nlocal] = buf[m++];
+  lambdaH[nlocal] = buf[m++];
+  gradlambdaH[nlocal][0] = buf[m++];
+  gradlambdaH[nlocal][1] = buf[m++];
+  gradlambdaH[nlocal][2] = buf[m++];
+  comH[nlocal][0] = buf[m++];
+  comH[nlocal][1] = buf[m++];
+  comH[nlocal][2] = buf[m++];
+  replambdaH[nlocal] = (int) ubuf(buf[m++]).i;
+  moltypeH[nlocal] = (int) ubuf(buf[m++]).i;
+
+  molecule[nlocal] = (tagint) ubuf(buf[m++]).i;
+
+  num_bond[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_bond[nlocal]; k++) {
+    bond_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    bond_atom[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  num_angle[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_angle[nlocal]; k++) {
+    angle_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    angle_atom1[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    angle_atom2[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    angle_atom3[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  num_dihedral[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_dihedral[nlocal]; k++) {
+    dihedral_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    dihedral_atom1[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    dihedral_atom2[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    dihedral_atom3[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    dihedral_atom4[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  num_improper[nlocal] = (int) ubuf(buf[m++]).i;
+  for (k = 0; k < num_improper[nlocal]; k++) {
+    improper_type[nlocal][k] = (int) ubuf(buf[m++]).i;
+    improper_atom1[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    improper_atom2[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    improper_atom3[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+    improper_atom4[nlocal][k] = (tagint) ubuf(buf[m++]).i;
+  }
+
+  nspecial[nlocal][0] = nspecial[nlocal][1] = nspecial[nlocal][2] = 0;
+
+  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 AtomVecFullHars::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] = ((imageint) IMGMAX << IMG2BITS) |
+    ((imageint) IMGMAX << IMGBITS) | IMGMAX;
+  v[nlocal][0] = 0.0;
+  v[nlocal][1] = 0.0;
+  v[nlocal][2] = 0.0;
+
+  q[nlocal] = 0.0;
+  lambdaH[nlocal] = 0.0;
+  gradlambdaH[nlocal][0] = 0.0;
+  gradlambdaH[nlocal][1] = 0.0;
+  gradlambdaH[nlocal][2] = 0.0;
+  comH[nlocal][0] = 0;
+  comH[nlocal][1] = 0;
+  comH[nlocal][2] = 0;
+
+  replambdaH[nlocal] = 0;
+  moltypeH[nlocal] = 0;
+
+  molecule[nlocal] = 0;
+  num_bond[nlocal] = 0;
+  num_angle[nlocal] = 0;
+  num_dihedral[nlocal] = 0;
+  num_improper[nlocal] = 0;
+  nspecial[nlocal][0] = nspecial[nlocal][1] = nspecial[nlocal][2] = 0;
+
+  atom->nlocal++;
+}
+
+/* ----------------------------------------------------------------------
+   unpack one line from Atoms section of data file
+   initialize other atom quantities
+------------------------------------------------------------------------- */
+
+void AtomVecFullHars::data_atom(double *coord, imageint imagetmp, char **values)
+{
+  int nlocal = atom->nlocal;
+  if (nlocal == nmax) grow(0);
+
+  tag[nlocal] = ATOTAGINT(values[0]);
+  molecule[nlocal] = ATOTAGINT(values[1]);
+  type[nlocal] = atoi(values[2]);
+  if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
+    error->one(FLERR,"Invalid atom type in Atoms section of data file");
+
+  q[nlocal] = atof(values[3]);
+  replambdaH[nlocal] = atoi(values[4]);
+  moltypeH[nlocal] = atoi(values[5]);
+
+
+  x[nlocal][0] = coord[0];
+  x[nlocal][1] = coord[1];
+  x[nlocal][2] = coord[2];
+
+  comH[nlocal][0] = 0;
+  comH[nlocal][1] = 0;
+  comH[nlocal][2] = 0;
+
+  image[nlocal] = imagetmp;
+
+  mask[nlocal] = 1;
+  v[nlocal][0] = 0.0;
+  v[nlocal][1] = 0.0;
+  v[nlocal][2] = 0.0;
+  num_bond[nlocal] = 0;
+  num_angle[nlocal] = 0;
+  num_dihedral[nlocal] = 0;
+  num_improper[nlocal] = 0;
+
+  atom->nlocal++;
+}
+
+/* ----------------------------------------------------------------------
+   unpack hybrid quantities from one line in Atoms section of data file
+   initialize other atom quantities for this sub-style
+------------------------------------------------------------------------- */
+
+int AtomVecFullHars::data_atom_hybrid(int nlocal, char **values)
+{
+  molecule[nlocal] = ATOTAGINT(values[0]);
+  q[nlocal] = atof(values[1]);
+  replambdaH[nlocal] = atoi(values[2]);
+  moltypeH[nlocal] = atoi(values[3]);
+
+  num_bond[nlocal] = 0;
+  num_angle[nlocal] = 0;
+  num_dihedral[nlocal] = 0;
+  num_improper[nlocal] = 0;
+
+  return 2;
+}
+
+/* ----------------------------------------------------------------------
+   pack atom info for data file including 3 image flags
+------------------------------------------------------------------------- */
+
+void AtomVecFullHars::pack_data(double **buf)
+{
+  int nlocal = atom->nlocal;
+  for (int i = 0; i < nlocal; i++) {
+    buf[i][0] = ubuf(tag[i]).d;
+    buf[i][1] = ubuf(molecule[i]).d;
+    buf[i][2] = ubuf(type[i]).d;
+    buf[i][3] = q[i];
+    buf[i][4] = ubuf(replambdaH[i]).d;
+    buf[i][5] = ubuf(moltypeH[i]).d;
+
+    buf[i][6] = x[i][0];
+    buf[i][7] = x[i][1];
+    buf[i][8] = x[i][2];
+    buf[i][9] = ubuf((image[i] & IMGMASK) - IMGMAX).d;
+    buf[i][10] = ubuf((image[i] >> IMGBITS & IMGMASK) - IMGMAX).d;
+    buf[i][11] = ubuf((image[i] >> IMG2BITS) - IMGMAX).d;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   pack hybrid atom info for data file
+------------------------------------------------------------------------- */
+
+int AtomVecFullHars::pack_data_hybrid(int i, double *buf)
+{
+  buf[0] = ubuf(molecule[i]).d;
+  buf[1] = q[i];
+  buf[2] = ubuf(replambdaH[i]).d;
+  buf[3] = ubuf(moltypeH[i]).d;
+
+  return 2;
+}
+
+/* ----------------------------------------------------------------------
+   write atom info to data file including 3 image flags
+------------------------------------------------------------------------- */
+
+void AtomVecFullHars::write_data(FILE *fp, int n, double **buf)
+{
+  for (int i = 0; i < n; i++)
+    fprintf(fp,TAGINT_FORMAT " " TAGINT_FORMAT
+            " %d %-1.16e %-1.16e %-1.16e %-1.16e %d %d %d\n",
+            (tagint) ubuf(buf[i][0]).i,(tagint) ubuf(buf[i][1]).i,
+            (int) ubuf(buf[i][2]).i,
+            buf[i][3],buf[i][4],buf[i][5],buf[i][6],
+            (int) ubuf(buf[i][7]).i,(int) ubuf(buf[i][8]).i,
+            (int) ubuf(buf[i][9]).i);
+}
+
+/* ----------------------------------------------------------------------
+   write hybrid atom info to data file
+------------------------------------------------------------------------- */
+
+int AtomVecFullHars::write_data_hybrid(FILE *fp, double *buf)
+{
+  fprintf(fp," " TAGINT_FORMAT " %-1.16e",(tagint) ubuf(buf[0]).i,buf[1]);
+  return 2;
+}
+
+/* ----------------------------------------------------------------------
+   return # of bytes of allocated memory
+------------------------------------------------------------------------- */
+
+bigint AtomVecFullHars::memory_usage()
+{
+  bigint bytes = 0;
+
+  if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
+  if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
+  if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
+  if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
+  if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
+  if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
+  if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
+
+  if (atom->memcheck("q")) bytes += memory->usage(q,nmax);
+  if (atom->memcheck("lambdaH")) bytes += memory->usage(lambdaH,nmax);
+  if (atom->memcheck("gradlambdaH")) bytes += memory->usage(gradlambdaH,nmax,3);
+  if (atom->memcheck("replambdaH")) bytes += memory->usage(replambdaH,nmax);
+  if (atom->memcheck("moltypeH")) bytes += memory->usage(moltypeH,nmax);
+
+  if (atom->memcheck("comH")) bytes += memory->usage(comH,nmax,3);
+
+
+  if (atom->memcheck("molecule")) bytes += memory->usage(molecule,nmax);
+  if (atom->memcheck("nspecial")) bytes += memory->usage(nspecial,nmax,3);
+  if (atom->memcheck("special"))
+    bytes += memory->usage(special,nmax,atom->maxspecial);
+
+  if (atom->memcheck("num_bond")) bytes += memory->usage(num_bond,nmax);
+  if (atom->memcheck("bond_type"))
+    bytes += memory->usage(bond_type,nmax,atom->bond_per_atom);
+  if (atom->memcheck("bond_atom"))
+    bytes += memory->usage(bond_atom,nmax,atom->bond_per_atom);
+
+  if (atom->memcheck("num_angle")) bytes += memory->usage(num_angle,nmax);
+  if (atom->memcheck("angle_type"))
+    bytes += memory->usage(angle_type,nmax,atom->angle_per_atom);
+  if (atom->memcheck("angle_atom1"))
+    bytes += memory->usage(angle_atom1,nmax,atom->angle_per_atom);
+  if (atom->memcheck("angle_atom2"))
+    bytes += memory->usage(angle_atom2,nmax,atom->angle_per_atom);
+  if (atom->memcheck("angle_atom3"))
+    bytes += memory->usage(angle_atom3,nmax,atom->angle_per_atom);
+
+  if (atom->memcheck("num_dihedral")) bytes += memory->usage(num_dihedral,nmax);
+  if (atom->memcheck("dihedral_type"))
+    bytes += memory->usage(dihedral_type,nmax,atom->dihedral_per_atom);
+  if (atom->memcheck("dihedral_atom1"))
+    bytes += memory->usage(dihedral_atom1,nmax,atom->dihedral_per_atom);
+  if (atom->memcheck("dihedral_atom2"))
+    bytes += memory->usage(dihedral_atom2,nmax,atom->dihedral_per_atom);
+  if (atom->memcheck("dihedral_atom3"))
+    bytes += memory->usage(dihedral_atom3,nmax,atom->dihedral_per_atom);
+  if (atom->memcheck("dihedral_atom4"))
+    bytes += memory->usage(dihedral_atom4,nmax,atom->dihedral_per_atom);
+
+  if (atom->memcheck("num_improper")) bytes += memory->usage(num_improper,nmax);
+  if (atom->memcheck("improper_type"))
+    bytes += memory->usage(improper_type,nmax,atom->improper_per_atom);
+  if (atom->memcheck("improper_atom1"))
+    bytes += memory->usage(improper_atom1,nmax,atom->improper_per_atom);
+  if (atom->memcheck("improper_atom2"))
+    bytes += memory->usage(improper_atom2,nmax,atom->improper_per_atom);
+  if (atom->memcheck("improper_atom3"))
+    bytes += memory->usage(improper_atom3,nmax,atom->improper_per_atom);
+  if (atom->memcheck("improper_atom4"))
+    bytes += memory->usage(improper_atom4,nmax,atom->improper_per_atom);
+
+  return bytes;
+}
diff --git a/src/USER-HADRESS/atom_vec_full_hars.h b/src/USER-HADRESS/atom_vec_full_hars.h
new file mode 100644
index 000000000..59bac9a3b
--- /dev/null
+++ b/src/USER-HADRESS/atom_vec_full_hars.h
@@ -0,0 +1,104 @@
+/* -*- 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 ATOM_CLASS
+
+AtomStyle(full/hars,AtomVecFullHars)
+
+#else
+
+#ifndef LMP_ATOM_VEC_FULL_HARS_H
+#define LMP_ATOM_VEC_FULL_HARS_H
+
+#include "atom_vec.h"
+
+namespace LAMMPS_NS {
+
+class AtomVecFullHars : public AtomVec {
+ public:
+  AtomVecFullHars(class LAMMPS *);
+  virtual ~AtomVecFullHars() {}
+  void grow(int);
+  void grow_reset();
+  void copy(int, int, int);
+  virtual int pack_comm(int, int *, double *, int, int *);
+  virtual int pack_comm_vel(int, int *, double *, int, int *);
+  virtual void unpack_comm(int, int, double *);
+  virtual void unpack_comm_vel(int, int, double *);
+  int pack_reverse(int, int, double *);
+  void unpack_reverse(int, int *, double *);
+  virtual int pack_border(int, int *, double *, int, int *);
+  virtual int pack_border_vel(int, int *, double *, int, int *);
+  int pack_border_hybrid(int, int *, double *);
+  virtual void unpack_border(int, int, double *);
+  virtual void unpack_border_vel(int, int, double *);
+  int unpack_border_hybrid(int, int, double *);
+  virtual int pack_exchange(int, double *);
+  virtual int unpack_exchange(double *);
+  int size_restart();
+  int pack_restart(int, double *);
+  int unpack_restart(double *);
+  void create_atom(int, double *);
+  void data_atom(double *, imageint, char **);
+  int data_atom_hybrid(int, char **);
+  void pack_data(double **);
+  int pack_data_hybrid(int, double *);
+  void write_data(FILE *, int, double **);
+  int write_data_hybrid(FILE *, double *);
+  bigint memory_usage();
+
+ protected:
+  tagint *tag;
+  int *type,*mask;
+  imageint *image;
+  double **x,**v,**f;
+  double *q;
+  double *lambdaH;
+  double **gradlambdaH;
+  int *replambdaH;
+  int *moltypeH;
+  double **comH;
+  tagint *molecule;
+  int **nspecial;
+  tagint **special;
+  int *num_bond;
+  int **bond_type;
+  tagint **bond_atom;
+  int *num_angle;
+  int **angle_type;
+  tagint **angle_atom1,**angle_atom2,**angle_atom3;
+  int *num_dihedral;
+  int **dihedral_type;
+  tagint **dihedral_atom1,**dihedral_atom2,**dihedral_atom3,**dihedral_atom4;
+  int *num_improper;
+  int **improper_type;
+  tagint **improper_atom1,**improper_atom2,**improper_atom3,**improper_atom4;
+};
+
+}
+
+#endif
+#endif
+
+/* ERROR/WARNING messages:
+
+E: Per-processor system is too big
+
+The number of owned atoms plus ghost atoms on a single
+processor must fit in 32-bit integer.
+
+E: Invalid atom type in Atoms section of data file
+
+Atom types must range from 1 to specified # of types.
+
+*/
diff --git a/src/USER-HADRESS/fix_lambdah_calc.cpp b/src/USER-HADRESS/fix_lambdah_calc.cpp
new file mode 100644
index 000000000..17d84032d
--- /dev/null
+++ b/src/USER-HADRESS/fix_lambdah_calc.cpp
@@ -0,0 +1,958 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain 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: Maziar Heidari (Max Planck Institute for Polymer Research)
+------------------------------------------------------------------------- */
+
+#include "math.h"
+#include "string.h"
+#include "stdlib.h"
+#include "fix_lambdah_calc.h"
+#include "atom.h"
+#include "input.h"
+#include "variable.h"
+#include "domain.h"
+#include "lattice.h"
+#include "update.h"
+#include "modify.h"
+#include "output.h"
+#include "respa.h"
+#include "error.h"
+#include "force.h"
+#include "math_const.h"
+#include "memory.h"
+#include "comm.h"
+#include "citeme.h"
+
+
+using namespace LAMMPS_NS;
+using namespace FixConst;
+using namespace MathConst;
+
+#define BIG MAXTAGINT
+
+static const char cite_HAdResS[] =
+  "@Article{Heidari et al.2016\n"
+  " author = {M. Heidari, R. Cortes-Huerto, D. Donadio and R. Potestio},\n"
+  " title = {Accurate and general treatment of electrostatic interaction in Hamiltonian adaptive resolution simulations},\n"
+  " journal = {Eur. Phys. J. Special Topics},\n"
+  " year =    2016,\n"
+  " volume =  Submitted,\n"
+  " pages =   {}\n"
+  "}\n\n";
+
+
+/* ---------------------------------------------------------------------- */
+
+FixLambdaHCalc::FixLambdaHCalc(LAMMPS *lmp, int narg, char **arg) :
+  Fix(lmp, narg, arg)
+{
+
+
+    if (lmp->citeme) lmp->citeme->add(cite_HAdResS);
+
+    massproc_H = NULL;
+    masstotal_H = NULL;
+    com_H = NULL;
+    comall_H = NULL;
+    molmap_H = NULL;
+    lambdaCM = NULL;
+    gradlambdaCM = NULL;
+    Comp_Density_Num_H = NULL;
+    Comp_Density_Num_all_H = NULL;
+    Mean_Density_H = NULL;
+    Int_Mean_Density_H = NULL;
+    Mean_Comp_Density_Conv_H = NULL;
+    grad_Comp_Density_Conv_H = NULL;
+    Mean_grad_Comp_Density_Conv_H = NULL;
+
+
+
+  me = comm->me;
+
+  if (narg < 8) error->all(FLERR,"Illegal fix LambdaH/Calc command");
+
+  atom->nmoltypesH  = force->numeric(FLERR,arg[3]);
+  Length_Hyb  = force->numeric(FLERR,arg[4]);
+  Length_ATRegion  = force->numeric(FLERR,arg[5]);
+  Pressure_Comp_Flag  = force->numeric(FLERR,arg[6]);
+  Pressure_lambda_Increment  = force->numeric(FLERR,arg[7]);
+  Pressure_Update_Frequency  = force->numeric(FLERR,arg[8]);
+  Pressure_Update_Time_Begin  = force->numeric(FLERR,arg[9]);
+  Pressure_Update_Time_End  = force->numeric(FLERR,arg[10]);
+
+  if (strcmp(arg[11],"slab") == 0) Hybrid_Style = 0;
+  else if (strcmp(arg[11],"sphere") == 0) Hybrid_Style = 1;
+  else if (strcmp(arg[11],"cylinder") == 0) Hybrid_Style = 2;
+  else error->all(FLERR,"Illegal fix LambdaH/Calc command");
+
+  Density_Comp_Flag  = force->numeric(FLERR,arg[12]);
+  Density_Bin_Size  = force->numeric(FLERR,arg[13]);
+  Density_Update_Frequency  = force->numeric(FLERR,arg[14]);
+  Density_Update_Time_Begin  = force->numeric(FLERR,arg[15]);
+  Density_Update_Time_End  = force->numeric(FLERR,arg[16]);
+  Density_Sigma_Gauss = force->numeric(FLERR,arg[17]);
+  Density_Gauss_Int_Range = force->numeric(FLERR,arg[18]);
+  Density_Ref = force->numeric(FLERR,arg[19]);
+  Comp_Density_Scaling_factor_H =  force->numeric(FLERR,arg[20]);
+  Load_File_Flag =  force->numeric(FLERR,arg[21]);
+
+  x0lo = domain->boxlo[0];
+  x0hi = domain->boxhi[0];
+  x1lo = domain->boxlo[1];
+  x1hi = domain->boxhi[1];
+  x2lo = domain->boxlo[2];
+  x2hi = domain->boxhi[2];
+
+  center_box[0] = (x0hi + x0lo)/2.0;
+  center_box[1] = (x1hi + x1lo)/2.0;
+  center_box[2] = (x2hi + x2lo)/2.0;
+
+
+  x0BoxSize = x0hi - x0lo;
+  Length_CGRegion = x0BoxSize - 2*Length_Hyb - Length_ATRegion;
+  R_Start_Hybrid_1 = x0lo + Length_CGRegion/2.0;
+  R_Start_Hybrid_2 = x0lo + x0BoxSize - (Length_CGRegion/2.0 + Length_Hyb);
+  S_Start_Hybrid = Length_ATRegion;
+  Pressure_Bin_Num = 1.0 / Pressure_lambda_Increment;
+  xmin_AT = R_Start_Hybrid_1 + Length_Hyb;
+  xmax_AT= R_Start_Hybrid_1 + Length_Hyb + Length_ATRegion;
+  if(Hybrid_Style==0)Density_Bin_Num = floor(x0BoxSize / Density_Bin_Size);
+  else if(Hybrid_Style==1)Density_Bin_Num = floor(sqrt(pow(0.5*(x0hi-x0lo),2.0)+pow(0.5*(x1hi-x1lo),2.0)+pow(0.5*(x2hi-x2lo),2.0)) / Density_Bin_Size);
+  else if(Hybrid_Style==2)Density_Bin_Num = floor(sqrt(pow(0.5*(x0hi-x0lo),2.0)+pow(0.5*(x1hi-x1lo),2.0)) / Density_Bin_Size);
+
+
+  Comp_Counter_H = 0;
+  Density_Counter_H = 0;
+  Density_Compensation_Run = 0;
+
+  memory->create(Comp_Density_Num_H,Density_Bin_Num,atom->nmoltypesH+1,"lambdaH/calc:Comp_Density_Num_H");
+  memory->create(Comp_Density_Num_all_H,Density_Bin_Num,atom->nmoltypesH+1,"lambdaH/calc:Comp_Density_Num_all_H");
+
+  if(me==0){
+    if (screen){
+      fprintf(screen,"nmoltypes= %d\n",atom->nmoltypesH);
+      fprintf(screen,"Length_Hyb= %f\n",Length_Hyb);
+      fprintf(screen,"Length_ATRegion= %f\n",Length_ATRegion);
+      fprintf(screen,"Pressure_Comp_Flag= %d\n",Pressure_Comp_Flag);
+      fprintf(screen,"Pressure_lambda_Increment= %f\n",Pressure_lambda_Increment);
+      fprintf(screen,"Pressure_Update_Frequency= %d\n",Pressure_Update_Frequency);
+      fprintf(screen,"Pressure_Update_Time_Begin= %d\n",Pressure_Update_Time_Begin);
+      fprintf(screen,"Pressure_Update_Time_End= %d\n",Pressure_Update_Time_End);
+      fprintf(screen,"Density_Comp_Flag= %d\n",Density_Comp_Flag);
+      fprintf(screen,"Density_Bin_Size= %f\n",Density_Bin_Size);
+      fprintf(screen,"Density_Update_Frequency= %d\n",Density_Update_Frequency);
+      fprintf(screen,"Density_Update_Time_Begin= %d\n",Density_Update_Time_Begin);
+      fprintf(screen,"Density_Update_Time_End= %d\n",Density_Update_Time_End);
+      fprintf(screen,"Density_Sigma_Gauss= %f\n",Density_Sigma_Gauss);
+      fprintf(screen,"Density_Gauss_Int_Range= %d\n",Density_Gauss_Int_Range);
+      fprintf(screen,"Density_Ref= %f\n",Density_Ref);
+      fprintf(screen,"Comp_Density_Scaling_factor_H = %f\n",Comp_Density_Scaling_factor_H);
+      fprintf(screen,"Load_File_Flag = %d\n",Load_File_Flag);
+      fprintf(screen,"Center_box = %f %f %f\n",center_box[0],center_box[1],center_box[2]);
+      fprintf(screen,"Density_Bin_Size = %f\n",Density_Bin_Size);
+      fprintf(screen,"Density_Bin_Num = %d\n",Density_Bin_Num);
+      fprintf(screen,"x0lo= %f\n",x0lo);
+      fprintf(screen,"x0hi= %f\n",x0hi);
+      fprintf(screen,"x0BoxSize= %f\n",x0BoxSize);
+      fprintf(screen,"d1= %f\n",R_Start_Hybrid_1);
+      fprintf(screen,"d2= %f\n",R_Start_Hybrid_2);
+      fprintf(screen,"moltype%d\n",atom->nmoltypesH);
+
+    }
+    if (logfile){
+        fprintf(logfile,"nmoltypes= %d\n",atom->nmoltypesH);
+        fprintf(logfile,"Length_Hyb= %f\n",Length_Hyb);
+        fprintf(logfile,"Length_ATRegion= %f\n",Length_ATRegion);
+        fprintf(logfile,"Pressure_Comp_Flag= %d\n",Pressure_Comp_Flag);
+        fprintf(logfile,"Pressure_lambda_Increment= %f\n",Pressure_lambda_Increment);
+        fprintf(logfile,"Pressure_Update_Frequency= %d\n",Pressure_Update_Frequency);
+        fprintf(logfile,"Pressure_Update_Time_Begin= %d\n",Pressure_Update_Time_Begin);
+        fprintf(logfile,"Pressure_Update_Time_End= %d\n",Pressure_Update_Time_End);
+        fprintf(logfile,"Density_Comp_Flag= %d\n",Density_Comp_Flag);
+        fprintf(logfile,"Density_Bin_Size= %f\n",Density_Bin_Size);
+        fprintf(logfile,"Density_Update_Frequency= %d\n",Density_Update_Frequency);
+        fprintf(logfile,"Density_Update_Time_Begin= %d\n",Density_Update_Time_Begin);
+        fprintf(logfile,"Density_Update_Time_End= %d\n",Density_Update_Time_End);
+        fprintf(logfile,"Density_Sigma_Gauss= %f\n",Density_Sigma_Gauss);
+        fprintf(logfile,"Density_Gauss_Int_Range= %d\n",Density_Gauss_Int_Range);
+        fprintf(logfile,"Density_Ref= %f\n",Density_Ref);
+        fprintf(logfile,"Comp_Density_Scaling_factor_H = %f\n",Comp_Density_Scaling_factor_H);
+        fprintf(logfile,"Load_File_Flag = %d\n",Load_File_Flag);
+        fprintf(logfile,"Center_box = %f %f %f\n",center_box[0],center_box[1],center_box[2]);
+        fprintf(logfile,"Density_Bin_Size = %f\n",Density_Bin_Size);
+        fprintf(logfile,"Density_Bin_Num = %d\n",Density_Bin_Num);
+        fprintf(logfile,"x0lo= %f\n",x0lo);
+        fprintf(logfile,"x0hi= %f\n",x0hi);
+        fprintf(logfile,"x0BoxSize= %f\n",x0BoxSize);
+        fprintf(logfile,"d1= %f\n",R_Start_Hybrid_1);
+        fprintf(logfile,"d2= %f\n",R_Start_Hybrid_2);
+        fprintf(logfile,"moltype%d\n",atom->nmoltypesH);
+
+    }
+  }
+
+  memory->create(Int_Mean_Density_H,Density_Bin_Num,atom->nmoltypesH+1,"lambdaH/calc:Int_Mean_Density_H");
+  memory->create(Mean_Density_H,Density_Bin_Num,atom->nmoltypesH+1,"lambdaH/calc:Mean_Density_H");
+  memory->create(Mean_Comp_Density_Conv_H,Density_Bin_Num,atom->nmoltypesH+1,"lambdaH/calc:Mean_Comp_Density_Conv_H");
+  memory->create(grad_Comp_Density_Conv_H,Density_Bin_Num,atom->nmoltypesH+1,"lambdaH/calc:grad_Comp_Density_Conv_H");
+  memory->create(Mean_grad_Comp_Density_Conv_H,Density_Bin_Num,atom->nmoltypesH+1,"lambdaH/calc:Mean_grad_Comp_Density_Conv_H");
+
+
+  int This_Step = update->ntimestep;
+
+  for(int i = 0;i < Density_Bin_Num; i++){
+      for(int j = 0; j < atom->nmoltypesH; j++){
+          Comp_Density_Num_H[i][j] = 0;
+          Comp_Density_Num_all_H[i][j] = 0;
+          Int_Mean_Density_H[i][j] = 0;
+          Mean_Density_H[i][j] = 0;
+          Mean_Comp_Density_Conv_H[i][j] = 0;
+          Mean_grad_Comp_Density_Conv_H[i][j] = 0;
+          grad_Comp_Density_Conv_H[i][j] = 0;
+      }
+  }
+
+  if((This_Step >= Density_Update_Time_End || Load_File_Flag) && Density_Comp_Flag != 0)Load_Compensation_Density();
+
+  if (atom->molecular == 0)
+    error->all(FLERR,"Compute com/molecule requires molecular atom style");
+
+  array_flag = 1;
+  size_array_cols = 3;
+  extarray = 0;
+  // setup molecule-based data
+  nmolecules = molecules_in_group(idlo,idhi);
+  size_array_rows = nmolecules;
+
+  //printf("Nmolecules= %d\n",nmolecules);
+
+  memory->create(massproc_H,nmolecules,"lambdaH/calc:massproc_H");
+  memory->create(masstotal_H,nmolecules,"lambdaH/calc:masstotal_H");
+  memory->create(com_H,nmolecules,3,"lambdaH/calc:com_H");
+  memory->create(comall_H,nmolecules,3,"lambdaH/calc:comall_H");
+  memory->create(lambdaCM,nmolecules,"lambdaH/calc:lambdaCM");
+  memory->create(gradlambdaCM,nmolecules,3,"lambdaH/calc:gradlambdaCM");
+
+  // compute masstotal for each molecule
+
+  int *mask = atom->mask;
+  tagint *molecule = atom->molecule;
+  int *type = atom->type;
+  double *mass = atom->mass;
+  double *rmass = atom->rmass;
+  int nlocal = atom->nlocal;
+  tagint imol;
+  double massone;
+
+  for (int i = 0; i < nmolecules; i++) massproc_H[i] = 0.0;
+
+  for (int i = 0; i < nlocal; i++)
+  {
+    if (mask[i] & groupbit) {
+      if (rmass) massone = rmass[i];
+      else massone = mass[type[i]];
+      imol = molecule[i];
+      if (molmap_H) imol = molmap_H[imol-idlo];
+      else imol--;
+      massproc_H[imol] += massone;
+    }
+}
+
+  MPI_Allreduce(massproc_H,masstotal_H,nmolecules,MPI_DOUBLE,MPI_SUM,world);
+  int *replambdaH = atom->replambdaH;
+  int pass = 0;
+  for (int i = 0; i < nlocal; i++) if(replambdaH[i] != 0)pass=1;
+  if(pass==0)      error->all(FLERR,"No representative atom (replambdaH) has been defined!");
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+FixLambdaHCalc::~FixLambdaHCalc()
+{
+
+    memory->destroy(massproc_H);
+    memory->destroy(masstotal_H);
+    memory->destroy(com_H);
+    memory->destroy(comall_H);
+    memory->destroy(molmap_H);
+    memory->destroy(lambdaCM);
+    memory->destroy(gradlambdaCM);
+    memory->destroy(Comp_Density_Num_H);
+    memory->destroy(Comp_Density_Num_all_H);
+    memory->destroy(Mean_Density_H);
+    memory->destroy(Int_Mean_Density_H);
+    memory->destroy(Mean_Comp_Density_Conv_H);
+    memory->destroy(grad_Comp_Density_Conv_H);
+    memory->destroy(Mean_grad_Comp_Density_Conv_H);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int FixLambdaHCalc::setmask()
+{
+  int mask = 0;
+  //mask |= PRE_FORCE;
+//  mask |= PRE_NEIGHBOR;
+  mask |= POST_INTEGRATE;
+  mask |= THERMO_ENERGY;
+//  mask |= POST_FORCE_RESPA;
+  mask |= MIN_PRE_FORCE;
+  return mask;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void FixLambdaHCalc::init()
+{
+    int ntmp = molecules_in_group(idlo,idhi);
+    if (ntmp != nmolecules)
+      error->all(FLERR,"Molecule count changed in compute com/molecule");
+
+
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+void FixLambdaHCalc::setup(int vflag)
+{
+
+//  if (strstr(update->integrate_style,"verlet"))
+    //pre_force(vflag);
+    post_integrate();
+//  else {
+//    ((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
+//    post_force_respa(vflag,nlevels_respa-1,0);
+ //   ((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
+ // }
+}
+
+/* ---------------------------------------------------------------------- */
+
+
+void FixLambdaHCalc::post_integrate()
+{
+
+  tagint imol;
+  double massone;
+  double unwrap[3];
+
+
+  //invoked_array = update->ntimestep;
+  for (int i = 0; i < nmolecules; i++)
+    com_H[i][0] = com_H[i][1] = com_H[i][2] = 0.0;
+
+  double **x = atom->x;
+  int *mask = atom->mask;
+  tagint *molecule = atom->molecule;
+  int *type = atom->type;
+  imageint *image = atom->image;
+  double *mass = atom->mass;
+  double *rmass = atom->rmass;
+  int nlocal = atom->nlocal;
+
+  double *lambdaH = atom->lambdaH;
+  double **gradlambdaH = atom->gradlambdaH;
+  double **comH = atom->comH;
+
+  int This_Step = update->ntimestep;
+  if(This_Step >= Density_Update_Time_Begin && This_Step <= Density_Update_Time_End && Density_Comp_Flag == 1){
+      Density_Compensation_Run = 1;
+      if(me==0 && This_Step == Density_Update_Time_Begin){
+          if(screen)fprintf(screen,"\nStart of constant-density route\n");
+          if(logfile)fprintf(logfile,"\nStart of constant-density route\n");
+          Clear_File_Compensation_Density();
+      }
+  }
+
+
+  for (int i = 0; i < nlocal; i++)
+    if (mask[i] & groupbit) {
+
+        if (rmass) massone = rmass[i];
+        else massone = mass[type[i]];
+        imol = molecule[i];
+        if (molmap_H) imol = molmap_H[imol-idlo];
+        else imol--;
+        domain->unmap(x[i],image[i],unwrap);
+        massone /= masstotal_H[imol];
+
+        com_H[imol][0] += unwrap[0] * massone;
+        com_H[imol][1] += unwrap[1] * massone;
+        com_H[imol][2] += unwrap[2] * massone;
+    }
+
+
+  MPI_Allreduce(&com_H[0][0],&comall_H[0][0],3*nmolecules,MPI_DOUBLE,MPI_SUM,world);
+
+
+  double xtmp,ytmp,ztmp;
+  double delx,dely,delz;
+  double Grad_Factor;
+  double rdiff;
+
+  for (int i = 0; i < nmolecules; i++){
+
+
+      domain->remap(comall_H[i]);
+
+      if(Hybrid_Style==0){
+          xtmp = comall_H[i][0];
+
+         if(xtmp < R_Start_Hybrid_1){
+             lambdaCM[i] = 0.0;
+             gradlambdaCM[i][0] = 0.0;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+
+         }
+         else if(xtmp >= R_Start_Hybrid_1 && xtmp < R_Start_Hybrid_1+Length_Hyb){
+             cosx=cos(MY_PI*(xtmp-R_Start_Hybrid_1+Length_Hyb)/(2.0*Length_Hyb));
+             sinx=sin(MY_PI*(xtmp-R_Start_Hybrid_1+Length_Hyb)/(2.0*Length_Hyb));
+             lambdaCM[i] = cosx * cosx;
+             gradlambdaCM[i][0] = -(MY_PI/Length_Hyb) * sinx * cosx;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+
+         }
+         else if(xtmp >=R_Start_Hybrid_1+Length_Hyb && xtmp < R_Start_Hybrid_2){
+             lambdaCM[i] = 1.0;
+             gradlambdaCM[i][0] = 0.0;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+
+         }
+         else if(xtmp >= R_Start_Hybrid_2 && xtmp < R_Start_Hybrid_2+Length_Hyb){
+             cosx = cos(MY_PI*(xtmp-R_Start_Hybrid_2)/(2.0*Length_Hyb));
+             sinx = sin(MY_PI*(xtmp-R_Start_Hybrid_2)/(2.0*Length_Hyb));
+             lambdaCM[i] = cosx * cosx;
+             gradlambdaCM[i][0] = -(MY_PI/Length_Hyb) * sinx * cosx;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+
+         }
+         else if(xtmp >=R_Start_Hybrid_2+Length_Hyb){
+             lambdaCM[i] = 0.0;
+             gradlambdaCM[i][0] = 0.0;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+
+         }
+    }
+
+      else if(Hybrid_Style==1){
+          xtmp = comall_H[i][0];
+          ytmp = comall_H[i][1];
+          ztmp = comall_H[i][2];
+
+          delx = (xtmp-center_box[0]);
+          dely = (ytmp-center_box[1]);
+          delz = (ztmp-center_box[2]);
+
+          r = sqrt(delx*delx+dely*dely+delz*delz);
+
+         if(r < S_Start_Hybrid){
+             lambdaCM[i] = 1.0;
+             gradlambdaCM[i][0] = 0.0;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+         }
+         else if(r >= S_Start_Hybrid && r < S_Start_Hybrid+Length_Hyb) {
+             rdiff = MY_PI*(r-S_Start_Hybrid)/(2.0*Length_Hyb);
+             cosr=cos(rdiff);
+             sinr=sin(rdiff);
+             lambdaCM[i] = cosr * cosr;
+             Grad_Factor = -MY_PI * sinr * cosr / (Length_Hyb * r);
+             gradlambdaCM[i][0] = Grad_Factor * delx;
+             gradlambdaCM[i][1] = Grad_Factor * dely;
+             gradlambdaCM[i][2] = Grad_Factor * delz;
+         }
+         else if(r >= S_Start_Hybrid+Length_Hyb){
+             lambdaCM[i] = 0.0;
+             gradlambdaCM[i][0] = 0.0;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+         }
+    }
+
+      else if(Hybrid_Style==2){
+
+          xtmp = comall_H[i][0];
+          ytmp = comall_H[i][1];
+
+          delx = (xtmp-center_box[0]);
+          dely = (ytmp-center_box[1]);
+
+          r = sqrt(delx*delx+dely*dely);
+
+         if(r < S_Start_Hybrid){
+             lambdaCM[i] = 1.0;
+             gradlambdaCM[i][0] = 0.0;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+         }
+         else if(r >= S_Start_Hybrid && r < S_Start_Hybrid+Length_Hyb) {
+             rdiff = MY_PI*(r-S_Start_Hybrid)/(2.0*Length_Hyb);
+             cosr=cos(rdiff);
+             sinr=sin(rdiff);
+             lambdaCM[i] = cosr * cosr;
+             Grad_Factor = -MY_PI * sinr * cosr / (Length_Hyb * r);
+
+             gradlambdaCM[i][0] = Grad_Factor * delx;
+             gradlambdaCM[i][1] = Grad_Factor * dely;
+             gradlambdaCM[i][2] = 0.0;
+         }
+         else if(r >= S_Start_Hybrid+Length_Hyb){
+             lambdaCM[i] = 0.0;
+             gradlambdaCM[i][0] = 0.0;
+             gradlambdaCM[i][1] = 0.0;
+             gradlambdaCM[i][2] = 0.0;
+         }
+    }
+
+
+}
+
+  int ibin,imoltypeH;
+  int *moltypeH = atom->moltypeH;
+
+  for (int i = 0; i < nlocal; i++)
+        if (mask[i] & groupbit)
+        {
+            imol = molecule[i];
+            imoltypeH = moltypeH[i];
+            if (molmap_H) imol = molmap_H[imol-idlo];
+            else imol--;
+            lambdaH[i] = lambdaCM[imol];
+            gradlambdaH[i][0] = gradlambdaCM[imol][0];
+            gradlambdaH[i][1] = gradlambdaCM[imol][1];
+            gradlambdaH[i][2] = gradlambdaCM[imol][2];
+//            if(gradlambdaH[i][2]!=0) printf("gradlambdaH[i][2] = %f\n",gradlambdaH[i][2]);
+
+//            gradlambdaH[i][2] = 0.0;
+            //gradlambdaH[i] = 0;
+//              if(replambdaH[i] == 1){
+                    comH[i][0] = comall_H[imol][0];
+                    comH[i][1] = comall_H[imol][1];
+                    comH[i][2] = comall_H[imol][2];
+//              }
+
+        if(Density_Comp_Flag != 0 && Density_Compensation_Run != 0){
+
+            if(Hybrid_Style==0){
+//                xtmp = comall_H[imol][0]-x0lo;
+                xtmp = comH[i][0]-x0lo;
+//                if(xtmp <= 0.5*x0BoxSize)ibin = floor(xtmp/Density_Bin_Size);
+//                else ibin = floor((x0BoxSize-xtmp)/Density_Bin_Size);
+
+                ibin = floor(xtmp/Density_Bin_Size);
+
+            }
+
+            else if(Hybrid_Style==1){
+                xtmp = comall_H[imol][0];
+                ytmp = comall_H[imol][1];
+                ztmp = comall_H[imol][2];
+
+                delx = (xtmp-center_box[0]);
+                dely = (ytmp-center_box[1]);
+                delz = (ztmp-center_box[2]);
+
+                r = sqrt(delx*delx+dely*dely+delz*delz);
+                ibin = floor(r/Density_Bin_Size);
+            }
+
+            else if(Hybrid_Style==2){
+
+                xtmp = comall_H[imol][0];
+                ytmp = comall_H[imol][1];
+
+                delx = (xtmp-center_box[0]);
+                dely = (ytmp-center_box[1]);
+
+                r = sqrt(delx*delx+dely*dely);
+                ibin = floor(r/Density_Bin_Size);
+             }
+
+            if(ibin>=Density_Bin_Num)ibin = Density_Bin_Num - 1;
+            Comp_Density_Num_H[ibin][imoltypeH-1]++;
+
+        }
+
+        }
+
+
+//  int Middle_Bin_Num = (Density_Bin_Num-1) / 2;
+
+//  if(Hybrid_Style == 0)for(int i = Middle_Bin_Num+1;i < Density_Bin_Num; i++)Comp_Density_Num_H[i] = Comp_Density_Num_H[Density_Bin_Num-1-i];
+  if(Density_Compensation_Run)Density_Counter_H++;
+
+        double Density_Bin_Vol, exponent;
+        double Normalization;
+        int jmin, jmax,jj;
+        if(This_Step % Density_Update_Frequency == 0 && Density_Comp_Flag != 0 && Density_Compensation_Run != 0){
+
+      //   if(atom->nmoltypesH ==1)   MPI_Allreduce(&Comp_Density_Num_H[0][0],&Comp_Density_Num_all_H[0][0],Density_Bin_Num,MPI_INT,MPI_SUM,world);
+        MPI_Allreduce(&Comp_Density_Num_H[0][0],&Comp_Density_Num_all_H[0][0],Density_Bin_Num*(atom->nmoltypesH+1),MPI_INT,MPI_SUM,world);
+
+        if(Hybrid_Style == 0)Density_Bin_Vol = 1.0*Density_Bin_Size * (x1hi-x1lo) * (x2hi-x2lo);
+
+        for(int i = 0; i < Density_Bin_Num; i++){
+            if(Hybrid_Style == 1)Density_Bin_Vol = (4.0/3.0) * MY_PI * (pow(((i+1) * Density_Bin_Size),3.0) - pow((i * Density_Bin_Size),3.0));
+            if(Hybrid_Style == 2)Density_Bin_Vol = 4.0 * MY_PI * (x2hi-x2lo) * (pow(((i+1) * Density_Bin_Size),2.0) - pow((i * Density_Bin_Size),2.0));
+            for(int j = 0; j < atom->nmoltypesH; j++){
+                Mean_Density_H[i][j] = Comp_Density_Num_all_H[i][j] / (Density_Counter_H * Density_Bin_Vol);
+            }
+        }
+
+        Density_Counter_H = 0;
+
+        for(int k = 0; k < atom->nmoltypesH;k++){
+            for(int i = 0;i < Density_Bin_Num; i++){
+                Normalization = 0;
+                jmin = i - Density_Gauss_Int_Range*floor(Density_Sigma_Gauss / Density_Bin_Size);
+                jmax = i + Density_Gauss_Int_Range*floor(Density_Sigma_Gauss / Density_Bin_Size);
+                Mean_Comp_Density_Conv_H[i][k] = 0;
+                    if(Hybrid_Style != 0){
+                        if(jmin<0)jmin=0;
+                        if(jmax>=Density_Bin_Num)jmax=Density_Bin_Num-1;
+                    }
+
+                for(int j = jmin;j <= jmax; j++){
+                    jj = j;
+                    if(Hybrid_Style == 0){
+                            if(j < 0)jj = Density_Bin_Num + j;
+                            if(j >= Density_Bin_Num)jj = j - Density_Bin_Num;
+                    }
+                    exponent = (i-j)*Density_Bin_Size/Density_Sigma_Gauss;
+                    exponent = pow(exponent,2.0);
+                    Normalization += exp(-exponent)*Density_Bin_Size;
+                    Mean_Comp_Density_Conv_H[i][k] += Mean_Density_H[jj][k] * exp(-exponent)*Density_Bin_Size;
+    //                    Mean_Comp_Density_Conv_H[i] += Mean_Density_H[j] * exp(-exponent);
+                }
+                Mean_Comp_Density_Conv_H[i][k] /= Normalization;
+
+                }
+            }
+
+            Density_Fluctuation = 0;
+            for(int k = 0; k < atom->nmoltypesH;k++)for(int i = 0;i < Density_Bin_Num; i++)Density_Fluctuation += (Density_Bin_Size/x0BoxSize)*pow((Mean_Density_H[i][k]-Density_Ref)/Density_Ref,2.0);
+            for(int k = 0; k < atom->nmoltypesH;k++)
+                for(int i = 1;i < Density_Bin_Num-1; i++)
+                    grad_Comp_Density_Conv_H[i][k] = Comp_Density_Scaling_factor_H * (Mean_Comp_Density_Conv_H[i+1][k] - Mean_Comp_Density_Conv_H[i-1][k])/(2*Density_Bin_Size*Density_Ref);
+
+
+            //for(int i = 1;i < Density_Bin_Num-1; i++)Mean_grad_Comp_Density_Conv_H[i] = (Comp_Counter_H * Mean_grad_Comp_Density_Conv_H[i] + grad_Comp_Density_Conv_H[i]) / (Comp_Counter_H + 1);
+            for(int k = 0; k < atom->nmoltypesH;k++)
+                for(int i = 1;i < Density_Bin_Num-1; i++)
+                    Mean_grad_Comp_Density_Conv_H[i][k] +=  grad_Comp_Density_Conv_H[i][k];
+
+//            for(int i = Middle_Bin_Num+1;i < Density_Bin_Num; i++)Comp_Density_Num_H[i] = Comp_Density_Num_H[Density_Bin_Num-1-i];
+
+            for(int k = 0; k < atom->nmoltypesH;k++)
+                for(int i = 0;i < Density_Bin_Num; i++)
+                    Int_Mean_Density_H[i][k]=0;
+
+            for(int k = 0; k < atom->nmoltypesH;k++)
+                for(int i = 0;i < Density_Bin_Num; i++)
+                    for(int j = 0;j <= i; j++)
+                        Int_Mean_Density_H[i][k] += Mean_grad_Comp_Density_Conv_H[j][k] * Density_Bin_Size;
+
+                        Comp_Counter_H += 1;
+
+            for(int k = 0; k < atom->nmoltypesH;k++)
+                for(int i = 0;i < Density_Bin_Num; i++){
+                    Comp_Density_Num_H[i][k] = 0;
+                    Comp_Density_Num_all_H[i][k] = 0;
+                }
+
+
+          }
+
+        if(This_Step == Density_Update_Time_End && Density_Compensation_Run != 0){
+            Density_Compensation_Run = 0;
+            if(me==0){
+                if(screen)fprintf(screen,"\nEnd of constant-density route\n");
+                if(logfile)fprintf(logfile,"\nEnd of constant-density route\n");
+            }
+        }
+
+        if (me == 0 && This_Step % Density_Update_Frequency == 0 && Density_Compensation_Run != 0) Print_Compensation_Density();
+
+}
+
+
+double FixLambdaHCalc::memory_usage()
+{
+  double bytes = (bigint) nmolecules * 2 * sizeof(double);
+  if (molmap_H) bytes += (idhi-idlo+1) * sizeof(int);
+  bytes += (bigint) nmolecules * 2*3 * sizeof(double);
+  bytes += (bigint) nmolecules * 2*3 * sizeof(double);
+  return bytes;
+}
+
+/* ---------------------------------------------------------------------- */
+
+
+int FixLambdaHCalc::molecules_in_group(tagint &idlo, tagint &idhi)
+{
+  int i;
+
+  memory->destroy(molmap_H);
+  molmap_H = NULL;
+
+  // find lo/hi molecule ID for any atom in group
+  // warn if atom in group has ID = 0
+
+  tagint *molecule = atom->molecule;
+  int *mask = atom->mask;
+  int nlocal = atom->nlocal;
+
+  tagint lo = BIG;
+  tagint hi = -BIG;
+  int flag = 0;
+  for (i = 0; i < nlocal; i++)
+  {
+    if (mask[i] & groupbit) {
+      if (molecule[i] == 0) flag = 1;
+      lo = MIN(lo,molecule[i]);
+      hi = MAX(hi,molecule[i]);
+    }
+  }
+
+  int flagall;
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,"Atom with molecule ID = 0 included in "
+                   "compute molecule group");
+
+  MPI_Allreduce(&lo,&idlo,1,MPI_LMP_TAGINT,MPI_MIN,world);
+  MPI_Allreduce(&hi,&idhi,1,MPI_LMP_TAGINT,MPI_MAX,world);
+  if (idlo == BIG) return 0;
+
+  // molmap = vector of length nlen
+  // set to 1 for IDs that appear in group across all procs, else 0
+
+  tagint nlen_tag = idhi-idlo+1;
+  if (nlen_tag > MAXSMALLINT)
+    error->all(FLERR,"Too many molecules for compute");
+  int nlen = (int) nlen_tag;
+
+  memory->create(molmap_H,nlen,"lambdaH/calc:molmap");
+  for (i = 0; i < nlen; i++) molmap_H[i] = 0;
+
+  for (i = 0; i < nlocal; i++)
+    if (mask[i] & groupbit)
+      molmap_H[molecule[i]-idlo] = 1;
+
+  int *molmapall;
+  memory->create(molmapall,nlen,"compute:molmapall");
+  MPI_Allreduce(molmap_H,molmapall,nlen,MPI_INT,MPI_MAX,world);
+
+  // nmolecules = # of non-zero IDs in molmap
+  // molmap[i] = index of molecule, skipping molecules not in group with -1
+
+  int nmolecules = 0;
+  for (i = 0; i < nlen; i++)
+    if (molmapall[i]) molmap_H[i] = nmolecules++;
+    else molmap_H[i] = -1;
+  memory->destroy(molmapall);
+
+  // warn if any molecule has some atoms in group and some not in group
+
+  flag = 0;
+  for (i = 0; i < nlocal; i++) {
+    if (mask[i] & groupbit) continue;
+    if (molecule[i] < idlo || molecule[i] > idhi) continue;
+    if (molmap_H[molecule[i]-idlo] >= 0) flag = 1;
+  }
+
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,
+                   "One or more compute molecules has atoms not in group");
+
+  // if molmap simply stores 1 to Nmolecules, then free it
+
+  if (idlo == 1 && idhi == nmolecules && nlen == nmolecules) {
+    memory->destroy(molmap_H);
+    molmap_H = NULL;
+  }
+  return nmolecules;
+}
+
+
+void FixLambdaHCalc::Print_Compensation_Density(){
+
+
+    FILE *fp1;
+    fp1 = fopen("Mean_Comp_Density.txt","w");
+
+    if (fp1 == NULL) {
+        char str[128];
+        sprintf(str,"Cannot open fix Mean_Comp_Density file %s","Mean_Comp_Density.txt");
+        error->one(FLERR,str);
+    }
+
+
+    for(int i = 0;i < Density_Bin_Num; i++){
+        fprintf(fp1,"%d",i+1);
+        for(int k = 0; k < atom->nmoltypesH;k++)
+            fprintf(fp1,"\t%.10f",Mean_grad_Comp_Density_Conv_H[i][k]);
+        fprintf(fp1,"\n");
+    }
+    fclose(fp1);
+
+    /*
+    FILE *fp2;
+
+    char filename2[1000];
+    sprintf(filename2, "Mean_Comp_Density%4.1f_%d.txt", Comp_Density_Scaling_factor_H,Density_Update_Frequency);
+
+    fp2 = fopen(filename2,"a");
+
+    if (fp2 == NULL) {
+        char str[128];
+        sprintf(str,"Cannot open fix Mean_Comp_Density file %s","Mean_Comp_Density.txt");
+        error->one(FLERR,str);
+    }
+
+    printf("Density_Fluctuation = %f\n",Density_Fluctuation);
+
+    double x0;
+    if(Hybrid_Style==0)x0=x0lo;
+    else x0=0;
+
+    for(int i = 0;i < Density_Bin_Num; i++){
+        fprintf(fp2,"%d\t %.10f\t",i+1,i*Density_Bin_Size+x0);
+        for(int k = 0; k < atom->nmoltypesH;k++)
+            fprintf(fp2,"\t%.10f\t %.10f\t %.10f\t %.10f",Mean_Comp_Density_Conv_H[i][k],grad_Comp_Density_Conv_H[i][k],Mean_grad_Comp_Density_Conv_H[i][k]);
+        fprintf(fp2,"\n");
+
+    }
+    fclose(fp2);
+
+
+    FILE *fp3;
+    char filename3[1000];
+    sprintf(filename3, "Density_Fluctuation%4.1f_%d.txt", Comp_Density_Scaling_factor_H,Density_Update_Frequency);
+
+    fp3 = fopen(filename3,"a");
+
+    if (fp3 == NULL) {
+        char str[128];
+        sprintf(str,"Cannot open fix Density_Fluctuation file %s","Density_Fluctuation.txt");
+        error->one(FLERR,str);
+    }
+
+    int This_Step = update->ntimestep;
+    fprintf(fp3,"%d %.10f\n",This_Step,Density_Fluctuation);
+
+    fclose(fp3);
+
+*/
+}
+
+void FixLambdaHCalc::Clear_File_Compensation_Density(){
+
+    FILE *fp1;
+    fp1 = fopen("Mean_Comp_Density.txt","w");
+
+    if (fp1 == NULL) {
+        char str[128];
+        sprintf(str,"Cannot open fix Mean_Comp_Density file %s","Mean_Comp_Density.txt");
+        error->one(FLERR,str);
+    }
+
+
+    fclose(fp1);
+
+    /*
+    FILE *fp2;
+
+    char filename2[1000];
+    sprintf(filename2, "Mean_Comp_Density%4.1f_%d.txt", Comp_Density_Scaling_factor_H,Density_Update_Frequency);
+
+    fp2 = fopen(filename2,"w");
+
+    if (fp2 == NULL) {
+        char str[128];
+        sprintf(str,"Cannot open fix Mean_Comp_Density file %s","Mean_Comp_Density.txt");
+        error->one(FLERR,str);
+    }
+
+
+   fclose(fp2);
+
+   FILE *fp3;
+   char filename3[1000];
+   sprintf(filename3, "Density_Fluctuation%4.1f_%d.txt", Comp_Density_Scaling_factor_H,Density_Update_Frequency);
+
+   fp3 = fopen(filename3,"w");
+
+   if (fp3 == NULL) {
+       char str[128];
+       sprintf(str,"Cannot open fix Density_Fluctuation file %s","Density_Fluctuation.txt");
+       error->one(FLERR,str);
+   }
+
+   fclose(fp3);
+    */
+
+}
+
+void FixLambdaHCalc::Load_Compensation_Density(){
+
+    if(me == 0){
+        FILE *fp1;
+        char str[128];
+
+        fp1 = fopen("Mean_Comp_Density.txt","r");
+        if (fp1 == NULL) {
+            sprintf(str,"Cannot open fix Mean_Comp_Density.txt file %s","Mean_Comp_Density.txt");
+            error->one(FLERR,str);
+        }
+
+        int i1;
+        float i2;
+
+        while (!feof(fp1)){
+            fscanf (fp1,"%d",&i1);
+            for(int k = 0; k < atom->nmoltypesH;k++){
+                fscanf (fp1,"\t%f",&i2);
+                Mean_grad_Comp_Density_Conv_H[i1-1][k] = (double) i2;
+            }
+            fscanf (fp1,"\n");
+
+                if(i1 > Density_Bin_Num){
+                    sprintf(str,"Density bin number mismatches %d != %d",Density_Bin_Num,i1);
+                    error->one(FLERR,str);
+                }
+
+        }
+
+        fclose(fp1);
+
+
+        if(me==0){
+            if(screen)fprintf(screen,"\n\nDensity componsation forces distributed successfully!\n\n");
+            if(logfile)fprintf(logfile,"\n\nDensity componsation forces distributed successfully!\n\n");
+        }
+    }
+
+    MPI_Bcast(Mean_grad_Comp_Density_Conv_H,Density_Bin_Num*(atom->nmoltypesH+1),MPI_DOUBLE,0,world);
+
+}
diff --git a/src/USER-HADRESS/fix_lambdah_calc.h b/src/USER-HADRESS/fix_lambdah_calc.h
new file mode 100644
index 000000000..d3552e17f
--- /dev/null
+++ b/src/USER-HADRESS/fix_lambdah_calc.h
@@ -0,0 +1,102 @@
+/* -*- 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(lambdah/calc,FixLambdaHCalc)
+
+#else
+
+#ifndef LMP_FIX_LAMBDAH_CALC_H
+#define LMP_FIX_LAMBDAH_CALC_H
+
+#include "fix.h"
+
+namespace LAMMPS_NS {
+
+class FixLambdaHCalc : public Fix {
+ public:
+  FixLambdaHCalc(class LAMMPS *, int, char **);
+  ~FixLambdaHCalc();
+  int setmask();
+  void init();
+  void setup(int);
+
+  void post_integrate();
+  double memory_usage();
+
+
+ double Length_Hyb,Length_ATRegion,Length_CGRegion;
+ int Hybrid_Style;
+ int Pressure_Comp_Flag,Pressure_Bin_Num,Pressure_Update_Frequency,Pressure_Update_Time_End, Pressure_Update_Time_Begin;
+ double Pressure_lambda_Increment;
+ int Density_Comp_Flag,Density_Compensation_Run,Density_Bin_Num,Density_Update_Frequency,Density_Update_Time_End,Density_Update_Time_Begin;
+ double Density_Bin_Size;
+ int Comp_Counter_H,Density_Counter_H;
+ double **Mean_grad_Comp_Density_Conv_H;
+
+ double Density_Ref;
+ double center_box[3];
+ int me;
+ double x0lo,x0hi,x1lo,x1hi,x2lo,x2hi,x0BoxSize;
+ double Density_Sigma_Gauss;
+ double Comp_Density_Scaling_factor_H;
+ int Density_Gauss_Int_Range;
+
+ double xmin_AT,xmax_AT;
+ private:
+ int nmolecules;
+ tagint idlo,idhi;
+ double *massproc_H,*masstotal_H;
+ double **com_H,**comall_H;
+ double Density_Fluctuation;
+ int **Comp_Density_Num_H, **Comp_Density_Num_all_H;
+ double **Int_Mean_Density_H, **Mean_Density_H, **grad_Comp_Density_Conv_H, **Mean_Comp_Density_Conv_H;
+ int Load_File_Flag;
+ double R_Start_Hybrid_1,R_Start_Hybrid_2,S_Start_Hybrid,r,cosr,sinr,sinx,cosx;
+ double *lambdaCM, **gradlambdaCM;
+ int *molmap_H;                 // convert molecule ID to local index
+
+ int molecules_in_group(tagint &, tagint &);
+
+ void Print_Compensation_Density();
+ void Load_Compensation_Density();
+ void Clear_File_Compensation_Density();
+};
+
+}
+
+#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: Variable name for fix indent does not exist
+
+Self-explanatory.
+
+E: Variable for fix indent is invalid style
+
+Only equal-style variables can be used.
+
+E: Variable for fix indent is not equal style
+
+Only equal-style variables can be used.
+
+*/
diff --git a/src/USER-HADRESS/molecule.cpp b/src/USER-HADRESS/molecule.cpp
new file mode 100644
index 000000000..89ca26d05
--- /dev/null
+++ b/src/USER-HADRESS/molecule.cpp
@@ -0,0 +1,1829 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain 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 "molecule.h"
+#include "atom.h"
+#include "atom_vec.h"
+#include "atom_vec_body.h"
+#include "force.h"
+#include "comm.h"
+#include "domain.h"
+#include "math_extra.h"
+#include "math_const.h"
+#include "memory.h"
+#include "error.h"
+
+using namespace LAMMPS_NS;
+using namespace MathConst;
+
+#define MAXLINE 256
+#define EPSILON 1.0e-7
+#define BIG 1.0e20
+
+#define SINERTIA 0.4            // moment of inertia prefactor for sphere
+
+/* ---------------------------------------------------------------------- */
+
+Molecule::Molecule(LAMMPS *lmp, int narg, char **arg, int &index) :
+  Pointers(lmp)
+{
+  me = comm->me;
+
+  if (index >= narg) error->all(FLERR,"Illegal molecule command");
+
+  int n = strlen(arg[0]) + 1;
+  id = new char[n];
+  strcpy(id,arg[0]);
+
+  for (int i = 0; i < n-1; i++)
+    if (!isalnum(id[i]) && id[i] != '_')
+      error->all(FLERR,"Molecule template ID must be "
+                 "alphanumeric or underscore characters");
+
+  // parse args until reach unknown arg (next file)
+
+  toffset = 0;
+  boffset = aoffset = doffset = ioffset = 0;
+  sizescale = 1.0;
+
+  int ifile = index;
+  int iarg = ifile+1;
+
+  while (iarg < narg) {
+    if (strcmp(arg[iarg],"offset") == 0) {
+      if (iarg+6 > narg) error->all(FLERR,"Illegal molecule command");
+      toffset = force->inumeric(FLERR,arg[iarg+1]);
+      boffset = force->inumeric(FLERR,arg[iarg+2]);
+      aoffset = force->inumeric(FLERR,arg[iarg+3]);
+      doffset = force->inumeric(FLERR,arg[iarg+4]);
+      ioffset = force->inumeric(FLERR,arg[iarg+5]);
+      if (toffset < 0 || boffset < 0 || aoffset < 0 ||
+          doffset < 0 || ioffset < 0)
+        error->all(FLERR,"Illegal molecule command");
+      iarg += 6;
+    } else if (strcmp(arg[iarg],"toff") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal molecule command");
+      toffset = force->inumeric(FLERR,arg[iarg+1]);
+      if (toffset < 0) error->all(FLERR,"Illegal molecule command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"boff") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal molecule command");
+      boffset = force->inumeric(FLERR,arg[iarg+1]);
+      if (boffset < 0) error->all(FLERR,"Illegal molecule command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"aoff") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal molecule command");
+      aoffset = force->inumeric(FLERR,arg[iarg+1]);
+      if (aoffset < 0) error->all(FLERR,"Illegal molecule command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"doff") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal molecule command");
+      doffset = force->inumeric(FLERR,arg[iarg+1]);
+      if (doffset < 0) error->all(FLERR,"Illegal molecule command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"ioff") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal molecule command");
+      ioffset = force->inumeric(FLERR,arg[iarg+1]);
+      if (ioffset < 0) error->all(FLERR,"Illegal molecule command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"scale") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal molecule command");
+      sizescale = force->numeric(FLERR,arg[iarg+1]);
+      if (sizescale <= 0.0) error->all(FLERR,"Illegal molecule command");
+      iarg += 2;
+    } else break;
+  }
+
+  index = iarg;
+
+  // last molecule if have scanned all args
+
+  if (iarg == narg) last = 1;
+  else last = 0;
+
+  // initialize all fields to empty
+
+  initialize();
+
+  // scan file for sizes of all fields and allocate them
+
+  if (me == 0) open(arg[ifile]);
+  read(0);
+  if (me == 0) fclose(fp);
+  allocate();
+
+  // read file again to populate all fields
+
+  if (me == 0) open(arg[ifile]);
+  read(1);
+  if (me == 0) fclose(fp);
+
+  // stats
+
+  if (me == 0) {
+    if (screen)
+      fprintf(screen,"Read molecule %s:\n"
+              "  %d atoms with %d types\n  %d bonds with %d types\n"
+              "  %d angles with %d types\n  %d dihedrals with %d types\n"
+              "  %d impropers with %d types\n",
+              id,natoms,ntypes,
+              nbonds,nbondtypes,nangles,nangletypes,
+              ndihedrals,ndihedraltypes,nimpropers,nimpropertypes);
+    if (logfile)
+      fprintf(logfile,"Read molecule %s:\n"
+              "  %d atoms with %d types\n  %d bonds with %d types\n"
+              "  %d angles with %d types\n  %d dihedrals with %d types\n"
+              "  %d impropers with %d types\n",
+              id,natoms,ntypes,
+              nbonds,nbondtypes,nangles,nangletypes,
+              ndihedrals,ndihedraltypes,nimpropers,nimpropertypes);
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+Molecule::~Molecule()
+{
+  delete [] id;
+  deallocate();
+}
+
+/* ----------------------------------------------------------------------
+   compute center = geometric center of molecule
+   also compute:
+     dx = displacement of each atom from center
+     molradius = radius of molecule from center 
+       including finite-size particles or body particles
+------------------------------------------------------------------------- */
+
+void Molecule::compute_center()
+{
+  if (centerflag) return;
+  centerflag = 1;
+
+  center[0] = center[1] = center[2] = 0.0;
+  for (int i = 0; i < natoms; i++) {
+    center[0] += x[i][0];
+    center[1] += x[i][1];
+    center[2] += x[i][2];
+  }
+  center[0] /= natoms;
+  center[1] /= natoms;
+  center[2] /= natoms;
+
+  memory->destroy(dx);
+  memory->create(dx,natoms,3,"molecule:dx");
+
+  for (int i = 0; i < natoms; i++) {
+    dx[i][0] = x[i][0] - center[0];
+    dx[i][1] = x[i][1] - center[1];
+    dx[i][2] = x[i][2] - center[2];
+  }
+
+  molradius = 0.0;
+  for (int i = 0; i < natoms; i++) {
+    double rad = MathExtra::len3(dx[i]);
+    if (radiusflag) rad += radius[i];
+    molradius = MAX(molradius,rad);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   compute masstotal = total mass of molecule
+   could have been set by user, otherwise calculate it
+------------------------------------------------------------------------- */
+
+void Molecule::compute_mass()
+{
+  if (massflag) return;
+  massflag = 1;
+
+  if (!rmassflag) atom->check_mass();
+
+  masstotal = 0.0;
+  for (int i = 0; i < natoms; i++) {
+    if (rmassflag) masstotal += rmass[i];
+    else masstotal += atom->mass[type[i]];
+  }
+}
+
+/* ----------------------------------------------------------------------
+   compute com = center of mass of molecule
+   could have been set by user, otherwise calculate it
+   works for finite size particles assuming no overlap
+   also compute:
+     dxcom = displacement of each atom from COM
+     comatom = which atom (1-Natom) is nearest the COM
+     maxextent = furthest any atom in molecule is from comatom (not COM)
+------------------------------------------------------------------------- */
+
+void Molecule::compute_com()
+{
+  if (!comflag) {
+    comflag = 1;
+
+    if (!rmassflag) atom->check_mass();
+
+    double onemass;
+    com[0] = com[1] = com[2] = 0.0;
+    for (int i = 0; i < natoms; i++) {
+      if (rmassflag) onemass = rmass[i];
+      else onemass = atom->mass[type[i]];
+      com[0] += x[i][0]*onemass;
+      com[1] += x[i][1]*onemass;
+      com[2] += x[i][2]*onemass;
+    }
+    com[0] /= masstotal;
+    com[1] /= masstotal;
+    com[2] /= masstotal;
+  }
+
+  memory->destroy(dxcom);
+  memory->create(dxcom,natoms,3,"molecule:dxcom");
+
+  for (int i = 0; i < natoms; i++) {
+    dxcom[i][0] = x[i][0] - com[0];
+    dxcom[i][1] = x[i][1] - com[1];
+    dxcom[i][2] = x[i][2] - com[2];
+  }
+
+  double rsqmin = BIG;
+  for (int i = 0; i < natoms; i++) {
+    double rsq = MathExtra::lensq3(dxcom[i]);
+    if (rsq < rsqmin) {
+      comatom = i;
+      rsqmin = rsq;
+    }
+  }
+
+  double rsqmax = 0.0;
+  for (int i = 0; i < natoms; i++) {
+    double dx = x[comatom][0] - x[i][0];
+    double dy = x[comatom][1] - x[i][1];
+    double dz = x[comatom][2] - x[i][2];
+    double rsq = dx*dx + dy*dy + dz*dz;
+    rsqmax = MAX(rsqmax,rsq);
+  }
+
+  comatom++;
+  maxextent = sqrt(rsqmax);
+}
+
+/* ----------------------------------------------------------------------
+   compute itensor = 6 moments of inertia of molecule around xyz axes
+   could have been set by user, otherwise calculate it
+   accounts for finite size spheres, assuming no overlap
+   also compute:
+     inertia = 3 principal components of inertia
+     ex,ey,ez = principal axes in space coords
+     quat = quaternion for orientation of molecule
+     dxbody = displacement of each atom from COM in body frame
+------------------------------------------------------------------------- */
+
+void Molecule::compute_inertia()
+{
+  if (!inertiaflag) {
+    inertiaflag = 1;
+
+    if (!rmassflag) atom->check_mass();
+
+    double onemass,dx,dy,dz;
+    for (int i = 0; i < 6; i++) itensor[i] = 0.0;
+    for (int i = 0; i < natoms; i++) {
+      if (rmassflag) onemass = rmass[i];
+      else onemass = atom->type[type[i]];
+      dx = dxcom[i][0];
+      dy = dxcom[i][1];
+      dz = dxcom[i][2];
+      itensor[0] += onemass * (dy*dy + dz*dz);
+      itensor[1] += onemass * (dx*dx + dz*dz);
+      itensor[2] += onemass * (dx*dx + dy*dy);
+      itensor[3] -= onemass * dy*dz;
+      itensor[4] -= onemass * dx*dz;
+      itensor[5] -= onemass * dx*dy;
+    }
+
+    if (radiusflag) {
+      for (int i = 0; i < natoms; i++) {
+        if (rmassflag) onemass = rmass[i];
+        else onemass = atom->type[type[i]];
+        itensor[0] += SINERTIA*onemass * radius[i]*radius[i];
+        itensor[1] += SINERTIA*onemass * radius[i]*radius[i];
+        itensor[2] += SINERTIA*onemass * radius[i]*radius[i];
+      }
+    }
+  }
+
+  // diagonalize inertia tensor for each body via Jacobi rotations
+  // inertia = 3 eigenvalues = principal moments of inertia
+  // evectors and exzy = 3 evectors = principal axes of rigid body
+
+  double cross[3];
+  double tensor[3][3],evectors[3][3];
+
+  tensor[0][0] = itensor[0];
+  tensor[1][1] = itensor[1];
+  tensor[2][2] = itensor[2];
+  tensor[1][2] = tensor[2][1] = itensor[3];
+  tensor[0][2] = tensor[2][0] = itensor[4];
+  tensor[0][1] = tensor[1][0] = itensor[5];
+
+  if (MathExtra::jacobi(tensor,inertia,evectors))
+    error->all(FLERR,"Insufficient Jacobi rotations for rigid molecule");
+
+  ex[0] = evectors[0][0];
+  ex[1] = evectors[1][0];
+  ex[2] = evectors[2][0];
+  ey[0] = evectors[0][1];
+  ey[1] = evectors[1][1];
+  ey[2] = evectors[2][1];
+  ez[0] = evectors[0][2];
+  ez[1] = evectors[1][2];
+  ez[2] = evectors[2][2];
+
+  // if any principal moment < scaled EPSILON, set to 0.0
+
+  double max;
+  max = MAX(inertia[0],inertia[1]);
+  max = MAX(max,inertia[2]);
+
+  if (inertia[0] < EPSILON*max) inertia[0] = 0.0;
+  if (inertia[1] < EPSILON*max) inertia[1] = 0.0;
+  if (inertia[2] < EPSILON*max) inertia[2] = 0.0;
+
+  // enforce 3 evectors as a right-handed coordinate system
+  // flip 3rd vector if needed
+
+  MathExtra::cross3(ex,ey,cross);
+  if (MathExtra::dot3(cross,ez) < 0.0) MathExtra::negate3(ez);
+
+  // create quaternion
+
+  MathExtra::exyz_to_q(ex,ey,ez,quat);
+
+  // compute displacements in body frame defined by quat
+
+  memory->destroy(dxbody);
+  memory->create(dxbody,natoms,3,"molecule:dxbody");
+
+  for (int i = 0; i < natoms; i++)
+    MathExtra::transpose_matvec(ex,ey,ez,dxcom[i],dxbody[i]);
+}
+
+/* ----------------------------------------------------------------------
+   read molecule info from file
+   flag = 0, just scan for sizes of fields
+   flag = 1, read and store fields
+------------------------------------------------------------------------- */
+
+void Molecule::read(int flag)
+{
+  char line[MAXLINE],keyword[MAXLINE];
+  char *eof,*ptr;
+
+  // skip 1st line of file
+
+  if (me == 0) {
+    eof = fgets(line,MAXLINE,fp);
+    if (eof == NULL) error->one(FLERR,"Unexpected end of molecule file");
+  }
+
+  // read header lines
+  // skip blank lines or lines that start with "#"
+  // stop when read an unrecognized line
+
+  while (1) {
+
+    readline(line);
+
+    // trim anything from '#' onward
+    // if line is blank, continue
+
+    if ((ptr = strchr(line,'#'))) *ptr = '\0';
+    if (strspn(line," \t\n\r") == strlen(line)) continue;
+
+    // search line for header keywords and set corresponding variable
+
+    if (strstr(line,"atoms")) sscanf(line,"%d",&natoms);
+    else if (strstr(line,"bonds")) sscanf(line,"%d",&nbonds);
+    else if (strstr(line,"angles")) sscanf(line,"%d",&nangles);
+    else if (strstr(line,"dihedrals")) sscanf(line,"%d",&ndihedrals);
+    else if (strstr(line,"impropers")) sscanf(line,"%d",&nimpropers);
+
+    else if (strstr(line,"mass")) {
+      massflag = 1;
+      sscanf(line,"%lg",&masstotal);
+      masstotal *= sizescale*sizescale*sizescale;
+    }
+    else if (strstr(line,"com")) {
+      comflag = 1;
+      sscanf(line,"%lg %lg %lg",&com[0],&com[1],&com[2]);
+      com[0] *= sizescale;
+      com[1] *= sizescale;
+      com[2] *= sizescale;
+      if (domain->dimension == 2 && com[2] != 0.0)
+        error->all(FLERR,"Molecule file z center-of-mass must be 0.0 for 2d");
+    }
+    else if (strstr(line,"inertia")) {
+      inertiaflag = 1;
+      sscanf(line,"%lg %lg %lg %lg %lg %lg",
+             &itensor[0],&itensor[1],&itensor[2],
+             &itensor[3],&itensor[4],&itensor[5]);
+      itensor[0] *= sizescale*sizescale*sizescale*sizescale*sizescale;
+      itensor[1] *= sizescale*sizescale*sizescale*sizescale*sizescale;
+      itensor[2] *= sizescale*sizescale*sizescale*sizescale*sizescale;
+      itensor[3] *= sizescale*sizescale*sizescale*sizescale*sizescale;
+      itensor[4] *= sizescale*sizescale*sizescale*sizescale*sizescale;
+      itensor[5] *= sizescale*sizescale*sizescale*sizescale*sizescale;
+    }
+    else if (strstr(line,"body")) {
+      bodyflag = 1;
+      avec_body = (AtomVecBody *) atom->style_match("body");
+      if (!avec_body) 
+        error->all(FLERR,"Molecule file requires atom style body");
+      sscanf(line,"%d %d",&nibody,&ndbody);
+    }
+
+    else break;
+  }
+
+  // error checks
+
+  if (natoms < 1) error->all(FLERR,"No count or invalid atom count in molecule file");
+  if (nbonds < 0) error->all(FLERR,"Invalid bond count in molecule file");
+  if (nangles < 0) error->all(FLERR,"Invalid angle count in molecule file");
+  if (ndihedrals < 0)
+    error->all(FLERR,"Invalid dihedral count in molecule file");
+  if (nimpropers < 0)
+    error->all(FLERR,"Invalid improper count in molecule file");
+
+  // count = vector for tallying bonds,angles,etc per atom
+
+  if (flag == 0) memory->create(count,natoms,"molecule:count");
+  else count = NULL;
+
+  // grab keyword and skip next line
+
+  parse_keyword(0,line,keyword);
+  readline(line);
+
+  // loop over sections of molecule file
+
+  while (strlen(keyword)) {
+    if (strcmp(keyword,"Coords") == 0) {
+      xflag = 1;
+      if (flag) coords(line);
+      else skip_lines(natoms,line);
+    } else if (strcmp(keyword,"Types") == 0) {
+      typeflag = 1;
+      if (flag) types(line);
+      else skip_lines(natoms,line);
+    } else if (strcmp(keyword,"Charges") == 0) {
+      qflag = 1;
+      if (flag) charges(line);
+      else skip_lines(natoms,line);
+    } else if (strcmp(keyword,"Diameters") == 0) {
+      radiusflag = 1;
+      if (flag) diameters(line);
+      else skip_lines(natoms,line);
+    } else if (strcmp(keyword,"Masses") == 0) {
+      rmassflag = 1;
+      if (flag) masses(line);
+      else skip_lines(natoms,line);
+
+    } else if (strcmp(keyword,"replambdaH") == 0) {
+        replambdaHflag = 1;
+        if (flag) representative_atom(line);
+        else skip_lines(natoms,line);
+      } else if (strcmp(keyword,"moltypeH") == 0) {
+        moltypeHflag = 1;
+        if (flag) moltype_atom(line);
+        else skip_lines(natoms,line);
+
+      } else if (strcmp(keyword,"Bonds") == 0) {
+      if (nbonds == 0)
+	error->all(FLERR,"Molecule file has bonds but no nbonds setting");
+      bondflag = tag_require = 1;
+      bonds(flag,line);
+    } else if (strcmp(keyword,"Angles") == 0) {
+      if (nangles == 0)
+	error->all(FLERR,"Molecule file has angles but no nangles setting");
+      angleflag = tag_require = 1;
+      angles(flag,line);
+    } else if (strcmp(keyword,"Dihedrals") == 0) {
+      if (ndihedrals == 0) error->all(FLERR,"Molecule file has dihedrals "
+				      "but no ndihedrals setting");
+      dihedralflag = tag_require = 1;
+      dihedrals(flag,line);
+    } else if (strcmp(keyword,"Impropers") == 0) {
+      if (nimpropers == 0) error->all(FLERR,"Molecule file has impropers "
+				      "but no nimpropers setting");
+      improperflag = tag_require = 1;
+      impropers(flag,line);
+
+    } else if (strcmp(keyword,"Special Bond Counts") == 0) {
+      nspecialflag = 1;
+      nspecial_read(flag,line);
+    } else if (strcmp(keyword,"Special Bonds") == 0) {
+      specialflag = tag_require = 1;
+      if (flag) special_read(line);
+      else skip_lines(natoms,line);
+
+    } else if (strcmp(keyword,"Shake Flags") == 0) {
+      shakeflagflag = 1;
+      if (flag) shakeflag_read(line);
+      else skip_lines(natoms,line);
+    } else if (strcmp(keyword,"Shake Atoms") == 0) {
+      shakeatomflag = tag_require = 1;
+      if (shaketypeflag) shakeflag = 1;
+      if (!shakeflagflag)
+	error->all(FLERR,"Molecule file shake flags not before shake atoms");
+      if (flag) shakeatom_read(line);
+      else skip_lines(natoms,line);
+    } else if (strcmp(keyword,"Shake Bond Types") == 0) {
+      shaketypeflag = 1;
+      if (shakeatomflag) shakeflag = 1;
+      if (!shakeflagflag)
+	error->all(FLERR,"Molecule file shake flags not before shake bonds");
+      if (flag) shaketype_read(line);
+      else skip_lines(natoms,line);
+
+    } else if (strcmp(keyword,"Body Integers") == 0) {
+      if (bodyflag == 0 || nibody == 0)
+	error->all(FLERR,"Molecule file has body params "
+                   "but no setting for them");
+      ibodyflag = 1;
+      body(flag,0,line);
+    } else if (strcmp(keyword,"Body Doubles") == 0) {
+      if (bodyflag == 0 || ndbody == 0)
+	error->all(FLERR,"Molecule file has body params "
+                   "but no setting for them");
+      dbodyflag = 1;
+      body(flag,1,line);
+
+    } else error->one(FLERR,"Unknown section in molecule file");
+
+    parse_keyword(1,line,keyword);
+  }
+
+  // clean up
+
+  memory->destroy(count);
+
+  // error check
+
+  if (flag == 0) {
+    if ((nspecialflag && !specialflag) || (!nspecialflag && specialflag))
+      error->all(FLERR,"Molecule file needs both Special Bond sections");
+    if (specialflag && !bondflag)
+      error->all(FLERR,"Molecule file has special flags but no bonds");
+    if ((shakeflagflag || shakeatomflag || shaketypeflag) && !shakeflag)
+      error->all(FLERR,"Molecule file shake info is incomplete");
+    if (bodyflag && nibody && ibodyflag == 0)
+      error->all(FLERR,"Molecule file has no Body Integers section");
+    if (bodyflag && ndbody && dbodyflag == 0)
+      error->all(FLERR,"Molecule file has no Body Doubles section");
+  }
+
+  // auto-generate special bonds
+
+  if (bondflag && !specialflag) {
+    specialflag = 1;
+    nspecialflag = 1;
+    maxspecial = atom->maxspecial;
+    if (flag) special_generate();
+  }
+
+  // body particle must have natom = 1
+  // set radius by having body class compute its own radius
+  
+  if (bodyflag) {
+    radiusflag = 1;
+    if (natoms != 1) 
+      error->all(FLERR,"Molecule natoms must be 1 for body particle");
+    if (sizescale != 1.0)
+      error->all(FLERR,"Molecule sizescale must be 1.0 for body particle");
+    if (flag) {
+      radius[0] = avec_body->radius_body(nibody,ndbody,ibodyparams,dbodyparams);
+      maxradius = radius[0];
+    }
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read coords from file
+------------------------------------------------------------------------- */
+
+void Molecule::coords(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 4)
+        error->all(FLERR,"Invalid Coords section in molecule file");
+    }
+    sscanf(line,"%d %lg %lg %lg",&tmp,&x[i][0],&x[i][1],&x[i][2]);
+    x[i][0] *= sizescale;
+    x[i][1] *= sizescale;
+    x[i][2] *= sizescale;
+  }
+
+  if (domain->dimension == 2) {
+    for (int i = 0; i < natoms; i++)
+      if (x[i][2] != 0.0)
+        error->all(FLERR,"Molecule file z coord must be 0.0 for 2d");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read types from file
+   set ntypes = max of any atom type
+------------------------------------------------------------------------- */
+
+void Molecule::types(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 2)
+        error->all(FLERR,"Invalid Types section in molecule file");
+    }
+    sscanf(line,"%d %d",&tmp,&type[i]);
+    type[i] += toffset;
+  }
+
+  for (int i = 0; i < natoms; i++)
+    if (type[i] <= 0)
+      error->all(FLERR,"Invalid atom type in molecule file");
+
+  for (int i = 0; i < natoms; i++)
+    ntypes = MAX(ntypes,type[i]);
+}
+
+/* ----------------------------------------------------------------------
+   read charges from file
+------------------------------------------------------------------------- */
+
+void Molecule::charges(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 2)
+        error->all(FLERR,"Invalid Charges section in molecule file");
+    }
+    sscanf(line,"%d %lg",&tmp,&q[i]);
+  }
+}
+
+void Molecule::representative_atom(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    sscanf(line,"%d %d",&tmp,&replambdaH[i]);
+    printf("i=%d rep = %d",i,replambdaH[i]);
+  }
+}
+
+void Molecule::moltype_atom(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    sscanf(line,"%d %d",&tmp,&moltypeH[i]);
+    printf("i=%d rep = %d",i,moltypeH[i]);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read diameters from file and set radii
+------------------------------------------------------------------------- */
+
+void Molecule::diameters(char *line)
+{
+  int tmp;
+  maxradius = 0.0;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 2)
+        error->all(FLERR,"Invalid Diameters section in molecule file");
+    }
+    sscanf(line,"%d %lg",&tmp,&radius[i]);
+    radius[i] *= sizescale;
+    radius[i] *= 0.5;
+    maxradius = MAX(maxradius,radius[i]);
+  }
+
+  for (int i = 0; i < natoms; i++)
+    if (radius[i] < 0.0)
+      error->all(FLERR,"Invalid atom diameter in molecule file");
+}
+
+/* ----------------------------------------------------------------------
+   read masses from file
+------------------------------------------------------------------------- */
+
+void Molecule::masses(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 2)
+        error->all(FLERR,"Invalid Masses section in molecule file");
+    }
+    sscanf(line,"%d %lg",&tmp,&rmass[i]);
+    rmass[i] *= sizescale*sizescale*sizescale;
+  }
+
+  for (int i = 0; i < natoms; i++)
+    if (rmass[i] <= 0.0) error->all(FLERR,"Invalid atom mass in molecule file");
+}
+
+/* ----------------------------------------------------------------------
+   read bonds from file
+   set nbondtypes = max type of any bond
+   store each with both atoms if newton_bond = 0
+   if flag = 0, just count bonds/atom
+   if flag = 1, store them with atoms
+------------------------------------------------------------------------- */
+
+void Molecule::bonds(int flag, char *line)
+{
+  int tmp,itype;
+  tagint m,atom1,atom2;
+  int newton_bond = force->newton_bond;
+
+  if (flag == 0)
+    for (int i = 0; i < natoms; i++) count[i] = 0;
+  else
+    for (int i = 0; i < natoms; i++) num_bond[i] = 0;
+
+  for (int i = 0; i < nbonds; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 4)
+        error->all(FLERR,"Invalid Bonds section in molecule file");
+    }
+    sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT,
+           &tmp,&itype,&atom1,&atom2);
+    itype += boffset;
+
+    if (atom1 <= 0 || atom1 > natoms ||
+	atom2 <= 0 || atom2 > natoms)
+      error->one(FLERR,"Invalid atom ID in Bonds section of molecule file");
+    if (itype <= 0)
+      error->one(FLERR,"Invalid bond type in Bonds section of molecule file");
+
+    if (flag) {
+      m = atom1-1;
+      nbondtypes = MAX(nbondtypes,itype);
+      bond_type[m][num_bond[m]] = itype;
+      bond_atom[m][num_bond[m]] = atom2;
+      num_bond[m]++;
+      if (newton_bond == 0) {
+	m = atom2-1;
+	bond_type[m][num_bond[m]] = itype;
+	bond_atom[m][num_bond[m]] = atom1;
+	num_bond[m]++;
+      }
+    } else {
+      count[atom1-1]++;
+      if (newton_bond == 0) count[atom2-1]++;
+    }
+  }
+
+  // bond_per_atom = max of count vector
+
+  if (flag == 0) {
+    bond_per_atom = 0;
+    for (int i = 0; i < natoms; i++)
+      bond_per_atom = MAX(bond_per_atom,count[i]);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read angles from file
+   store each with all 3 atoms if newton_bond = 0
+   if flag = 0, just count angles/atom
+   if flag = 1, store them with atoms
+------------------------------------------------------------------------- */
+
+void Molecule::angles(int flag, char *line)
+{
+  int tmp,itype;
+  tagint m,atom1,atom2,atom3;
+  int newton_bond = force->newton_bond;
+
+  if (flag == 0)
+    for (int i = 0; i < natoms; i++) count[i] = 0;
+  else
+    for (int i = 0; i < natoms; i++) num_angle[i] = 0;
+
+  for (int i = 0; i < nangles; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 5)
+        error->all(FLERR,"Invalid Angles section in molecule file");
+    }
+    sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT,
+           &tmp,&itype,&atom1,&atom2,&atom3);
+    itype += aoffset;
+
+    if (atom1 <= 0 || atom1 > natoms ||
+        atom2 <= 0 || atom2 > natoms ||
+        atom3 <= 0 || atom3 > natoms)
+      error->one(FLERR,"Invalid atom ID in Angles section of molecule file");
+    if (itype <= 0)
+      error->one(FLERR,"Invalid angle type in Angles section of molecule file");
+
+    if (flag) {
+      m = atom2-1;
+      nangletypes = MAX(nangletypes,itype);
+      angle_type[m][num_angle[m]] = itype;
+      angle_atom1[m][num_angle[m]] = atom1;
+      angle_atom2[m][num_angle[m]] = atom2;
+      angle_atom3[m][num_angle[m]] = atom3;
+      num_angle[m]++;
+      if (newton_bond == 0) {
+	m = atom1-1;
+	angle_type[m][num_angle[m]] = itype;
+	angle_atom1[m][num_angle[m]] = atom1;
+	angle_atom2[m][num_angle[m]] = atom2;
+	angle_atom3[m][num_angle[m]] = atom3;
+	num_angle[m]++;
+	m = atom3-1;
+	angle_type[m][num_angle[m]] = itype;
+	angle_atom1[m][num_angle[m]] = atom1;
+	angle_atom2[m][num_angle[m]] = atom2;
+	angle_atom3[m][num_angle[m]] = atom3;
+	num_angle[m]++;
+      }
+    } else {
+      count[atom2-1]++;
+      if (newton_bond == 0) {
+	count[atom1-1]++;
+	count[atom3-1]++;
+      }
+    }
+  }
+
+  // angle_per_atom = max of count vector
+
+  if (flag == 0) {
+    angle_per_atom = 0;
+    for (int i = 0; i < natoms; i++)
+      angle_per_atom = MAX(angle_per_atom,count[i]);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read dihedrals from file
+   store each with all 4 atoms if newton_bond = 0
+   if flag = 0, just count dihedrals/atom
+   if flag = 1, store them with atoms
+------------------------------------------------------------------------- */
+
+void Molecule::dihedrals(int flag, char *line)
+{
+  int tmp,itype;
+  tagint m,atom1,atom2,atom3,atom4;
+  int newton_bond = force->newton_bond;
+
+  if (flag == 0)
+    for (int i = 0; i < natoms; i++) count[i] = 0;
+  else
+    for (int i = 0; i < natoms; i++) num_dihedral[i] = 0;
+
+  for (int i = 0; i < ndihedrals; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 6)
+        error->all(FLERR,"Invalid Dihedrals section in molecule file");
+    }
+    sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " "
+           TAGINT_FORMAT " " TAGINT_FORMAT " ",
+           &tmp,&itype,&atom1,&atom2,&atom3,&atom4);
+    itype += doffset;
+
+    if (atom1 <= 0 || atom1 > natoms ||
+        atom2 <= 0 || atom2 > natoms ||
+        atom3 <= 0 || atom3 > natoms ||
+        atom4 <= 0 || atom4 > natoms)
+      error->one(FLERR,
+		 "Invalid atom ID in dihedrals section of molecule file");
+    if (itype <= 0)
+      error->one(FLERR,
+		 "Invalid dihedral type in dihedrals section of molecule file");
+
+    if (flag) {
+      m = atom2-1;
+      ndihedraltypes = MAX(ndihedraltypes,itype);
+      dihedral_type[m][num_dihedral[m]] = itype;
+      dihedral_atom1[m][num_dihedral[m]] = atom1;
+      dihedral_atom2[m][num_dihedral[m]] = atom2;
+      dihedral_atom3[m][num_dihedral[m]] = atom3;
+      dihedral_atom4[m][num_dihedral[m]] = atom4;
+      num_dihedral[m]++;
+      if (newton_bond == 0) {
+	m = atom1-1;
+	dihedral_type[m][num_dihedral[m]] = itype;
+	dihedral_atom1[m][num_dihedral[m]] = atom1;
+	dihedral_atom2[m][num_dihedral[m]] = atom2;
+	dihedral_atom3[m][num_dihedral[m]] = atom3;
+	dihedral_atom4[m][num_dihedral[m]] = atom4;
+	num_dihedral[m]++;
+	m = atom3-1;
+	dihedral_type[m][num_dihedral[m]] = itype;
+	dihedral_atom1[m][num_dihedral[m]] = atom1;
+	dihedral_atom2[m][num_dihedral[m]] = atom2;
+	dihedral_atom3[m][num_dihedral[m]] = atom3;
+	dihedral_atom4[m][num_dihedral[m]] = atom4;
+	num_dihedral[m]++;
+	m = atom4-1;
+	dihedral_type[m][num_dihedral[m]] = itype;
+	dihedral_atom1[m][num_dihedral[m]] = atom1;
+	dihedral_atom2[m][num_dihedral[m]] = atom2;
+	dihedral_atom3[m][num_dihedral[m]] = atom3;
+	dihedral_atom4[m][num_dihedral[m]] = atom4;
+	num_dihedral[m]++;
+      }
+    } else {
+      count[atom2-1]++;
+      if (newton_bond == 0) {
+	count[atom1-1]++;
+	count[atom3-1]++;
+	count[atom4-1]++;
+      }
+    }
+  }
+
+  // dihedral_per_atom = max of count vector
+
+  if (flag == 0) {
+    dihedral_per_atom = 0;
+    for (int i = 0; i < natoms; i++)
+      dihedral_per_atom = MAX(dihedral_per_atom,count[i]);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read impropers from file
+   store each with all 4 atoms if newton_bond = 0
+   if flag = 0, just count impropers/atom
+   if flag = 1, store them with atoms
+------------------------------------------------------------------------- */
+
+void Molecule::impropers(int flag, char *line)
+{
+  int tmp,itype;
+  tagint m,atom1,atom2,atom3,atom4;
+  int newton_bond = force->newton_bond;
+
+  if (flag == 0)
+    for (int i = 0; i < natoms; i++) count[i] = 0;
+  else
+    for (int i = 0; i < natoms; i++) num_improper[i] = 0;
+
+  for (int i = 0; i < nimpropers; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 6)
+        error->all(FLERR,"Invalid Impropers section in molecule file");
+    }
+    sscanf(line,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " "
+           TAGINT_FORMAT " " TAGINT_FORMAT " ",
+           &tmp,&itype,&atom1,&atom2,&atom3,&atom4);
+    itype += ioffset;
+
+    if (atom1 <= 0 || atom1 > natoms ||
+        atom2 <= 0 || atom2 > natoms ||
+        atom3 <= 0 || atom3 > natoms ||
+        atom4 <= 0 || atom4 > natoms)
+      error->one(FLERR,
+		 "Invalid atom ID in impropers section of molecule file");
+    if (itype <= 0)
+      error->one(FLERR,
+		 "Invalid improper type in impropers section of molecule file");
+
+    if (flag) {
+      m = atom2-1;
+      nimpropertypes = MAX(nimpropertypes,itype);
+      improper_type[m][num_improper[m]] = itype;
+      improper_atom1[m][num_improper[m]] = atom1;
+      improper_atom2[m][num_improper[m]] = atom2;
+      improper_atom3[m][num_improper[m]] = atom3;
+      improper_atom4[m][num_improper[m]] = atom4;
+      num_improper[m]++;
+      if (newton_bond == 0) {
+	m = atom1-1;
+	improper_type[m][num_improper[m]] = itype;
+	improper_atom1[m][num_improper[m]] = atom1;
+	improper_atom2[m][num_improper[m]] = atom2;
+	improper_atom3[m][num_improper[m]] = atom3;
+	improper_atom4[m][num_improper[m]] = atom4;
+	num_improper[m]++;
+	m = atom3-1;
+	improper_type[m][num_improper[m]] = itype;
+	improper_atom1[m][num_improper[m]] = atom1;
+	improper_atom2[m][num_improper[m]] = atom2;
+	improper_atom3[m][num_improper[m]] = atom3;
+	improper_atom4[m][num_improper[m]] = atom4;
+	num_improper[m]++;
+	m = atom4-1;
+	improper_type[m][num_improper[m]] = itype;
+	improper_atom1[m][num_improper[m]] = atom1;
+	improper_atom2[m][num_improper[m]] = atom2;
+	improper_atom3[m][num_improper[m]] = atom3;
+	improper_atom4[m][num_improper[m]] = atom4;
+	num_improper[m]++;
+      }
+    } else {
+      count[atom2-1]++;
+      if (newton_bond == 0) {
+	count[atom1-1]++;
+	count[atom3-1]++;
+	count[atom4-1]++;
+      }
+    }
+  }
+
+  // improper_per_atom = max of count vector
+
+  if (flag == 0) {
+    improper_per_atom = 0;
+    for (int i = 0; i < natoms; i++)
+      improper_per_atom = MAX(improper_per_atom,count[i]);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read 3 special bonds counts from file
+   if flag = 0, just tally maxspecial
+   if flag = 1, store them with atoms
+------------------------------------------------------------------------- */
+
+void Molecule::nspecial_read(int flag, char *line)
+{
+  int tmp,c1,c2,c3;
+
+  if (flag == 0) maxspecial = 0;
+
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (i == 0) {
+      int nwords = atom->count_words(line);
+      if (nwords != 4)
+        error->all(FLERR,"Invalid Special Bond Counts section in "
+                   "molecule file");
+    }
+    sscanf(line,"%d %d %d %d",&tmp,&c1,&c2,&c3);
+
+    if (flag) {
+      nspecial[i][0] = c1;
+      nspecial[i][1] = c1+c2;
+      nspecial[i][2] = c1+c2+c3;
+    } else maxspecial = MAX(maxspecial,c1+c2+c3);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read special bond indices from file
+------------------------------------------------------------------------- */
+
+void Molecule::special_read(char *line)
+{
+  int m,nwords;
+  char **words = new char*[maxspecial+1];
+
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    nwords = parse(line,words,maxspecial+1);
+    if (nwords != nspecial[i][2]+1)
+      error->all(FLERR,"Molecule file special list "
+		 "does not match special count");
+
+    for (m = 1; m < nwords; m++) {
+      special[i][m-1] = ATOTAGINT(words[m]);
+      if (special[i][m-1] <= 0 || special[i][m-1] > natoms ||
+	  special[i][m-1] == i+1)
+	error->all(FLERR,"Invalid special atom index in molecule file");
+    }
+  }
+
+  delete [] words;
+}
+
+/* ----------------------------------------------------------------------
+   auto generate special bond info
+------------------------------------------------------------------------- */
+
+void Molecule::special_generate()
+{
+  int newton_bond = force->newton_bond;
+  tagint atom1,atom2;
+  int count[natoms];
+
+  for (int i = 0; i < natoms; i++) count[i] = 0;
+
+  // 1-2 neighbors
+
+  if (newton_bond) {
+    for (int i = 0; i < natoms; i++) {
+      for (int j = 0; j < num_bond[i]; j++) {
+        atom1 = i;
+        atom2 = bond_atom[i][j]-1;
+        nspecial[i][0]++;
+        nspecial[atom2][0]++;
+        if (count[i] >= maxspecial || count[atom2] >= maxspecial)
+          error->one(FLERR,"Molecule auto special bond generation overflow");
+        special[i][count[i]++] = atom2 + 1;
+        special[atom2][count[atom2]++] = i + 1;
+      }
+    }
+  } else {
+    for (int i = 0; i < natoms; i++) {
+      nspecial[i][0] = num_bond[i];
+      for (int j = 0; j < num_bond[i]; j++) {
+        atom1 = i;
+        atom2 = bond_atom[i][j];
+        if (count[atom1] >= maxspecial)
+          error->one(FLERR,"Molecule auto special bond generation overflow");
+        special[i][count[atom1]++] = atom2;
+      }
+    }
+  }
+
+  // 1-3 neighbors with no duplicates
+
+  for (int i = 0; i < natoms; i++) nspecial[i][1] = nspecial[i][0];
+
+  int dedup;
+  for (int i = 0; i < natoms; i++) {
+    for (int m = 0; m < nspecial[i][0]; m++) {
+      for (int j = 0; j < nspecial[special[i][m]-1][0]; j++) {
+        dedup = 0;
+        for (int k =0; k < count[i]; k++) {
+          if (special[special[i][m]-1][j] == special[i][k] ||
+              special[special[i][m]-1][j] == i+1) {
+            dedup = 1;
+          }
+        }
+        if (!dedup) {
+          if (count[i] >= maxspecial)
+            error->one(FLERR,"Molecule auto special bond generation overflow");
+          special[i][count[i]++] = special[special[i][m]-1][j];
+          nspecial[i][1]++;
+        }
+      }
+    }
+  }
+
+  // 1-4 neighbors with no duplicates
+
+  for (int i = 0; i < natoms; i++) nspecial[i][2] = nspecial[i][1];
+
+  for (int i = 0; i < natoms; i++) {
+    for (int m = nspecial[i][0]; m < nspecial[i][1]; m++) {
+      for (int j = 0; j < nspecial[special[i][m]-1][0]; j++) {
+        dedup = 0;
+        for (int k =0; k < count[i]; k++) {
+          if (special[special[i][m]-1][j] == special[i][k] ||
+              special[special[i][m]-1][j] == i+1) {
+            dedup = 1;
+          }
+        }
+        if (!dedup) {
+          if (count[i] >= maxspecial)
+            error->one(FLERR,"Molecule auto special bond generation overflow");
+          special[i][count[i]++] = special[special[i][m]-1][j];
+          nspecial[i][2]++;
+        }
+      }
+    }
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read SHAKE flags from file
+------------------------------------------------------------------------- */
+
+void Molecule::shakeflag_read(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    sscanf(line,"%d %d",&tmp,&shake_flag[i]);
+  }
+
+  for (int i = 0; i < natoms; i++)
+    if (shake_flag[i] < 0 || shake_flag[i] > 4)
+      error->all(FLERR,"Invalid shake flag in molecule file");
+}
+
+/* ----------------------------------------------------------------------
+   read SHAKE atom info from file
+------------------------------------------------------------------------- */
+
+void Molecule::shakeatom_read(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (shake_flag[i] == 1)
+      sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT,
+             &tmp,&shake_atom[i][0],&shake_atom[i][1],&shake_atom[i][2]);
+    else if (shake_flag[i] == 2)
+      sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT,
+             &tmp,&shake_atom[i][0],&shake_atom[i][1]);
+    else if (shake_flag[i] == 3)
+      sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT,
+             &tmp,&shake_atom[i][0],&shake_atom[i][1],&shake_atom[i][2]);
+    else if (shake_flag[i] == 4)
+      sscanf(line,"%d " TAGINT_FORMAT " " TAGINT_FORMAT " "
+             TAGINT_FORMAT " " TAGINT_FORMAT,
+             &tmp,&shake_atom[i][0],&shake_atom[i][1],
+             &shake_atom[i][2],&shake_atom[i][3]);
+  }
+
+  for (int i = 0; i < natoms; i++) {
+    int m = shake_flag[i];
+    if (m == 1) m = 3;
+    for (int j = 0; j < m; j++)
+      if (shake_atom[i][j] <= 0 || shake_atom[i][j] > natoms)
+        error->all(FLERR,"Invalid shake atom in molecule file");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read SHAKE bond type info from file
+------------------------------------------------------------------------- */
+
+void Molecule::shaketype_read(char *line)
+{
+  int tmp;
+  for (int i = 0; i < natoms; i++) {
+    readline(line);
+    if (shake_flag[i] == 1)
+      sscanf(line,"%d %d %d %d",&tmp,
+             &shake_type[i][0],&shake_type[i][1],&shake_type[i][2]);
+    else if (shake_flag[i] == 2)
+      sscanf(line,"%d %d",&tmp,&shake_type[i][0]);
+    else if (shake_flag[i] == 3)
+      sscanf(line,"%d %d %d",&tmp,&shake_type[i][0],&shake_type[i][1]);
+    else if (shake_flag[i] == 4)
+      sscanf(line,"%d %d %d %d",&tmp,
+             &shake_type[i][0],&shake_type[i][1],&shake_type[i][2]);
+  }
+
+  for (int i = 0; i < natoms; i++) {
+    int m = shake_flag[i];
+    if (m == 1) m = 3;
+    for (int j = 0; j < m-1; j++)
+      if (shake_type[i][j] <= 0)
+        error->all(FLERR,"Invalid shake bond type in molecule file");
+    if (shake_flag[i] == 1)
+      if (shake_type[i][2] <= 0)
+        error->all(FLERR,"Invalid shake angle type in molecule file");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read body params from file
+   pflag = 0/1 for integer/double params
+------------------------------------------------------------------------- */
+
+void Molecule::body(int flag, int pflag, char *line)
+{
+  int i,ncount;
+
+  int nparam = nibody;
+  if (pflag) nparam = ndbody;
+
+  int nword = 0;
+  while (nword < nparam) {
+    readline(line);
+
+    ncount = atom->count_words(line);
+    if (ncount == 0)
+      error->one(FLERR,"Too few values in body section of molecule file");
+    if (nword+ncount > nparam) 
+      error->all(FLERR,"Too many values in body section of molecule file");
+    
+    if (flag) {
+      if (pflag == 0) {
+        ibodyparams[nword++] = force->inumeric(FLERR,strtok(line," \t\n\r\f"));
+        for (i = 1; i < ncount; i++)
+          ibodyparams[nword++] = 
+            force->inumeric(FLERR,strtok(NULL," \t\n\r\f"));
+      } else {
+        dbodyparams[nword++] = force->numeric(FLERR,strtok(line," \t\n\r\f"));
+        for (i = 1; i < ncount; i++)
+          dbodyparams[nword++] = 
+            force->numeric(FLERR,strtok(NULL," \t\n\r\f"));
+      }
+    } else nword += ncount;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   error check molecule attributes and topology against system settings
+   flag = 0, just check this molecule
+   flag = 1, check all molecules in set, this is 1st molecule in set
+------------------------------------------------------------------------- */
+
+void Molecule::check_attributes(int flag)
+{
+  int n = 1;
+  if (flag) n = nset;
+  int imol = atom->find_molecule(id);
+
+  for (int i = imol; i < imol+n; i++) {
+    Molecule *onemol = atom->molecules[imol];
+
+    // check per-atom attributes of molecule
+    // warn if not a match
+
+    int mismatch = 0;
+    if (onemol->replambdaHflag && !atom->replambdaH_flag) mismatch = 1;
+    if (onemol->moltypeHflag && !atom->moltypeH_flag) mismatch = 1;
+    if (onemol->qflag && !atom->q_flag) mismatch = 1;
+    if (onemol->radiusflag && !atom->radius_flag) mismatch = 1;
+    if (onemol->rmassflag && !atom->rmass_flag) mismatch = 1;
+
+    if (mismatch && me == 0)
+      error->warning(FLERR,
+                     "Molecule attributes do not match system attributes");
+
+    // for all atom styles, check nbondtype,etc
+
+    mismatch = 0;
+    if (atom->nbondtypes < onemol->nbondtypes) mismatch = 1;
+    if (atom->nangletypes < onemol->nangletypes) mismatch = 1;
+    if (atom->ndihedraltypes < onemol->ndihedraltypes) mismatch = 1;
+    if (atom->nimpropertypes < onemol->nimpropertypes) mismatch = 1;
+
+    if (mismatch)
+      error->all(FLERR,"Molecule topology type exceeds system topology type");
+
+    // for molecular atom styles, check bond_per_atom,etc + maxspecial
+    // do not check for atom style template, since nothing stored per atom
+
+    if (atom->molecular == 1) {
+      if (atom->avec->bonds_allow &&
+          atom->bond_per_atom < onemol->bond_per_atom) mismatch = 1;
+      if (atom->avec->angles_allow &&
+          atom->angle_per_atom < onemol->angle_per_atom) mismatch = 1;
+      if (atom->avec->dihedrals_allow &&
+          atom->dihedral_per_atom < onemol->dihedral_per_atom) mismatch = 1;
+      if (atom->avec->impropers_allow &&
+          atom->improper_per_atom < onemol->improper_per_atom) mismatch = 1;
+      if (atom->maxspecial < onemol->maxspecial) mismatch = 1;
+
+      if (mismatch)
+        error->all(FLERR,"Molecule toplogy/atom exceeds system topology/atom");
+    }
+
+    // warn if molecule topology defined but no special settings
+
+    if (onemol->bondflag && !onemol->specialflag)
+      if (me == 0) error->warning(FLERR,"Molecule has bond topology "
+                                  "but no special bond settings");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   init all data structures to empty
+------------------------------------------------------------------------- */
+
+void Molecule::initialize()
+{
+  natoms = 0;
+  nbonds = nangles = ndihedrals = nimpropers = 0;
+  ntypes = 0;
+  nbondtypes = nangletypes = ndihedraltypes = nimpropertypes = 0;
+  nibody = ndbody = 0;
+
+  bond_per_atom = angle_per_atom = dihedral_per_atom = improper_per_atom = 0;
+  maxspecial = 0;
+
+  xflag = typeflag = qflag = radiusflag = rmassflag = 0;
+  bondflag = angleflag = dihedralflag = improperflag = 0;
+  nspecialflag = specialflag = 0;
+  shakeflag = shakeflagflag = shakeatomflag = shaketypeflag = 0;
+  bodyflag = ibodyflag = dbodyflag = 0;
+
+  centerflag = massflag = comflag = inertiaflag = 0;
+  tag_require = 0;
+
+  x = NULL;
+  type = NULL;
+  q = NULL;
+  radius = NULL;
+  rmass = NULL;
+
+  num_bond = NULL;
+  bond_type = NULL;
+  bond_atom = NULL;
+
+  num_angle = NULL;
+  angle_type = NULL;
+  angle_atom1 = angle_atom2 = angle_atom3 = NULL;
+
+  num_dihedral = NULL;
+  dihedral_type = NULL;
+  dihedral_atom1 = dihedral_atom2 = dihedral_atom3 = dihedral_atom4 = NULL;
+
+  num_improper = NULL;
+  improper_type = NULL;
+  improper_atom1 = improper_atom2 = improper_atom3 = improper_atom4 = NULL;
+
+  nspecial = NULL;
+  special = NULL;
+
+  shake_flag = NULL;
+  shake_atom = NULL;
+  shake_type = NULL;
+
+  ibodyparams = NULL;
+  dbodyparams = NULL;
+
+  dx = NULL;
+  dxcom = NULL;
+  dxbody = NULL;
+}
+
+/* ----------------------------------------------------------------------
+   allocate all data structures
+   also initialize values for data structures that are always allocated
+------------------------------------------------------------------------- */
+
+void Molecule::allocate()
+{
+  if (xflag) memory->create(x,natoms,3,"molecule:x");
+  if (typeflag) memory->create(type,natoms,"molecule:type");
+  if (qflag) memory->create(q,natoms,"molecule:q");
+  if (radiusflag) memory->create(radius,natoms,"molecule:radius");
+  if (rmassflag) memory->create(rmass,natoms,"molecule:rmass");
+  if (replambdaHflag) memory->create(replambdaH,natoms,"molecule:replambdaH");
+  if (moltypeHflag) memory->create(moltypeH,natoms,"molecule:moltypeH");
+
+  // always allocate num_bond,num_angle,etc and special+nspecial
+  // even if not in molecule file, initialize to 0
+  // this is so methods that use these arrays don't have to check they exist
+
+  memory->create(num_bond,natoms,"molecule:num_bond");
+  for (int i = 0; i < natoms; i++) num_bond[i] = 0;
+  memory->create(num_angle,natoms,"molecule:num_angle");
+  for (int i = 0; i < natoms; i++) num_angle[i] = 0;
+  memory->create(num_dihedral,natoms,"molecule:num_dihedral");
+  for (int i = 0; i < natoms; i++) num_dihedral[i] = 0;
+  memory->create(num_improper,natoms,"molecule:num_improper");
+  for (int i = 0; i < natoms; i++) num_improper[i] = 0;
+
+  memory->create(special,natoms,maxspecial,"molecule:special");
+
+  memory->create(nspecial,natoms,3,"molecule:nspecial");
+  for (int i = 0; i < natoms; i++)
+    nspecial[i][0] = nspecial[i][1] = nspecial[i][2] = 0;
+
+  if (bondflag) {
+    memory->create(bond_type,natoms,bond_per_atom,
+		   "molecule:bond_type");
+    memory->create(bond_atom,natoms,bond_per_atom,
+		   "molecule:bond_atom");
+  }
+
+  if (angleflag) {
+    memory->create(angle_type,natoms,angle_per_atom,
+		   "molecule:angle_type");
+    memory->create(angle_atom1,natoms,angle_per_atom,
+		   "molecule:angle_atom1");
+    memory->create(angle_atom2,natoms,angle_per_atom,
+		   "molecule:angle_atom2");
+    memory->create(angle_atom3,natoms,angle_per_atom,
+		   "molecule:angle_atom3");
+  }
+
+  if (dihedralflag) {
+    memory->create(dihedral_type,natoms,dihedral_per_atom,
+		   "molecule:dihedral_type");
+    memory->create(dihedral_atom1,natoms,dihedral_per_atom,
+		   "molecule:dihedral_atom1");
+    memory->create(dihedral_atom2,natoms,dihedral_per_atom,
+		   "molecule:dihedral_atom2");
+    memory->create(dihedral_atom3,natoms,dihedral_per_atom,
+		   "molecule:dihedral_atom3");
+    memory->create(dihedral_atom4,natoms,dihedral_per_atom,
+		   "molecule:dihedral_atom4");
+  }
+
+  if (improperflag) {
+    memory->create(improper_type,natoms,improper_per_atom,
+		   "molecule:improper_type");
+    memory->create(improper_atom1,natoms,improper_per_atom,
+		   "molecule:improper_atom1");
+    memory->create(improper_atom2,natoms,improper_per_atom,
+		   "molecule:improper_atom2");
+    memory->create(improper_atom3,natoms,improper_per_atom,
+		   "molecule:improper_atom3");
+    memory->create(improper_atom4,natoms,improper_per_atom,
+		   "molecule:improper_atom4");
+  }
+
+  if (shakeflag) {
+    memory->create(shake_flag,natoms,"molecule:shake_flag");
+    memory->create(shake_atom,natoms,4,"molecule:shake_flag");
+    memory->create(shake_type,natoms,3,"molecule:shake_flag");
+  }
+
+  if (bodyflag) {
+    if (nibody) memory->create(ibodyparams,nibody,"molecule:ibodyparams");
+    if (ndbody) memory->create(dbodyparams,ndbody,"molecule:dbodyparams");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   deallocate all data structures
+------------------------------------------------------------------------- */
+
+void Molecule::deallocate()
+{
+  memory->destroy(x);
+  memory->destroy(type);
+  memory->destroy(q);
+  memory->destroy(radius);
+  memory->destroy(replambdaH);
+  memory->destroy(moltypeH);
+  memory->destroy(rmass);
+
+  memory->destroy(num_bond);
+  memory->destroy(bond_type);
+  memory->destroy(bond_atom);
+
+  memory->destroy(num_angle);
+  memory->destroy(angle_type);
+  memory->destroy(angle_atom1);
+  memory->destroy(angle_atom2);
+  memory->destroy(angle_atom3);
+
+  memory->destroy(num_dihedral);
+  memory->destroy(dihedral_type);
+  memory->destroy(dihedral_atom1);
+  memory->destroy(dihedral_atom2);
+  memory->destroy(dihedral_atom3);
+  memory->destroy(dihedral_atom4);
+
+  memory->destroy(num_improper);
+  memory->destroy(improper_type);
+  memory->destroy(improper_atom1);
+  memory->destroy(improper_atom2);
+  memory->destroy(improper_atom3);
+  memory->destroy(improper_atom4);
+
+  memory->destroy(nspecial);
+  memory->destroy(special);
+
+  memory->destroy(shake_flag);
+  memory->destroy(shake_atom);
+  memory->destroy(shake_type);
+
+  memory->destroy(dx);
+  memory->destroy(dxcom);
+  memory->destroy(dxbody);
+
+  memory->destroy(ibodyparams);
+  memory->destroy(dbodyparams);
+}
+
+/* ----------------------------------------------------------------------
+   open molecule file
+------------------------------------------------------------------------- */
+
+void Molecule::open(char *file)
+{
+  fp = fopen(file,"r");
+  if (fp == NULL) {
+    char str[128];
+    sprintf(str,"Cannot open molecule file %s",file);
+    error->one(FLERR,str);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read and bcast a line
+------------------------------------------------------------------------- */
+
+void Molecule::readline(char *line)
+{
+  int n;
+  if (me == 0) {
+    if (fgets(line,MAXLINE,fp) == NULL) n = 0;
+    else n = strlen(line) + 1;
+  }
+  MPI_Bcast(&n,1,MPI_INT,0,world);
+  if (n == 0) error->all(FLERR,"Unexpected end of molecule file");
+  MPI_Bcast(line,n,MPI_CHAR,0,world);
+}
+
+/* ----------------------------------------------------------------------
+   extract keyword from line
+   flag = 0, read and bcast line
+   flag = 1, line has already been read
+------------------------------------------------------------------------- */
+
+void Molecule::parse_keyword(int flag, char *line, char *keyword)
+{
+  if (flag) {
+
+    // read upto non-blank line plus 1 following line
+    // eof is set to 1 if any read hits end-of-file
+
+    int eof = 0;
+    if (me == 0) {
+      if (fgets(line,MAXLINE,fp) == NULL) eof = 1;
+      while (eof == 0 && strspn(line," \t\n\r") == strlen(line)) {
+	if (fgets(line,MAXLINE,fp) == NULL) eof = 1;
+      }
+      if (fgets(keyword,MAXLINE,fp) == NULL) eof = 1;
+    }
+
+    // if eof, set keyword empty and return
+
+    MPI_Bcast(&eof,1,MPI_INT,0,world);
+    if (eof) {
+      keyword[0] = '\0';
+      return;
+    }
+
+    // bcast keyword line to all procs
+
+    int n;
+    if (me == 0) n = strlen(line) + 1;
+    MPI_Bcast(&n,1,MPI_INT,0,world);
+    MPI_Bcast(line,n,MPI_CHAR,0,world);
+  }
+
+  // copy non-whitespace portion of line into keyword
+
+  int start = strspn(line," \t\n\r");
+  int stop = strlen(line) - 1;
+  while (line[stop] == ' ' || line[stop] == '\t'
+         || line[stop] == '\n' || line[stop] == '\r') stop--;
+  line[stop+1] = '\0';
+  strcpy(keyword,&line[start]);
+}
+
+/* ----------------------------------------------------------------------
+   skip N lines of file
+------------------------------------------------------------------------- */
+
+void Molecule::skip_lines(int n, char *line)
+{
+  for (int i = 0; i < n; i++) readline(line);
+}
+
+/* ----------------------------------------------------------------------
+   parse line into words separated by whitespace
+   return # of words
+   max = max pointers storable in words
+------------------------------------------------------------------------- */
+
+int Molecule::parse(char *line, char **words, int max)
+{
+  char *ptr;
+
+  int nwords = 0;
+  words[nwords++] = strtok(line," \t\n\r\f");
+
+  while ((ptr = strtok(NULL," \t\n\r\f"))) {
+    if (nwords < max) words[nwords] = ptr;
+    nwords++;
+  }
+
+  return nwords;
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 prints molecule params
+------------------------------------------------------------------------- */
+
+/*
+
+void Molecule::print()
+{
+  printf("MOLECULE %s\n",id);
+  printf("  %d natoms\n",natoms);
+  if (nbonds) printf("  %d nbonds\n",nbonds);
+  if (nangles) printf("  %d nangles\n",nangles);
+  if (ndihedrals) printf("  %d ndihedrals\n",ndihedrals);
+  if (nimpropers) printf("  %d nimpropers\n",nimpropers);
+
+  if (xflag) {
+    printf(  "Coords:\n");
+    for (int i = 0; i < natoms; i++)
+      printf("    %d %g %g %g\n",i+1,x[i][0],x[i][1],x[i][2]);
+  }
+  if (typeflag) {
+    printf(  "Types:\n");
+    for (int i = 0; i < natoms; i++)
+      printf("    %d %d\n",i+1,type[i]);
+  }
+  if (qflag) {
+    printf(  "Charges:\n");
+    for (int i = 0; i < natoms; i++)
+      printf("    %d %g\n",i+1,q[i]);
+  }
+  if (radiusflag) {
+    printf(  "Radii:\n");
+    for (int i = 0; i < natoms; i++)
+      printf("    %d %g\n",i+1,radius[i]);
+  }
+  if (rmassflag) {
+    printf(  "Masses:\n");
+    for (int i = 0; i < natoms; i++)
+      printf("    %d %g\n",i+1,rmass[i]);
+  }
+
+  if (bondflag) {
+    printf(  "Bonds:\n");
+    for (int i = 0; i < natoms; i++) {
+      printf("    %d %d\n",i+1,num_bond[i]);
+      for (int j = 0; j < num_bond[i]; j++)
+        printf("      %d %d %d %d\n",j+1,bond_type[i][j],i+1,bond_atom[i][j]);
+    }
+  }
+  if (angleflag) {
+    printf(  "Angles:\n");
+    for (int i = 0; i < natoms; i++) {
+      printf("    %d %d\n",i+1,num_angle[i]);
+      for (int j = 0; j < num_angle[i]; j++)
+        printf("      %d %d %d %d %d\n",
+               j+1,angle_type[i][j],
+               angle_atom1[i][j],angle_atom2[i][j],angle_atom3[i][j]);
+    }
+  }
+  if (dihedralflag) {
+    printf(  "Dihedrals:\n");
+    for (int i = 0; i < natoms; i++) {
+      printf("    %d %d\n",i+1,num_dihedral[i]);
+      for (int j = 0; j < num_dihedral[i]; j++)
+        printf("      %d %d %d %d %d %d\n",
+               j+1,dihedral_type[i][j],
+               dihedral_atom1[i][j],dihedral_atom2[i][j],
+               dihedral_atom3[i][j],dihedral_atom4[i][j]);
+    }
+  }
+  if (improperflag) {
+    printf(  "Impropers:\n");
+    for (int i = 0; i < natoms; i++) {
+      printf("    %d %d\n",i+1,num_improper[i]);
+      for (int j = 0; j < num_improper[i]; j++)
+        printf("      %d %d %d %d %d %d\n",
+               j+1,improper_type[i][j],
+               improper_atom1[i][j],improper_atom2[i][j],
+               improper_atom3[i][j],improper_atom4[i][j]);
+    }
+  }
+
+  if (specialflag) {
+    printf(  "Special neighs:\n");
+    for (int i = 0; i < natoms; i++) {
+      printf("    %d %d %d %d\n",i+1,
+             nspecial[i][0],nspecial[i][1]-nspecial[i][0],
+             nspecial[i][2]-nspecial[i][1]);
+      printf("      ");
+      for (int j = 0; j < nspecial[i][2]; j++)
+        printf(" %d",special[i][j]);
+      printf("\n");
+    }
+  }
+}
+
+*/
diff --git a/src/USER-HADRESS/molecule.h b/src/USER-HADRESS/molecule.h
new file mode 100644
index 000000000..4521fc45b
--- /dev/null
+++ b/src/USER-HADRESS/molecule.h
@@ -0,0 +1,432 @@
+/* -*- 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_ONE_MOLECULE_H
+#define LMP_ONE_MOLECULE_H
+
+#include "pointers.h"
+
+namespace LAMMPS_NS {
+
+class Molecule : protected Pointers {
+ public:
+  char *id;   // template id of this molecule, same for all molecules in set
+  int nset;   // if first in set, # of molecules in this set
+              // else 0 if not first in set
+  int last;   // 1 if last molecule in set, else 0
+
+  // number of atoms,bonds,etc in molecule
+  // nibody,ndbody = # of integer/double fields in body
+
+  int natoms;
+  int nbonds,nangles,ndihedrals,nimpropers;
+  int ntypes;
+  int nbondtypes,nangletypes,ndihedraltypes,nimpropertypes;
+  int nibody,ndbody;
+
+  // max bond,angle,etc per atom
+
+  int bond_per_atom,angle_per_atom,dihedral_per_atom,improper_per_atom;
+  int maxspecial;
+
+  // 1 if attribute defined in file, 0 if not
+
+  int xflag,typeflag,qflag,radiusflag,rmassflag;
+  int replambdaHflag,moltypeHflag;
+  int bondflag,angleflag,dihedralflag,improperflag;
+  int nspecialflag,specialflag;
+  int shakeflag,shakeflagflag,shakeatomflag,shaketypeflag;
+  int bodyflag,ibodyflag,dbodyflag;
+
+  // 1 if attribute defined or computed, 0 if not
+
+  int centerflag,massflag,comflag,inertiaflag;
+
+  // 1 if molecule fields require atom IDs
+
+  int tag_require;
+
+  // attributes
+
+  double **x;          // displacement of each atom from origin
+  int *type;           // type of each atom
+  double *q;           // charge on each atom
+
+  int *replambdaH;      // replambdaH on each atom
+  int *moltypeH;      // moltypeH on each atom
+
+  double *radius;      // radius of each atom
+  double *rmass;       // mass of each atom
+
+  int *num_bond;       // bonds, angles, dihedrals, impropers for each atom
+  int **bond_type;
+  tagint **bond_atom;
+
+  int *num_angle;
+  int **angle_type;
+  tagint **angle_atom1,**angle_atom2,**angle_atom3;
+
+  int *num_dihedral;
+  int **dihedral_type;
+  tagint **dihedral_atom1,**dihedral_atom2,**dihedral_atom3,**dihedral_atom4;
+
+  int *num_improper;
+  int **improper_type;
+  tagint **improper_atom1,**improper_atom2,**improper_atom3,**improper_atom4;
+
+  int **nspecial;
+  tagint **special;
+
+  int *shake_flag;
+  tagint **shake_atom;
+  int **shake_type;
+
+  class AtomVecBody *avec_body;
+  int *ibodyparams;         // integer and double body params
+  double *dbodyparams;
+
+  double center[3];         // geometric center of molecule
+  double masstotal;         // total mass of molecule
+  double com[3];            // center of mass of molecule
+  double itensor[6];        // moments of inertia of molecule
+  double inertia[3];        // principal moments of inertia of molecule
+  double ex[3],ey[3],ez[3]; // principal axes of molecule in space coords
+  double quat[4];           // quaternion for orientation of molecule
+
+  double maxradius;    // max radius of any atom in molecule
+  double molradius;    // radius of molecule from geometric center
+                       // including finite-size particle radii
+  int comatom;         // index (1-Natom) of atom closest to COM
+  double maxextent;    // furthest any atom in molecule is from comatom
+
+  double **dx;         // displacement of each atom relative to center
+  double **dxcom;      // displacement of each atom relative to COM
+  double **dxbody;     // displacement of each atom relative to COM
+                       // in body frame (diagonalized interia tensor)
+
+  double *quat_external;   // orientation imposed by external class
+                           // e.g. FixPour or CreateAtoms
+  
+  Molecule(class LAMMPS *, int, char **, int &);
+  ~Molecule();
+  void compute_center();
+  void compute_mass();
+  void compute_com();
+  void compute_inertia();
+  void check_attributes(int);
+
+ private:
+  int me;
+  FILE *fp;
+  int *count;
+  int toffset,boffset,aoffset,doffset,ioffset;
+  int autospecial;
+  double sizescale;
+  
+  void read(int);
+  void coords(char *);
+  void types(char *);
+  void charges(char *);
+  void representative_atom(char *);
+  void moltype_atom(char *);
+  void diameters(char *);
+  void masses(char *);
+  void bonds(int, char *);
+  void angles(int, char *);
+  void dihedrals(int, char *);
+  void impropers(int, char *);
+  void nspecial_read(int, char *);
+  void special_read(char *);
+  void special_generate();
+  void shakeflag_read(char *);
+  void shakeatom_read(char *);
+  void shaketype_read(char *);
+  void body(int, int, char *);
+
+  void initialize();
+  void allocate();
+  void deallocate();
+
+  void open(char *);
+  void readline(char *);
+  void parse_keyword(int, char *, char *);
+  void skip_lines(int, char *);
+  int parse(char *, char **, int);
+
+  // void print();
+};
+
+}
+
+#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: Molecule template ID must be alphanumeric or underscore characters
+
+Self-explanatory.
+
+E: Insufficient Jacobi rotations for rigid molecule
+
+Eigensolve for rigid body was not sufficiently accurate.
+
+E: Unexpected end of molecule file
+
+Self-explanatory.
+
+E: Molecule file z center-of-mass must be 0.0 for 2d
+
+Self-explanatory.
+
+E: Molecule file requires atom style body
+
+Self-explanatory.
+
+E: No count or invalid atom count in molecule file
+
+The number of atoms must be specified.
+
+E: Invalid bond count in molecule file
+
+Self-explanatory.
+
+E: Invalid angle count in molecule file
+
+Self-explanatory.
+
+E: Invalid dihedral count in molecule file
+
+Self-explanatory.
+
+E: Invalid improper count in molecule file
+
+Self-explanatory.
+
+E: Molecule file has bonds but no nbonds setting
+
+Self-explanatory.
+
+E: Molecule file has angles but no nangles setting
+
+Self-explanatory.
+
+E: Molecule file has dihedrals but no ndihedrals setting
+
+Self-explanatory.
+
+E: Molecule file has impropers but no nimpropers setting
+
+Self-explanatory.
+
+E: Molecule file shake flags not before shake atoms
+
+The order of the two sections is important.
+
+E: Molecule file shake flags not before shake bonds
+
+The order of the two sections is important.
+
+E: Molecule file has body params but no setting for them
+
+Self-explanatory.
+
+E: Unknown section in molecule file
+
+Self-explanatory.
+
+E: Molecule file needs both Special Bond sections
+
+Self-explanatory.
+
+E: Molecule file has special flags but no bonds
+
+Self-explanatory.
+
+E: Molecule file shake info is incomplete
+
+All 3 SHAKE sections are needed.
+
+E: Molecule file has no Body Integers section
+
+Self-explanatory.
+
+E: Molecule file has no Body Doubles section
+
+Self-explanatory.
+
+E: Molecule natoms must be 1 for body particle
+
+Self-explanatory.
+
+E: Molecule sizescale must be 1.0 for body particle
+
+Self-explanatory.
+
+E: Invalid Coords section in molecule file
+
+Self-explanatory.
+
+E: Molecule file z coord must be 0.0 for 2d
+
+Self-explanatory.
+
+E: Invalid Types section in molecule file
+
+Self-explanatory.
+
+E: Invalid atom type in molecule file
+
+Atom types must range from 1 to specified # of types.
+
+E: Invalid Charges section in molecule file
+
+Self-explanatory.
+
+E: Invalid Diameters section in molecule file
+
+Self-explanatory.
+
+E: Invalid atom diameter in molecule file
+
+Diameters must be >= 0.0.
+
+E: Invalid Masses section in molecule file
+
+Self-explanatory.
+
+E: Invalid atom mass in molecule file
+
+Masses must be > 0.0.
+
+E: Invalid Bonds section in molecule file
+
+Self-explanatory.
+
+E: Invalid atom ID in Bonds section of molecule file
+
+Self-explanatory.
+
+E: Invalid bond type in Bonds section of molecule file
+
+Self-explanatory.
+
+E: Invalid Angles section in molecule file
+
+Self-explanatory.
+
+E: Invalid atom ID in Angles section of molecule file
+
+Self-explanatory.
+
+E: Invalid angle type in Angles section of molecule file
+
+Self-explanatory.
+
+E: Invalid Dihedrals section in molecule file
+
+Self-explanatory.
+
+E: Invalid atom ID in dihedrals section of molecule file
+
+Self-explanatory.
+
+E: Invalid dihedral type in dihedrals section of molecule file
+
+Self-explanatory.
+
+E: Invalid Impropers section in molecule file
+
+Self-explanatory.
+
+E: Invalid atom ID in impropers section of molecule file
+
+Self-explanatory.
+
+E: Invalid improper type in impropers section of molecule file
+
+Self-explanatory.
+
+E: Invalid Special Bond Counts section in molecule file
+
+Self-explanatory.
+
+E: Molecule file special list does not match special count
+
+The number of values in an atom's special list does not match count.
+
+E: Invalid special atom index in molecule file
+
+Self-explanatory.
+
+E: Molecule auto special bond generation overflow
+
+Counts exceed maxspecial setting for other atoms in system.
+
+E: Invalid shake flag in molecule file
+
+Self-explanatory.
+
+E: Invalid shake atom in molecule file
+
+Self-explanatory.
+
+E: Invalid shake bond type in molecule file
+
+Self-explanatory.
+
+E: Invalid shake angle type in molecule file
+
+Self-explanatory.
+
+E: Too few values in body section of molecule file
+
+Self-explanatory.
+
+E: Too many values in body section of molecule file
+
+Self-explanatory.
+
+W: Molecule attributes do not match system attributes
+
+An attribute is specified (e.g. diameter, charge) that is
+not defined for the specified atom style.
+
+E: Molecule topology type exceeds system topology type
+
+The number of bond, angle, etc types in the molecule exceeds the
+system setting.  See the create_box command for how to specify these
+values.
+
+E: Molecule toplogy/atom exceeds system topology/atom
+
+The number of bonds, angles, etc per-atom in the molecule exceeds the
+system setting.  See the create_box command for how to specify these
+values.
+
+W: Molecule has bond topology but no special bond settings
+
+This means the bonded atoms will not be excluded in pair-wise
+interactions.
+
+E: Cannot open molecule file %s
+
+The specified file cannot be opened.  Check that the path and name are
+correct.
+
+*/
diff --git a/src/USER-HADRESS/pair_lj_cut_coul_dsf_hars_at.cpp b/src/USER-HADRESS/pair_lj_cut_coul_dsf_hars_at.cpp
new file mode 100644
index 000000000..5a60d7ef7
--- /dev/null
+++ b/src/USER-HADRESS/pair_lj_cut_coul_dsf_hars_at.cpp
@@ -0,0 +1,971 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain 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: Maziar Heidari,
+                        Robinson Cortes-Huerto,
+                        Davide Donadio and
+                        Raffaello Potestio
+                        (Max Planck Institute for Polymer Research, 2015-2016)
+------------------------------------------------------------------------- */
+
+#include "math.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "pair_lj_cut_coul_dsf_hars_at.h"
+#include "atom.h"
+#include "comm.h"
+#include "force.h"
+#include "neighbor.h"
+#include "neigh_list.h"
+#include "memory.h"
+#include "math_const.h"
+#include "error.h"
+#include "fix_lambdah_calc.h"
+#include "update.h"
+
+
+using namespace LAMMPS_NS;
+using namespace MathConst;
+#define BIG MAXTAGINT
+
+
+#define EWALD_F   1.12837917
+#define EWALD_P   0.3275911
+#define A1        0.254829592
+#define A2       -0.284496736
+#define A3        1.421413741
+#define A4       -1.453152027
+#define A5        1.061405429
+
+/* ---------------------------------------------------------------------- */
+
+PairLJCutCoulDSFHARSAT::PairLJCutCoulDSFHARSAT(LAMMPS *lmp) : Pair(lmp)
+{
+  single_enable = 0;
+
+  AT_molmap_H = NULL;
+  nmolecules = molecules_in_group(idlo,idhi);
+
+  H_AdResS_allocated = 0;
+
+  AT_Pressure_Compensation_Run = 0;
+  Comp_Counter_H = 0;
+  memory->create(AT_massproc_H,nmolecules,"pair:AT_massproc_H");
+  memory->create(AT_masstotal_H,nmolecules,"pair:AT_masstotal_H");
+  memory->create(AT_mol_f_H,nmolecules,3,"pair:AT_mol_f_H");
+  memory->create(AT_mol_f_all_H,nmolecules,3,"pair:AT_mol_f_all_H");
+
+
+  // compute masstotal for each molecule
+  MPI_Comm_rank(world, &me);
+  int *mask = atom->mask;
+  tagint *molecule = atom->molecule;
+  int *type = atom->type;
+  double *mass = atom->mass;
+  double *rmass = atom->rmass;
+  int nlocal = atom->nlocal;
+
+  tagint imol;
+  double massone;
+
+  for (int i = 0; i < nmolecules; i++) AT_massproc_H[i] = 0.0;
+
+
+  for (int i = 0; i < nlocal; i++)
+  {
+//    if (mask[i] & groupbit) {
+    if (mask[i]) {
+      if (rmass) massone = rmass[i];
+      else massone = mass[type[i]];
+      imol = molecule[i];
+      if (AT_molmap_H) imol = AT_molmap_H[imol-idlo];
+      else imol--;
+      AT_massproc_H[imol] += massone;
+
+    }
+  }
+
+  MPI_Allreduce(AT_massproc_H,AT_masstotal_H,nmolecules,MPI_DOUBLE,MPI_SUM,world);
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+PairLJCutCoulDSFHARSAT::~PairLJCutCoulDSFHARSAT()
+{
+  if (allocated) {
+    memory->destroy(setflag);
+    memory->destroy(cutsq);
+
+    memory->destroy(cut_lj);
+    memory->destroy(cut_ljsq);
+    memory->destroy(epsilon);
+    memory->destroy(sigma);
+    memory->destroy(lj1);
+    memory->destroy(lj2);
+    memory->destroy(lj3);
+    memory->destroy(lj4);
+    memory->destroy(offset);
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::compute(int eflag, int vflag)
+{
+  int i,j,ii,jj,inum,jnum,itype,jtype;
+  double qtmp,xtmp,ytmp,ztmp,delx,dely,delz,evdwl,ecoul,fpair;
+  double r,rsq,r2inv,r6inv,forcecoul,forcelj,factor_coul,factor_lj,Vij_Coul,Vij_Lj;;
+  double prefactor,erfcc,erfcd,t;
+  int *ilist,*jlist,*numneigh,**firstneigh;
+  int imoltypeH,jmoltypeH;
+
+  evdwl = ecoul = 0.0;
+  if (eflag || vflag) ev_setup(eflag,vflag);
+  else evflag = vflag_fdotr = 0;
+  
+  double **x = atom->x;
+  double **f = atom->f;
+  double *q = atom->q;
+  double *lambdaH = atom->lambdaH;
+  double **gradlambdaH = atom->gradlambdaH;
+
+  int *type = atom->type;
+  int nlocal = atom->nlocal;
+  double *special_lj = force->special_lj;
+  double *special_coul = force->special_coul;
+  int newton_pair = force->newton_pair;
+  double qqrd2e = force->qqrd2e;
+  int imol,jmol;
+  tagint *molecule = atom->molecule;
+  double *mass = atom->mass;
+  int *replambdaH = atom->replambdaH;
+  int *moltypeH = atom->moltypeH;
+
+  int ibin, jbin;
+
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+
+  double xtmpj, iLambda, jLambda, ijLambda;
+
+  int This_Step = update->ntimestep;
+  if(This_Step >= AT_Update_Time_Begin && This_Step <= AT_Update_Time_End && AT_Pressure_Comp_Flag != 0) AT_Pressure_Compensation_Run = 1;
+
+
+  for (int i = 0; i < nmolecules; i++) {
+      AT_mol_f_H[i][0] = AT_mol_f_H[i][1] = AT_mol_f_H[i][2] = 0;
+      AT_mol_f_all_H[i][0] = AT_mol_f_all_H[i][1] = AT_mol_f_all_H[i][2] = 0;
+  }
+
+  // loop over neighbors of my atoms
+//  if(update->ntimestep<AT_Restart_Time_Step+1)return;
+
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
+    qtmp = q[i];
+    xtmp = x[i][0];
+    ytmp = x[i][1];
+    ztmp = x[i][2];
+    itype = type[i];
+    imoltypeH = moltypeH[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
+    
+    iLambda = lambdaH[i];
+
+    if (eflag) {
+      double e_self = -(e_shift/2.0 + alpha/MY_PIS) * qtmp*qtmp*qqrd2e;
+//      e_self = 0;
+      ev_tally(i,i,nlocal,0,0.0,e_self,0.0,0.0,0.0,0.0);
+    }
+
+    for (jj = 0; jj < jnum; jj++) {
+      j = jlist[jj];
+      factor_lj = special_lj[sbmask(j)];
+      factor_coul = special_coul[sbmask(j)];
+      j &= NEIGHMASK;
+
+      jLambda = lambdaH[j];
+
+      if(iLambda==0 && jLambda==0 && AllAtomistic!=1)continue;
+
+
+      delx = xtmp - x[j][0];
+      dely = ytmp - x[j][1];
+      delz = ztmp - x[j][2];
+      rsq = delx*delx + dely*dely + delz*delz;
+      jtype = type[j];
+      jmoltypeH = moltypeH[j];
+
+      imol = molecule[i];
+      jmol = molecule[j];
+      if (AT_molmap_H) {
+          imol = AT_molmap_H[imol-idlo];
+          jmol = AT_molmap_H[jmol-idlo];
+      }
+      else {
+          imol--;
+          jmol--;
+      }
+
+//      if(imol == jmol)continue;
+      if (rsq < cutsq[itype][jtype]) {
+        r2inv = 1.0/rsq;
+
+        if (rsq < cut_ljsq[itype][jtype]) {
+          r6inv = r2inv*r2inv*r2inv;
+          forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+        } else forcelj = 0.0;
+
+        if (rsq < cut_coulsq) {
+          r = sqrt(rsq);
+          prefactor = factor_coul * qqrd2e*qtmp*q[j]/r;
+          erfcd = exp(-alpha*alpha*r*r);
+          t = 1.0 / (1.0 + EWALD_P*alpha*r);
+          erfcc = t * (A1+t*(A2+t*(A3+t*(A4+t*A5)))) * erfcd;
+          forcecoul = prefactor * (erfcc/r + 2.0*alpha/MY_PIS * erfcd + 
+            r*f_shift) * r;
+        } else forcecoul = 0.0;
+
+        if(((iLambda==1 && jLambda==1) || AllAtomistic)){
+
+            fpair = (forcecoul + factor_lj*forcelj) * r2inv;
+            f[i][0] += delx*fpair;
+            f[i][1] += dely*fpair;
+            f[i][2] += delz*fpair;
+
+            if (newton_pair || j < nlocal) {
+                f[j][0] -= delx*fpair;
+                f[j][1] -= dely*fpair;
+                f[j][2] -= delz*fpair;
+            }
+
+            if (eflag) {
+            if (rsq < cut_ljsq[itype][jtype]) {
+                evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+                        offset[itype][jtype];
+                evdwl *= factor_lj;
+              } else evdwl = 0.0;
+          
+              if (rsq < cut_coulsq) {
+                ecoul = prefactor * (erfcc - r*e_shift - rsq*f_shift);
+              } else ecoul = 0.0;
+            }
+            if (evflag) ev_tally(i,j,nlocal,newton_pair,
+                                 evdwl,ecoul,fpair,delx,dely,delz);
+        }
+
+        else if(iLambda !=0 || jLambda != 0){
+
+                ijLambda = 0.5 * (iLambda + jLambda);
+                fpair = (forcecoul + factor_lj*forcelj) *ijLambda* r2inv;
+
+                if (rsq < cut_coulsq)
+                    Vij_Coul = 0.5*prefactor * (erfcc - r*e_shift - rsq*f_shift);
+                else Vij_Coul = 0.0;
+
+
+                if (rsq < cut_ljsq[itype][jtype])
+                  Vij_Lj = 0.5*factor_lj*(r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+                          offset[itype][jtype]);
+                else Vij_Lj = 0;
+
+                f[i][0] += delx*fpair;
+                f[i][1] += dely*fpair;
+                f[i][2] += delz*fpair;
+
+                ibin = floor(iLambda/AT_lambda_Increment);
+                if(ibin==AT_Bin_Num)ibin = AT_Bin_Num - 1;
+
+                if(AT_Pressure_Compensation_Run != 0 && iLambda != 0 && iLambda != 1)Comp_Energy_H[ibin][imoltypeH-1] += Vij_Coul+Vij_Lj;
+
+                AT_mol_f_H[imol][0] += -(Vij_Coul+Vij_Lj)*gradlambdaH[i][0];
+                AT_mol_f_H[imol][1] += -(Vij_Coul+Vij_Lj)*gradlambdaH[i][1];
+                AT_mol_f_H[imol][2] += -(Vij_Coul+Vij_Lj)*gradlambdaH[i][2];
+
+                if (newton_pair || j < nlocal) {
+                    f[j][0] -= delx*fpair;
+                    f[j][1] -= dely*fpair;
+                    f[j][2] -= delz*fpair;
+
+                    jbin = floor(jLambda/AT_lambda_Increment);
+                    if(jbin==AT_Bin_Num)jbin = AT_Bin_Num - 1;
+
+                    if(AT_Pressure_Compensation_Run != 0 && jLambda != 0 && jLambda != 1)Comp_Energy_H[jbin][jmoltypeH-1] += Vij_Coul+Vij_Lj;
+
+                    AT_mol_f_H[jmol][0] += -(Vij_Coul+Vij_Lj)*gradlambdaH[j][0];
+                    AT_mol_f_H[jmol][1] += -(Vij_Coul+Vij_Lj)*gradlambdaH[j][1];
+                    AT_mol_f_H[jmol][2] += -(Vij_Coul+Vij_Lj)*gradlambdaH[j][2];
+
+                }
+
+                if (eflag) {
+                    ecoul = ijLambda*Vij_Coul*2.0;
+                    evdwl = ijLambda*Vij_Lj*2.0;
+
+                }
+                if (evflag) ev_tally(i,j,nlocal,newton_pair,
+                                     evdwl,ecoul,fpair,delx,dely,delz);
+            }
+
+
+
+      }
+    }
+  }
+
+    MPI_Allreduce(&AT_mol_f_H[0][0],&AT_mol_f_all_H[0][0],3*nmolecules,MPI_DOUBLE,MPI_SUM,world);
+
+    if(AT_Pressure_Compensation_Run != 0 && AT_Pressure_Comp_Flag != 0){
+
+        for (int i = 0; i < nlocal; i++){
+            iLambda = lambdaH[i];
+            if(replambdaH[i]!=0 && iLambda != 0 && iLambda != 1){
+                ibin = floor(iLambda/AT_lambda_Increment);
+                if(ibin==AT_Bin_Num)ibin = AT_Bin_Num - 1;
+                imoltypeH = moltypeH[i]-1;
+                Comp_Energy_Num_H[ibin][imoltypeH]++;
+            }
+        }
+
+        if(This_Step % AT_Update_Frequency == 0)AT_Update_Compensation_Energy();
+
+    }
+
+
+    if(This_Step == AT_Update_Time_End && AT_Pressure_Compensation_Run != 0)AT_Print_Compensation_Energy();
+
+    double mol_mass,mass_frac;
+
+    if(AllAtomistic != 1){
+        if(AT_Pressure_Comp_Flag != 0){
+            for (int i = 0; i < nlocal; i++){
+                iLambda = lambdaH[i];
+                if(iLambda != 0 && iLambda != 1){
+                    imol = molecule[i];
+                    if (AT_molmap_H)imol = AT_molmap_H[imol-idlo];
+                    else imol--;
+                    mol_mass = AT_masstotal_H[imol];
+                    mass_frac = mass[type[i]] / mol_mass;
+                    ibin = floor(iLambda/AT_lambda_Increment);
+                    imoltypeH = moltypeH[i] - 1;
+
+                    f[i][0] += mass_frac*(AT_mol_f_all_H[imol][0]+gradlambdaH[i][0]*Mean_Comp_Energy_H[ibin][imoltypeH]);
+                    f[i][1] += mass_frac*(AT_mol_f_all_H[imol][1]+gradlambdaH[i][1]*Mean_Comp_Energy_H[ibin][imoltypeH]);
+                    f[i][2] += mass_frac*(AT_mol_f_all_H[imol][2]+gradlambdaH[i][2]*Mean_Comp_Energy_H[ibin][imoltypeH]);
+                    if (evflag) ev_tally(i,i,nlocal,newton_pair,
+                                       -0.5*Int_Mean_Energy_H[ibin][imoltypeH],0.0,0.0,0.0,0.0,0.0);
+
+                }
+
+            }
+
+        }
+        else{
+
+            for (int i = 0; i < nlocal; i++){
+
+                iLambda = lambdaH[i];
+                if(iLambda != 0 && iLambda != 1){
+
+                    imol = molecule[i];
+                    if (AT_molmap_H)imol = AT_molmap_H[imol-idlo];
+                    else imol--;
+                    mol_mass = AT_masstotal_H[imol];
+                    mass_frac = mass[type[i]] / mol_mass;
+                    ibin = floor(iLambda/AT_lambda_Increment);
+
+                    f[i][0] += mass_frac*(AT_mol_f_all_H[imol][0]);
+                    f[i][1] += mass_frac*(AT_mol_f_all_H[imol][1]);
+                    f[i][2] += mass_frac*(AT_mol_f_all_H[imol][2]);
+
+                }
+
+            }
+
+        }
+
+        }
+
+
+
+    if(This_Step == AT_Update_Time_End)AT_Pressure_Compensation_Run = 0;
+
+  if (vflag_fdotr) virial_fdotr_compute();
+}
+
+/* ----------------------------------------------------------------------
+   allocate all arrays
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::allocate()
+{
+  allocated = 1;
+  int n = atom->ntypes;
+
+  memory->create(setflag,n+1,n+1,"pair:setflag");
+  for (int i = 1; i <= n; i++)
+    for (int j = i; j <= n; j++)
+      setflag[i][j] = 0;
+
+  memory->create(cutsq,n+1,n+1,"pair:cutsq");
+
+  memory->create(cut_lj,n+1,n+1,"pair:cut_lj");
+  memory->create(cut_ljsq,n+1,n+1,"pair:cut_ljsq");
+  memory->create(epsilon,n+1,n+1,"pair:epsilon");
+  memory->create(sigma,n+1,n+1,"pair:sigma");
+  memory->create(lj1,n+1,n+1,"pair:lj1");
+  memory->create(lj2,n+1,n+1,"pair:lj2");
+  memory->create(lj3,n+1,n+1,"pair:lj3");
+  memory->create(lj4,n+1,n+1,"pair:lj4");
+  memory->create(offset,n+1,n+1,"pair:offset");
+}
+
+/* ----------------------------------------------------------------------
+   global settings
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::settings(int narg, char **arg)
+{
+  if (narg != 5) error->all(FLERR,"Illegal pair_style command");
+
+  alpha = force->numeric(FLERR,arg[0]);
+  cut_lj_global = force->numeric(FLERR,arg[1]);
+  cut_coul = force->numeric(FLERR,arg[2]);
+  
+  AllAtomistic = force->numeric(FLERR,arg[3]);
+  Load_File_Flag = force->numeric(FLERR,arg[4]);
+  // reset cutoffs that have been explicitly set
+
+  if (allocated) {
+    int i,j;
+    for (i = 1; i <= atom->ntypes; i++)
+      for (j = i+1; j <= atom->ntypes; j++)
+        if (setflag[i][j])
+          cut_lj[i][j] = cut_lj_global;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   set coeffs for one or more type pairs
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::coeff(int narg, char **arg)
+{
+  if (narg < 4 || narg > 5) 
+    error->all(FLERR,"Incorrect args for pair coefficients");
+  if (!allocated) allocate();
+
+  int ilo,ihi,jlo,jhi;
+  force->bounds(arg[0],atom->ntypes,ilo,ihi);
+  force->bounds(arg[1],atom->ntypes,jlo,jhi);
+  
+  double epsilon_one = force->numeric(FLERR,arg[2]);
+  double sigma_one = force->numeric(FLERR,arg[3]);
+
+  double cut_lj_one = cut_lj_global;
+  if (narg == 5) cut_lj_one = force->numeric(FLERR,arg[4]);
+    
+  int count = 0;
+  for (int i = ilo; i <= ihi; i++) {
+    for (int j = MAX(jlo,i); j <= jhi; j++) {
+      epsilon[i][j] = epsilon_one;
+      sigma[i][j] = sigma_one;
+      cut_lj[i][j] = cut_lj_one;
+      setflag[i][j] = 1;
+
+      count++;
+    }
+  }
+
+  if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
+}
+
+/* ----------------------------------------------------------------------
+   init specific to this pair style
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::init_style()
+{
+  if (!atom->q_flag)
+    error->all(FLERR,"Pair style lj/cut/coul/dsf requires atom attribute q");
+
+  if(me == 0){
+      if (screen)fprintf(screen,"AT_H_AdResS_allocated flag = %d\n",H_AdResS_allocated);
+      if (logfile)fprintf(logfile,"AT_H_AdResS_allocated flag = %d\n",H_AdResS_allocated);
+  }
+
+  if(!H_AdResS_allocated)H_AdResS_Allocation();
+
+  int This_Step = update->ntimestep;
+  AT_Restart_Time_Step = This_Step;
+
+  if((This_Step >= AT_Update_Time_End || Load_File_Flag) && AT_Pressure_Comp_Flag != 0)Load_Compensation_Pressure();
+
+  neighbor->request(this,instance_me);
+
+  cut_coulsq = cut_coul * cut_coul;
+  double erfcc = erfc(alpha*cut_coul); 
+  double erfcd = exp(-alpha*alpha*cut_coul*cut_coul);
+  f_shift = -(erfcc/cut_coulsq + 2.0/MY_PIS*alpha*erfcd/cut_coul); 
+  e_shift = erfcc/cut_coul - f_shift*cut_coul; 
+
+}
+
+/* ----------------------------------------------------------------------
+   init for one type pair i,j and corresponding j,i
+------------------------------------------------------------------------- */
+
+double PairLJCutCoulDSFHARSAT::init_one(int i, int j)
+{
+  if (setflag[i][j] == 0) {
+    epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
+                               sigma[i][i],sigma[j][j]);
+    sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
+    cut_lj[i][j] = mix_distance(cut_lj[i][i],cut_lj[j][j]);
+  }
+
+  double cut = MAX(cut_lj[i][j],cut_coul);
+  cut_ljsq[i][j] = cut_lj[i][j] * cut_lj[i][j];
+  
+  lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
+  lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
+  lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
+  lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
+     
+  if (offset_flag) {
+    double ratio = sigma[i][j] / cut_lj[i][j];
+    offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
+  } else offset[i][j] = 0.0;
+  
+  cut_ljsq[j][i] = cut_ljsq[i][j];
+  lj1[j][i] = lj1[i][j];
+  lj2[j][i] = lj2[i][j];
+  lj3[j][i] = lj3[i][j];
+  lj4[j][i] = lj4[i][j];
+  offset[j][i] = offset[i][j];
+
+  // compute I,J contribution to long-range tail correction
+  // count total # of atoms of type I and J via Allreduce
+
+  if (tail_flag) {
+    int *type = atom->type;
+    int nlocal = atom->nlocal;
+
+    double count[2],all[2];
+    count[0] = count[1] = 0.0;
+    for (int k = 0; k < nlocal; k++) {
+      if (type[k] == i) count[0] += 1.0;
+      if (type[k] == j) count[1] += 1.0;
+    }
+    MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
+        
+    double sig2 = sigma[i][j]*sigma[i][j];
+    double sig6 = sig2*sig2*sig2;
+    double rc3 = cut_lj[i][j]*cut_lj[i][j]*cut_lj[i][j];
+    double rc6 = rc3*rc3;
+    double rc9 = rc3*rc6;
+    etail_ij = 8.0*MY_PI*all[0]*all[1]*epsilon[i][j] * 
+               sig6 * (sig6 - 3.0*rc6) / (9.0*rc9); 
+    ptail_ij = 16.0*MY_PI*all[0]*all[1]*epsilon[i][j] * 
+               sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9); 
+  } 
+
+  return cut;
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::write_restart(FILE *fp)
+{
+  write_restart_settings(fp);
+
+  int i,j;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      fwrite(&setflag[i][j],sizeof(int),1,fp);
+      if (setflag[i][j]) {
+        fwrite(&epsilon[i][j],sizeof(double),1,fp);
+        fwrite(&sigma[i][j],sizeof(double),1,fp);
+        fwrite(&cut_lj[i][j],sizeof(double),1,fp);
+	    }
+    }
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::read_restart(FILE *fp)
+{
+  read_restart_settings(fp);
+  allocate();
+
+  int i,j;
+  int me = comm->me;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
+      MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
+      if (setflag[i][j]) {
+        if (me == 0) {
+          fread(&epsilon[i][j],sizeof(double),1,fp);
+          fread(&sigma[i][j],sizeof(double),1,fp);
+          fread(&cut_lj[i][j],sizeof(double),1,fp);
+        }
+        MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
+        MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
+        MPI_Bcast(&cut_lj[i][j],1,MPI_DOUBLE,0,world);
+      }
+    }
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::write_restart_settings(FILE *fp)
+{
+  fwrite(&alpha,sizeof(double),1,fp);
+  fwrite(&cut_lj_global,sizeof(double),1,fp);
+  fwrite(&cut_coul,sizeof(double),1,fp);
+  fwrite(&offset_flag,sizeof(int),1,fp);
+  fwrite(&mix_flag,sizeof(int),1,fp);
+  fwrite(&tail_flag,sizeof(int),1,fp);
+}
+
+/* ----------------------------------------------------------------------
+  proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairLJCutCoulDSFHARSAT::read_restart_settings(FILE *fp)
+{
+  if (comm->me == 0) {
+    fread(&alpha,sizeof(double),1,fp);
+    fread(&cut_lj_global,sizeof(double),1,fp);
+    fread(&cut_coul,sizeof(double),1,fp);
+    fread(&offset_flag,sizeof(int),1,fp);
+    fread(&mix_flag,sizeof(int),1,fp);
+    fread(&tail_flag,sizeof(int),1,fp);
+  }
+  MPI_Bcast(&alpha,1,MPI_DOUBLE,0,world);
+  MPI_Bcast(&cut_lj_global,1,MPI_DOUBLE,0,world);
+  MPI_Bcast(&cut_coul,1,MPI_DOUBLE,0,world);
+  MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
+  MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
+  MPI_Bcast(&tail_flag,1,MPI_INT,0,world);
+}
+
+/* ---------------------------------------------------------------------- */
+
+double PairLJCutCoulDSFHARSAT::single(int i, int j, int itype, int jtype, double rsq,
+                                double factor_coul, double factor_lj,
+                                double &fforce)
+{
+  double r2inv,r6inv,r,erfcc,erfcd,prefactor;
+  double forcecoul,forcelj,phicoul,philj;
+  
+  r2inv = 1.0/rsq;
+  if (rsq < cut_ljsq[itype][jtype]) {
+    r6inv = r2inv*r2inv*r2inv;
+    forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+  } else forcelj = 0.0;
+
+  if (rsq < cut_coulsq) {
+    r = sqrt(rsq);
+    prefactor = factor_coul * force->qqrd2e * atom->q[i]*atom->q[j]/r;
+    erfcc = erfc(alpha*r); 
+    erfcd = exp(-alpha*alpha*r*r);
+    forcecoul = prefactor * (erfcc/r + 2.0*alpha/MY_PIS * erfcd + 
+      r*f_shift) * r;
+  } else forcecoul = 0.0;
+  
+  fforce = (forcecoul + factor_lj*forcelj) * r2inv;
+      
+  double eng = 0.0;
+  if (rsq < cut_ljsq[itype][jtype]) {
+    philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+      offset[itype][jtype];
+    eng += factor_lj*philj;
+  }
+
+  if (rsq < cut_coulsq) { 
+    phicoul = prefactor * (erfcc - r*e_shift - rsq*f_shift);
+    eng += phicoul;
+  } 
+  
+  eng=0;
+  return eng;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void *PairLJCutCoulDSFHARSAT::extract(const char *str, int &dim)
+{
+  if (strcmp(str,"cut_coul") == 0) {
+    dim = 0;
+    return (void *) &cut_coul;
+  }
+  return NULL;
+}
+
+
+int PairLJCutCoulDSFHARSAT::molecules_in_group(tagint &idlo, tagint &idhi)
+{
+  int i;
+
+  memory->destroy(AT_molmap_H);
+  AT_molmap_H = NULL;
+
+  // find lo/hi molecule ID for any atom in group
+  // warn if atom in group has ID = 0
+
+  tagint *molecule = atom->molecule;
+  int *mask = atom->mask;
+  int nlocal = atom->nlocal;
+
+  tagint lo = BIG;
+  tagint hi = -BIG;
+  int flag = 0;
+  for (i = 0; i < nlocal; i++)
+  {
+//    if (mask[i] & groupbit) {
+      if (mask[i]) {
+      if (molecule[i] == 0) flag = 1;
+      lo = MIN(lo,molecule[i]);
+      hi = MAX(hi,molecule[i]);
+    }
+  }
+
+  int flagall;
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,"Atom with molecule ID = 0 included in "
+                   "compute molecule group");
+
+  MPI_Allreduce(&lo,&idlo,1,MPI_LMP_TAGINT,MPI_MIN,world);
+  MPI_Allreduce(&hi,&idhi,1,MPI_LMP_TAGINT,MPI_MAX,world);
+  if (idlo == BIG) return 0;
+
+  // molmap = vector of length nlen
+  // set to 1 for IDs that appear in group across all procs, else 0
+
+  tagint nlen_tag = idhi-idlo+1;
+  if (nlen_tag > MAXSMALLINT)
+    error->all(FLERR,"Too many molecules for compute");
+  int nlen = (int) nlen_tag;
+
+  memory->create(AT_molmap_H,nlen,"pair:molmap_H");
+  for (i = 0; i < nlen; i++) AT_molmap_H[i] = 0;
+
+  for (i = 0; i < nlocal; i++)
+   // if (mask[i] & groupbit)
+       if (mask[i])
+      AT_molmap_H[molecule[i]-idlo] = 1;
+
+  int *AT_molmapall;
+  memory->create(AT_molmapall,nlen,"pair:AT_molmapall");
+  MPI_Allreduce(AT_molmap_H,AT_molmapall,nlen,MPI_INT,MPI_MAX,world);
+
+  // nmolecules = # of non-zero IDs in molmap
+  // molmap[i] = index of molecule, skipping molecules not in group with -1
+
+  int nmolecules = 0;
+  for (i = 0; i < nlen; i++)
+    if (AT_molmapall[i]) AT_molmap_H[i] = nmolecules++;
+    else AT_molmap_H[i] = -1;
+  memory->destroy(AT_molmapall);
+
+  // warn if any molecule has some atoms in group and some not in group
+
+  flag = 0;
+  for (i = 0; i < nlocal; i++) {
+//    if (mask[i] & groupbit) continue;
+      if (mask[i]) continue;
+    if (molecule[i] < idlo || molecule[i] > idhi) continue;
+    if (AT_molmap_H[molecule[i]-idlo] >= 0) flag = 1;
+  }
+
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,
+                   "One or more compute molecules has atoms not in group");
+
+  // if molmap simply stores 1 to Nmolecules, then free it
+
+  if (idlo == 1 && idhi == nmolecules && nlen == nmolecules) {
+    memory->destroy(AT_molmap_H);
+    AT_molmap_H = NULL;
+  }
+  return nmolecules;
+}
+
+
+void PairLJCutCoulDSFHARSAT::AT_Print_Compensation_Energy(){
+
+    FILE *fp1;
+    fp1 = fopen("Mean_Comp_Energy_AT.txt","w");
+    if (fp1 == NULL) {
+        char str[128];
+        sprintf(str,"Cannot open Mean_Comp_Energy_AT.txt file %s","Mean_Comp_Energy_AT.txt");
+        error->one(FLERR,str);
+    }
+
+    for(int i = 0;i < AT_Bin_Num; i++){
+        fprintf(fp1,"%d",i+1);
+            for(int j = 0; j < atom->nmoltypesH; j++){
+                fprintf(fp1,"\t%.10f",Mean_Comp_Energy_H[i][j]);
+            }
+            fprintf(fp1,"\n");
+    }
+    fclose(fp1);
+}
+
+
+
+void PairLJCutCoulDSFHARSAT::AT_Update_Compensation_Energy(){
+    MPI_Allreduce(&Comp_Energy_H[0][0],&Comp_Energy_all_H[0][0],AT_Bin_Num*(atom->nmoltypesH+1),MPI_DOUBLE,MPI_SUM,world);
+    MPI_Allreduce(&Comp_Energy_Num_H[0][0],&Comp_Energy_Num_all_H[0][0],AT_Bin_Num*(atom->nmoltypesH+1),MPI_INT,MPI_SUM,world);
+
+    for(int j = 0;j < atom->nmoltypesH; j++){
+        for(int i = 0;i < AT_Bin_Num; i++){
+            Mean_Energy_H[i][j] = Comp_Energy_all_H[i][j] / Comp_Energy_Num_all_H[i][j];
+            Mean_Comp_Energy_H[i][j] = (Comp_Counter_H * Mean_Comp_Energy_H[i][j] + Mean_Energy_H[i][j]) / (Comp_Counter_H + 1);
+            Int_Mean_Energy_H[i][j]=0;
+        }
+    }
+
+    Comp_Counter_H++;
+
+    for(int j = 0;j < atom->nmoltypesH; j++){
+        for(int i = 0;i < AT_Bin_Num; i++){
+            Comp_Energy_Num_H[i][j] = 0;
+            Comp_Energy_Num_all_H[i][j] = 0;
+            Comp_Energy_H[i][j] = 0;
+            Comp_Energy_all_H[i][j] =0;
+        }
+
+    }
+    if (me == 0)AT_Print_Compensation_Energy();
+
+
+}
+
+
+void PairLJCutCoulDSFHARSAT::Load_Compensation_Pressure(){
+
+    if(me == 0){
+        FILE *fp1;
+        char str[128];
+
+        fp1 = fopen("Mean_Comp_Energy_AT.txt","r");
+        if (fp1 == NULL) {
+            sprintf(str,"Cannot open Mean_Comp_Energy_AT.txt file %s","Mean_Comp_Energy_AT.txt");
+            error->one(FLERR,str);
+        }
+
+        int i1;
+
+        while (!feof(fp1)){
+                fscanf (fp1,"%d",&i1);
+                for(int j=0;j<atom->nmoltypesH;j++)fscanf (fp1,"\t%f",&Mean_Comp_Energy_H[i1-1][j]);
+                fscanf (fp1,"\n");
+                if(i1 > AT_Bin_Num){
+                    sprintf(str,"At drift force compensation bin number mismatches %d != %d",AT_Bin_Num,i1);
+                    error->one(FLERR,str);
+                }
+
+        }
+
+        fclose(fp1);
+
+
+        if(me==0){
+            if(screen)fprintf(screen,"AT_Pressure componsation forces distributed successfully!\n");
+            if(logfile)fprintf(logfile,"AT_Pressure componsation forces distributed successfully!\n");
+        }
+
+    }
+
+    MPI_Bcast(Mean_Comp_Energy_H,AT_Bin_Num,MPI_DOUBLE,0,world);
+
+
+}
+
+void PairLJCutCoulDSFHARSAT::H_AdResS_Allocation(){
+    for (int i = 0; i < modify->nfix; i++){
+      if (strcmp(modify->fix[i]->style,"LambdaH/calc") == 0){
+             lambda_H_fix = (FixLambdaHCalc *) modify->fix[i];
+             AT_lambda_Increment = lambda_H_fix->Pressure_lambda_Increment;
+             AT_Bin_Num = lambda_H_fix->Pressure_Bin_Num;
+             AT_Update_Frequency = lambda_H_fix->Pressure_Update_Frequency;
+             AT_Update_Time_Begin = lambda_H_fix->Pressure_Update_Time_Begin;
+             AT_Update_Time_End = lambda_H_fix->Pressure_Update_Time_End;
+             AT_Pressure_Comp_Flag = lambda_H_fix->Pressure_Comp_Flag;
+             AT_center_box = lambda_H_fix->center_box;
+             AT_Hybrid_Style = lambda_H_fix->Hybrid_Style;
+      }
+    }
+
+    if(me == 0){
+        if (screen){
+            fprintf(screen,"AT_lambda_Increment= %f\n",AT_lambda_Increment);
+            fprintf(screen,"AT_Bin_Num= %d\n",AT_Bin_Num);
+            fprintf(screen,"AT_Update_Frequency= %d\n",AT_Update_Frequency);
+            fprintf(screen,"AT_Update_Time_Begin= %d\n",AT_Update_Time_Begin);
+            fprintf(screen,"AT_Update_Time_End= %d\n",AT_Update_Time_End);
+            fprintf(screen,"AT_Pressure_Comp_Flag= %d\n",AT_Pressure_Comp_Flag);
+        }
+
+        if (logfile){
+            fprintf(logfile,"AT_lambda_Increment= %f\n",AT_lambda_Increment);
+            fprintf(logfile,"AT_Bin_Num= %d\n",AT_Bin_Num);
+            fprintf(logfile,"AT_Update_Frequency= %d\n",AT_Update_Frequency);
+            fprintf(logfile,"AT_Update_Time_Begin= %d\n",AT_Update_Time_Begin);
+            fprintf(logfile,"AT_Update_Time_End= %d\n",AT_Update_Time_End);
+            fprintf(logfile,"AT_Pressure_Comp_Flag= %d\n",AT_Pressure_Comp_Flag);
+        }
+    }
+
+    memory->create(Comp_Energy_Num_H,AT_Bin_Num,atom->nmoltypesH+1,"pairLJHAT:Comp_Energy_Num_H");
+    memory->create(Comp_Energy_Num_all_H,AT_Bin_Num,atom->nmoltypesH+1,"pairLJHAT:Comp_Energy_Num_all_H");
+
+    memory->create(Int_Mean_Energy_H,AT_Bin_Num,atom->nmoltypesH+1,"pairLJHAT:Int_Mean_Energy_H");
+    memory->create(Comp_Energy_H,AT_Bin_Num,atom->nmoltypesH+1,"pairLJHAT:Comp_Energy_H");
+    memory->create(Comp_Energy_all_H,AT_Bin_Num,atom->nmoltypesH+1,"pairLJHAT:Comp_Energy_all_H");
+    memory->create(Mean_Comp_Energy_H,AT_Bin_Num,atom->nmoltypesH+1,"pairLJHAT:Mean_Comp_Energy_H");
+    memory->create(Mean_Energy_H,AT_Bin_Num,atom->nmoltypesH+1,"pairLJHAT:Mean_Energy_H");
+
+
+    for(int j=0;j<atom->nmoltypesH;j++){
+        for(int i = 0;i < AT_Bin_Num; i++){
+            Int_Mean_Energy_H[i][j]=0;
+            Comp_Energy_H[i][j]=0;
+            Comp_Energy_all_H[i][j]=0;
+            Mean_Comp_Energy_H[i][j]=0;
+            Comp_Energy_Num_H[i][j] = 0;
+            Comp_Energy_Num_all_H[i][j] = 0;
+        }
+
+    }
+
+    H_AdResS_allocated = 1;
+}
+
diff --git a/src/USER-HADRESS/pair_lj_cut_coul_dsf_hars_at.h b/src/USER-HADRESS/pair_lj_cut_coul_dsf_hars_at.h
new file mode 100644
index 000000000..b5d5076c4
--- /dev/null
+++ b/src/USER-HADRESS/pair_lj_cut_coul_dsf_hars_at.h
@@ -0,0 +1,115 @@
+/* -*- 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 PAIR_CLASS
+
+PairStyle(lj/cut/coul/dsf/hars/at,PairLJCutCoulDSFHARSAT)
+
+#else
+
+#ifndef LMP_PAIR_LJ_CUT_COUL_DSF_HARS_AT_H
+#define LMP_PAIR_LJ_CUT_COUL_DSF_HARS_AT_H
+
+#include "pair.h"
+
+namespace LAMMPS_NS {
+
+class PairLJCutCoulDSFHARSAT : public Pair {
+ public:
+  PairLJCutCoulDSFHARSAT(class LAMMPS *);
+  ~PairLJCutCoulDSFHARSAT();
+  void compute(int, int);
+  void settings(int, char **);
+  void coeff(int, char **);
+  void init_style();
+  double init_one(int, int);
+  void write_restart(FILE *);
+  void read_restart(FILE *);
+  void write_restart_settings(FILE *);
+  void read_restart_settings(FILE *);
+  double single(int, int, int, int, double, double, double, double &);
+  void *extract(const char *, int &);
+
+  void AT_Print_Compensation_Energy();
+  void AT_Update_Compensation_Energy();
+
+ protected:
+  double cut_lj_global;
+  double **cut_lj,**cut_ljsq;
+  double **epsilon,**sigma;
+  double **lj1,**lj2,**lj3,**lj4,**offset;
+  
+  double cut_coul,cut_coulsq;
+  double alpha;
+  double f_shift,e_shift;
+  
+  void allocate();
+  class FixLambdaHCalc *lambda_H_fix;
+
+  int AllAtomistic;
+
+  //private:
+    int me;
+
+    int H_AdResS_allocated;
+
+    int **Comp_Energy_Num_H,**Comp_Energy_Num_all_H, Comp_Counter_H;
+
+    double AT_lambda_Increment;
+    int AT_Bin_Num, AT_Update_Frequency, AT_Update_Time_End, AT_Update_Time_Begin;
+    int AT_Pressure_Compensation_Run;
+    int AT_Pressure_Comp_Flag;
+
+    int AT_Restart_Time_Step;
+    double *AT_center_box,AT_x0lo;
+    int AT_Hybrid_Style;
+    double **Int_Mean_Energy_H, **Comp_Energy_H, **Comp_Energy_all_H, **Mean_Energy_H, **Mean_Comp_Energy_H;
+
+     int nmolecules;
+     tagint idlo,idhi;
+
+     double *AT_massproc_H,*AT_masstotal_H;
+
+     double **AT_mol_f_H, **AT_mol_f_all_H;
+
+     int *AT_molmap_H;                 // convert molecule ID to local index
+     int Load_File_Flag;
+
+     int molecules_in_group(tagint &, tagint &);
+     void Load_Compensation_Pressure();
+     void H_AdResS_Allocation();
+
+};
+
+}
+
+#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: Incorrect args for pair coefficients
+
+Self-explanatory.  Check the input script or data file.
+
+E: Pair style lj/cut/coul/dsf requires atom attribute q
+
+The atom style defined does not have these attributes.
+
+*/
diff --git a/src/USER-HADRESS/pair_lj_cut_hars_at.cpp b/src/USER-HADRESS/pair_lj_cut_hars_at.cpp
new file mode 100644
index 000000000..f605c92ac
--- /dev/null
+++ b/src/USER-HADRESS/pair_lj_cut_hars_at.cpp
@@ -0,0 +1,1039 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain rights in this software.  This software is distributed under
+   the GNU General Public License.
+
+   See the README file in the top-level LAMMPS directory.
+------------------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------
+   Contributing author: Paul Crozier (SNL)
+------------------------------------------------------------------------- */
+
+#include "math.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "pair_lj_cut_hars_at.h"
+#include "atom.h"
+#include "comm.h"
+#include "force.h"
+#include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
+#include "update.h"
+#include "integrate.h"
+#include "respa.h"
+#include "math_const.h"
+#include "memory.h"
+#include "error.h"
+#include "domain.h"
+#include "fix.h"
+#include "fix_lambdah_calc.h"
+#include "modify.h"
+
+using namespace LAMMPS_NS;
+using namespace MathConst;
+#define BIG MAXTAGINT
+
+/* ---------------------------------------------------------------------- */
+
+PairLJCutHARSAT::PairLJCutHARSAT(LAMMPS *lmp) : Pair(lmp)
+{
+  respa_enable = 1;
+  writedata = 1;
+
+  AT_massproc_H = NULL;
+  AT_masstotal_H = NULL;
+  AT_molmap_H = NULL;
+  AT_mol_f_H = NULL;
+  AT_mol_f_all_H = NULL;
+  Comp_Energy_Num_H = NULL;
+  Comp_Energy_Num_all_H = NULL;
+
+  Int_Mean_Energy_H = NULL;
+  Mean_Energy_H = NULL;
+  Comp_Energy_H = NULL;
+  Comp_Energy_all_H = NULL;
+  Mean_Comp_Energy_H = NULL;
+
+  AT_molmap_H = NULL;
+  nmolecules = molecules_in_group(idlo,idhi);
+
+  H_AdResS_allocated = 0;
+
+  AT_Pressure_Compensation_Run = 0;
+  Comp_Counter_H = 0;
+  memory->create(AT_massproc_H,nmolecules,"pair:AT_massproc_H");
+  memory->create(AT_masstotal_H,nmolecules,"pair:AT_masstotal_H");
+  memory->create(AT_mol_f_H,nmolecules,3,"pair:AT_mol_f_H");
+  memory->create(AT_mol_f_all_H,nmolecules,3,"pair:AT_mol_f_all_H");
+
+
+  // compute masstotal for each molecule
+  MPI_Comm_rank(world, &me);
+  int *mask = atom->mask;
+  tagint *molecule = atom->molecule;
+  int *type = atom->type;
+  double *mass = atom->mass;
+  double *rmass = atom->rmass;
+  int nlocal = atom->nlocal;
+
+  tagint imol;
+  double massone;
+
+  for (int i = 0; i < nmolecules; i++) AT_massproc_H[i] = 0.0;
+
+
+  for (int i = 0; i < nlocal; i++)
+  {
+//    if (mask[i] & groupbit) {
+    if (mask[i]) {
+      if (rmass) massone = rmass[i];
+      else massone = mass[type[i]];
+      imol = molecule[i];
+      if (AT_molmap_H) imol = AT_molmap_H[imol-idlo];
+      else imol--;
+      AT_massproc_H[imol] += massone;
+
+    }
+  }
+
+  MPI_Allreduce(AT_massproc_H,AT_masstotal_H,nmolecules,MPI_DOUBLE,MPI_SUM,world);
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+PairLJCutHARSAT::~PairLJCutHARSAT()
+{
+  if (allocated) {
+      memory->destroy(setflag);
+      memory->destroy(cutsq);
+      memory->destroy(cut);
+      memory->destroy(epsilon);
+      memory->destroy(sigma);
+      memory->destroy(lj1);
+      memory->destroy(lj2);
+      memory->destroy(lj3);
+      memory->destroy(lj4);
+      memory->destroy(offset);
+      memory->destroy(AT_massproc_H);
+      memory->destroy(AT_masstotal_H);
+      memory->destroy(AT_molmap_H);
+      memory->destroy(AT_mol_f_H);
+      memory->destroy(AT_mol_f_all_H);
+      memory->destroy(Comp_Energy_Num_H);
+      memory->destroy(Comp_Energy_Num_all_H);
+      memory->destroy(Int_Mean_Energy_H);
+      memory->destroy(Mean_Energy_H);
+      memory->destroy(Comp_Energy_H);
+      memory->destroy(Comp_Energy_all_H);
+      memory->destroy(Mean_Comp_Energy_H);
+
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::compute(int eflag, int vflag)
+{
+  int i,j,ii,jj,inum,jnum,itype,jtype;
+  double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
+  double rsq,r2inv,r6inv,forcelj, factor_lj,Vij;
+  int *ilist,*jlist,*numneigh,**firstneigh;
+  int imoltypeH,jmoltypeH;
+
+  evdwl = 0.0;
+  if (eflag || vflag) ev_setup(eflag,vflag);
+  else evflag = vflag_fdotr = 0;
+
+  double **x = atom->x;
+  double **f = atom->f;
+  double *lambdaH = atom->lambdaH;
+  double **gradlambdaH = atom->gradlambdaH;
+  int *type = atom->type;
+  int nlocal = atom->nlocal;
+  double *special_lj = force->special_lj;
+  int newton_pair = force->newton_pair;
+  int imol,jmol;
+  tagint *molecule = atom->molecule;
+  double *mass = atom->mass;
+  int *replambdaH = atom->replambdaH;
+  int *moltypeH = atom->moltypeH;
+
+  int ibin, jbin;
+
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+
+  //if(update->ntimestep<3)return;
+
+  double xtmpj, iLambda, jLambda, ijLambda;
+
+  int This_Step = update->ntimestep;
+  if(This_Step >= AT_Update_Time_Begin && This_Step <= AT_Update_Time_End && AT_Pressure_Comp_Flag != 0) AT_Pressure_Compensation_Run = 1;
+
+
+  for (int i = 0; i < nmolecules; i++) {
+      AT_mol_f_H[i][0] = AT_mol_f_H[i][1] = AT_mol_f_H[i][2] = 0;
+      AT_mol_f_all_H[i][0] = AT_mol_f_all_H[i][1] = AT_mol_f_all_H[i][2] = 0;
+  }
+
+  for (ii = 0; ii < inum; ii++) {
+    i = ilist[ii];
+    xtmp = x[i][0];
+    ytmp = x[i][1];
+    ztmp = x[i][2];
+    itype = type[i];
+    imoltypeH = moltypeH[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
+
+    iLambda = lambdaH[i];
+
+    for (jj = 0; jj < jnum; jj++) {
+
+      j = jlist[jj];
+      factor_lj = special_lj[sbmask(j)];
+      j &= NEIGHMASK;
+      jLambda = lambdaH[j];
+
+
+      if(iLambda==0 && jLambda==0 && AllAtomistic!=1)continue;
+
+      delx = xtmp - x[j][0];
+      dely = ytmp - x[j][1];
+      delz = ztmp - x[j][2];
+
+      xtmpj = x[j][0];
+
+      rsq = delx*delx + dely*dely + delz*delz;
+      jtype = type[j];
+      jmoltypeH = moltypeH[j];
+
+      imol = molecule[i];
+      jmol = molecule[j];
+      if (AT_molmap_H) {
+          imol = AT_molmap_H[imol-idlo];
+          jmol = AT_molmap_H[jmol-idlo];
+      }
+      else {
+          imol--;
+          jmol--;
+      }
+
+
+      if (rsq < cutsq[itype][jtype] && lj1[itype][jtype] != 0 && (imol != jmol)) {
+
+
+          if(((iLambda==1 && jLambda==1) || AllAtomistic)){
+
+                r2inv = 1.0/rsq;
+                r6inv = r2inv*r2inv*r2inv;
+                forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+                fpair = factor_lj*forcelj*r2inv;
+
+                f[i][0] += delx*fpair;
+                f[i][1] += dely*fpair;
+                f[i][2] += delz*fpair;
+
+                if (newton_pair || j < nlocal) {
+                  f[j][0] -= delx*fpair;
+                  f[j][1] -= dely*fpair;
+                  f[j][2] -= delz*fpair;
+                }
+
+                if (eflag) {
+                    evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+                            offset[itype][jtype];
+                    evdwl *= factor_lj;
+                }
+
+                if (evflag) ev_tally(i,j,nlocal,newton_pair,
+                                     evdwl,0.0,fpair,delx,dely,delz);
+
+            }
+            else if(iLambda !=0 || jLambda != 0){
+
+
+                ijLambda = 0.5 * (iLambda + jLambda);
+                r2inv = 1.0/rsq;
+                r6inv = r2inv*r2inv*r2inv;
+                forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+
+                fpair = factor_lj*(forcelj*ijLambda)*r2inv;
+
+                Vij = 0.5*(r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+                        offset[itype][jtype]);
+
+                f[i][0] += delx*fpair;
+                f[i][1] += dely*fpair;
+                f[i][2] += delz*fpair;
+
+                ibin = floor(iLambda/AT_lambda_Increment);
+                if(ibin==AT_Bin_Num)ibin = AT_Bin_Num - 1;
+                if(AT_Pressure_Compensation_Run != 0 && iLambda != 0 && iLambda != 1)Comp_Energy_H[ibin][imoltypeH-1] += Vij;
+
+                AT_mol_f_H[imol][0] += -Vij*gradlambdaH[i][0];
+                AT_mol_f_H[imol][1] += -Vij*gradlambdaH[i][1];
+                AT_mol_f_H[imol][2] += -Vij*gradlambdaH[i][2];
+
+                if (newton_pair || j < nlocal) {
+
+                  f[j][0] -= delx*fpair;
+                  f[j][1] -= dely*fpair;
+                  f[j][2] -= delz*fpair;
+
+                  jbin = floor(jLambda/AT_lambda_Increment);
+                  if(jbin==AT_Bin_Num)jbin = AT_Bin_Num - 1;
+                  if(AT_Pressure_Compensation_Run != 0 && jLambda != 0 && jLambda != 1)Comp_Energy_H[jbin][jmoltypeH-1] += Vij;
+
+                  AT_mol_f_H[jmol][0] += -Vij*gradlambdaH[j][0];
+                  AT_mol_f_H[jmol][1] += -Vij*gradlambdaH[j][1];
+                  AT_mol_f_H[jmol][2] += -Vij*gradlambdaH[j][2];
+
+                }
+
+                if (eflag) {
+
+                    evdwl = ijLambda*Vij*2.0;
+                    evdwl *= factor_lj;
+                }
+
+                if (evflag) ev_tally(i,j,nlocal,newton_pair,
+                                 evdwl,0.0,fpair,delx,dely,delz);
+
+            }
+        }
+
+      }
+    }
+
+
+
+    MPI_Allreduce(&AT_mol_f_H[0][0],&AT_mol_f_all_H[0][0],3*nmolecules,MPI_DOUBLE,MPI_SUM,world);
+
+    if(AT_Pressure_Compensation_Run != 0 && AT_Pressure_Comp_Flag != 0){
+
+        for (int i = 0; i < nlocal; i++){
+            iLambda = lambdaH[i];
+            if(replambdaH[i]!=0 && iLambda != 0 && iLambda != 1){
+
+                ibin = floor(iLambda/AT_lambda_Increment);
+                if(ibin==AT_Bin_Num)ibin = AT_Bin_Num - 1;
+
+                imoltypeH = moltypeH[i]-1;
+
+                Comp_Energy_Num_H[ibin][imoltypeH]++;
+            }
+        }
+
+        if(This_Step % AT_Update_Frequency == 0)AT_Update_Compensation_Energy();
+
+    }
+
+
+    if(This_Step == AT_Update_Time_End && AT_Pressure_Compensation_Run != 0)AT_Print_Compensation_Energy();
+
+    double mol_mass,mass_frac;
+
+    if(AllAtomistic != 1){
+
+        if(AT_Pressure_Comp_Flag != 0){
+
+            for (int i = 0; i < nlocal; i++){
+
+                iLambda = lambdaH[i];
+                if(iLambda != 0 && iLambda != 1){
+
+                    imol = molecule[i];
+                    if (AT_molmap_H)imol = AT_molmap_H[imol-idlo];
+                    else imol--;
+                    mol_mass = AT_masstotal_H[imol];
+                    mass_frac = mass[type[i]] / mol_mass;
+                    ibin = floor(iLambda/AT_lambda_Increment);
+                    imoltypeH = moltypeH[i] - 1;
+
+
+                    f[i][0] += mass_frac*(AT_mol_f_all_H[imol][0]+gradlambdaH[i][0]*Mean_Comp_Energy_H[ibin][imoltypeH]);
+                    f[i][1] += mass_frac*(AT_mol_f_all_H[imol][1]+gradlambdaH[i][1]*Mean_Comp_Energy_H[ibin][imoltypeH]);
+                    f[i][2] += mass_frac*(AT_mol_f_all_H[imol][2]+gradlambdaH[i][2]*Mean_Comp_Energy_H[ibin][imoltypeH]);
+                    if (evflag) ev_tally(i,i,nlocal,newton_pair,
+                                         -0.5*Int_Mean_Energy_H[ibin][imoltypeH],0.0,0.0,0.0,0.0,0.0);
+
+                }
+
+            }
+
+        }
+        else{
+
+            for (int i = 0; i < nlocal; i++){
+
+                iLambda = lambdaH[i];
+                if(iLambda != 0 && iLambda != 1){
+
+                    imol = molecule[i];
+                    if (AT_molmap_H)imol = AT_molmap_H[imol-idlo];
+                    else imol--;
+                    mol_mass = AT_masstotal_H[imol];
+                    mass_frac = mass[type[i]] / mol_mass;
+                    ibin = floor(iLambda/AT_lambda_Increment);
+
+
+                    f[i][0] += mass_frac*(AT_mol_f_all_H[imol][0]);
+                    f[i][1] += mass_frac*(AT_mol_f_all_H[imol][1]);
+                    f[i][2] += mass_frac*(AT_mol_f_all_H[imol][2]);
+
+                }
+
+            }
+
+        }
+
+        }
+
+
+    if(This_Step == AT_Update_Time_End)AT_Pressure_Compensation_Run = 0;
+
+  if (vflag_fdotr) virial_fdotr_compute();
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::compute_inner()
+{
+    error->all(FLERR,"Rrespa has not been included!");
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::compute_middle()
+{
+    error->all(FLERR,"Rrespa has not been included!");
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::compute_outer(int eflag, int vflag)
+{
+    error->all(FLERR,"Rrespa has not been included!");
+
+}
+
+/* ----------------------------------------------------------------------
+   allocate all arrays
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::allocate()
+{
+  allocated = 1;
+  int n = atom->ntypes;
+
+  memory->create(setflag,n+1,n+1,"pairLJHAT:setflag");
+  for (int i = 1; i <= n; i++)
+    for (int j = i; j <= n; j++)
+      setflag[i][j] = 0;
+
+  memory->create(cutsq,n+1,n+1,"pairLJHAT:cutsq");
+
+  memory->create(cut,n+1,n+1,"pairLJHAT:cut");
+  memory->create(epsilon,n+1,n+1,"pairLJHAT:epsilon");
+  memory->create(sigma,n+1,n+1,"pairLJHAT:sigma");
+  memory->create(lj1,n+1,n+1,"pairLJHAT:lj1");
+  memory->create(lj2,n+1,n+1,"pairLJHAT:lj2");
+  memory->create(lj3,n+1,n+1,"pairLJHAT:lj3");
+  memory->create(lj4,n+1,n+1,"pairLJHAT:lj4");
+  memory->create(offset,n+1,n+1,"pairLJHAT:offset");
+
+}
+
+/* ----------------------------------------------------------------------
+   global settings
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::settings(int narg, char **arg)
+{
+  if (narg != 3) error->all(FLERR,"Illegal pair_style command");
+
+  cut_global = force->numeric(FLERR,arg[0]);
+
+  // reset cutoffs that have been explicitly set
+  AllAtomistic = force->numeric(FLERR,arg[1]);
+
+  Load_File_Flag = force->numeric(FLERR,arg[2]);
+
+
+  if (allocated) {
+    int i,j;
+    for (i = 1; i <= atom->ntypes; i++)
+      for (j = i+1; j <= atom->ntypes; j++)
+        if (setflag[i][j]) cut[i][j] = cut_global;
+  }
+
+
+
+}
+
+/* ----------------------------------------------------------------------
+   set coeffs for one or more type pairs
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::coeff(int narg, char **arg)
+{
+
+
+  if (narg < 4 || narg > 5)
+    error->all(FLERR,"Incorrect args for pair coefficients");
+  if (!allocated) allocate();
+
+  int ilo,ihi,jlo,jhi;
+  force->bounds(arg[0],atom->ntypes,ilo,ihi);
+  force->bounds(arg[1],atom->ntypes,jlo,jhi);
+
+  double epsilon_one = force->numeric(FLERR,arg[2]);
+  double sigma_one = force->numeric(FLERR,arg[3]);
+
+  double cut_one = cut_global;
+  if (narg == 5) cut_one = force->numeric(FLERR,arg[4]);
+
+
+  int count = 0;
+  for (int i = ilo; i <= ihi; i++) {
+    for (int j = MAX(jlo,i); j <= jhi; j++) {
+      epsilon[i][j] = epsilon_one;
+      sigma[i][j] = sigma_one;
+      cut[i][j] = cut_one;
+      setflag[i][j] = 1;
+      count++;
+    }
+  }
+
+  if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
+}
+
+/* ----------------------------------------------------------------------
+   init specific to this pair style
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::init_style()
+{
+  // request regular or rRESPA neighbor lists
+
+
+    if(me == 0){
+        if (screen)fprintf(screen,"AT_H_AdResS_allocated flag = %d\n",H_AdResS_allocated);
+        if (logfile)fprintf(logfile,"AT_H_AdResS_allocated flag = %d\n",H_AdResS_allocated);
+    }
+
+    if(!H_AdResS_allocated)H_AdResS_Allocation();
+
+    int This_Step = update->ntimestep;
+    if((This_Step >= AT_Update_Time_End  || Load_File_Flag) && AT_Pressure_Comp_Flag != 0)Load_Compensation_Pressure();
+
+
+    int irequest;
+
+  if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) {
+    int respa = 0;
+    if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
+    if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
+
+    if (respa == 0) irequest = neighbor->request(this,instance_me);
+    else if (respa == 1) {
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 1;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respainner = 1;
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 3;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respaouter = 1;
+    } else {
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 1;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respainner = 1;
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 2;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respamiddle = 1;
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 3;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respaouter = 1;
+    }
+
+  } else {
+      irequest = neighbor->request(this,instance_me);
+  }
+  // set rRESPA cutoffs
+
+  if (strstr(update->integrate_style,"respa") &&
+      ((Respa *) update->integrate)->level_inner >= 0)
+    cut_respa = ((Respa *) update->integrate)->cutoff;
+  else cut_respa = NULL;
+}
+
+/* ----------------------------------------------------------------------
+   neighbor callback to inform pair style of neighbor list to use
+   regular or rRESPA
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::init_list(int id, NeighList *ptr)
+{
+  if (id == 0) list = ptr;
+  else if (id == 1) listinner = ptr;
+  else if (id == 2) listmiddle = ptr;
+  else if (id == 3) listouter = ptr;
+}
+
+/* ----------------------------------------------------------------------
+   init for one type pair i,j and corresponding j,i
+------------------------------------------------------------------------- */
+
+double PairLJCutHARSAT::init_one(int i, int j)
+{
+  if (setflag[i][j] == 0) {
+    epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
+                               sigma[i][i],sigma[j][j]);
+    sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
+    cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
+  }
+
+
+  lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
+  lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
+  lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
+  lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
+
+
+  if (offset_flag) {
+    double ratio = sigma[i][j] / cut[i][j];
+    offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
+  } else offset[i][j] = 0.0;
+
+  lj1[j][i] = lj1[i][j];
+  lj2[j][i] = lj2[i][j];
+  lj3[j][i] = lj3[i][j];
+  lj4[j][i] = lj4[i][j];
+  offset[j][i] = offset[i][j];
+
+  // check interior rRESPA cutoff
+
+  if (cut_respa && cut[i][j] < cut_respa[3])
+    error->all(FLERR,"Pair cutoff < Respa interior cutoff");
+
+  // compute I,J contribution to long-range tail correction
+  // count total # of atoms of type I and J via Allreduce
+
+  if (tail_flag) {
+    int *type = atom->type;
+    int nlocal = atom->nlocal;
+
+    double count[2],all[2];
+    count[0] = count[1] = 0.0;
+    for (int k = 0; k < nlocal; k++) {
+      if (type[k] == i) count[0] += 1.0;
+      if (type[k] == j) count[1] += 1.0;
+    }
+    MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
+
+    double sig2 = sigma[i][j]*sigma[i][j];
+    double sig6 = sig2*sig2*sig2;
+    double rc3 = cut[i][j]*cut[i][j]*cut[i][j];
+    double rc6 = rc3*rc3;
+    double rc9 = rc3*rc6;
+    etail_ij = 8.0*MY_PI*all[0]*all[1]*epsilon[i][j] *
+      sig6 * (sig6 - 3.0*rc6) / (9.0*rc9);
+    ptail_ij = 16.0*MY_PI*all[0]*all[1]*epsilon[i][j] *
+      sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9);
+  }
+
+
+  return cut[i][j];
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::write_restart(FILE *fp)
+{
+  write_restart_settings(fp);
+
+  int i,j;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      fwrite(&setflag[i][j],sizeof(int),1,fp);
+      if (setflag[i][j]) {
+        fwrite(&epsilon[i][j],sizeof(double),1,fp);
+        fwrite(&sigma[i][j],sizeof(double),1,fp);
+        fwrite(&cut[i][j],sizeof(double),1,fp);
+      }
+    }
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::read_restart(FILE *fp)
+{
+  read_restart_settings(fp);
+  allocate();
+
+  int i,j;
+  int me = comm->me;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
+      MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
+      if (setflag[i][j]) {
+        if (me == 0) {
+          fread(&epsilon[i][j],sizeof(double),1,fp);
+          fread(&sigma[i][j],sizeof(double),1,fp);
+          fread(&cut[i][j],sizeof(double),1,fp);
+        }
+        MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
+        MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
+        MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
+      }
+    }
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::write_restart_settings(FILE *fp)
+{
+  fwrite(&cut_global,sizeof(double),1,fp);
+  fwrite(&offset_flag,sizeof(int),1,fp);
+  fwrite(&mix_flag,sizeof(int),1,fp);
+  fwrite(&tail_flag,sizeof(int),1,fp);
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::read_restart_settings(FILE *fp)
+{
+  int me = comm->me;
+  if (me == 0) {
+    fread(&cut_global,sizeof(double),1,fp);
+    fread(&offset_flag,sizeof(int),1,fp);
+    fread(&mix_flag,sizeof(int),1,fp);
+    fread(&tail_flag,sizeof(int),1,fp);
+  }
+  MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
+  MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
+  MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
+  MPI_Bcast(&tail_flag,1,MPI_INT,0,world);
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes to data file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::write_data(FILE *fp)
+{
+  for (int i = 1; i <= atom->ntypes; i++)
+    fprintf(fp,"%d %g %g\n",i,epsilon[i][i],sigma[i][i]);
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes all pairs to data file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSAT::write_data_all(FILE *fp)
+{
+  for (int i = 1; i <= atom->ntypes; i++)
+    for (int j = i; j <= atom->ntypes; j++)
+      fprintf(fp,"%d %d %g %g %g\n",i,j,epsilon[i][j],sigma[i][j],cut[i][j]);
+}
+
+/* ---------------------------------------------------------------------- */
+
+double PairLJCutHARSAT::single(int i, int j, int itype, int jtype, double rsq,
+                         double factor_coul, double factor_lj,
+                         double &fforce)
+{
+  double r2inv,r6inv,forcelj,philj;
+
+  r2inv = 1.0/rsq;
+  r6inv = r2inv*r2inv*r2inv;
+  forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+  fforce = factor_lj*forcelj*r2inv;
+
+  philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+    offset[itype][jtype];
+  return factor_lj*philj;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void *PairLJCutHARSAT::extract(const char *str, int &dim)
+{
+  dim = 2;
+  if (strcmp(str,"epsilon") == 0) return (void *) epsilon;
+  if (strcmp(str,"sigma") == 0) return (void *) sigma;
+  return NULL;
+}
+
+
+int PairLJCutHARSAT::molecules_in_group(tagint &idlo, tagint &idhi)
+{
+  int i;
+
+  memory->destroy(AT_molmap_H);
+  AT_molmap_H = NULL;
+
+  // find lo/hi molecule ID for any atom in group
+  // warn if atom in group has ID = 0
+
+  tagint *molecule = atom->molecule;
+  int *mask = atom->mask;
+  int nlocal = atom->nlocal;
+
+  tagint lo = BIG;
+  tagint hi = -BIG;
+  int flag = 0;
+  for (i = 0; i < nlocal; i++)
+  {
+//    if (mask[i] & groupbit) {
+      if (mask[i]) {
+      if (molecule[i] == 0) flag = 1;
+      lo = MIN(lo,molecule[i]);
+      hi = MAX(hi,molecule[i]);
+    }
+  }
+
+  int flagall;
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,"Atom with molecule ID = 0 included in "
+                   "compute molecule group");
+
+  MPI_Allreduce(&lo,&idlo,1,MPI_LMP_TAGINT,MPI_MIN,world);
+  MPI_Allreduce(&hi,&idhi,1,MPI_LMP_TAGINT,MPI_MAX,world);
+  if (idlo == BIG) return 0;
+
+  // molmap = vector of length nlen
+  // set to 1 for IDs that appear in group across all procs, else 0
+
+  tagint nlen_tag = idhi-idlo+1;
+  if (nlen_tag > MAXSMALLINT)
+    error->all(FLERR,"Too many molecules for compute");
+  int nlen = (int) nlen_tag;
+
+  memory->create(AT_molmap_H,nlen,"pair:molmap_H");
+  for (i = 0; i < nlen; i++) AT_molmap_H[i] = 0;
+
+  for (i = 0; i < nlocal; i++)
+   // if (mask[i] & groupbit)
+       if (mask[i])
+      AT_molmap_H[molecule[i]-idlo] = 1;
+
+  int *AT_molmapall;
+  memory->create(AT_molmapall,nlen,"pair:AT_molmapall");
+  MPI_Allreduce(AT_molmap_H,AT_molmapall,nlen,MPI_INT,MPI_MAX,world);
+
+  // nmolecules = # of non-zero IDs in molmap
+  // molmap[i] = index of molecule, skipping molecules not in group with -1
+
+  int nmolecules = 0;
+  for (i = 0; i < nlen; i++)
+    if (AT_molmapall[i]) AT_molmap_H[i] = nmolecules++;
+    else AT_molmap_H[i] = -1;
+  memory->destroy(AT_molmapall);
+
+  // warn if any molecule has some atoms in group and some not in group
+
+  flag = 0;
+  for (i = 0; i < nlocal; i++) {
+//    if (mask[i] & groupbit) continue;
+      if (mask[i]) continue;
+    if (molecule[i] < idlo || molecule[i] > idhi) continue;
+    if (AT_molmap_H[molecule[i]-idlo] >= 0) flag = 1;
+  }
+
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,
+                   "One or more compute molecules has atoms not in group");
+
+  // if molmap simply stores 1 to Nmolecules, then free it
+
+  if (idlo == 1 && idhi == nmolecules && nlen == nmolecules) {
+    memory->destroy(AT_molmap_H);
+    AT_molmap_H = NULL;
+  }
+  return nmolecules;
+}
+
+
+void PairLJCutHARSAT::AT_Print_Compensation_Energy(){
+
+        FILE *fp1;
+        fp1 = fopen("Mean_Comp_Energy_AT.txt","w");
+        if (fp1 == NULL) {
+            char str[128];
+            sprintf(str,"Cannot open Mean_Comp_Energy_AT.txt file %s","Mean_Comp_Energy_AT.txt");
+            error->one(FLERR,str);
+        }
+
+        for(int i = 0;i < AT_Bin_Num; i++){
+            fprintf(fp1,"%d",i+1);
+                for(int j = 0; j < atom->nmoltypesH; j++){
+                    fprintf(fp1,"\t%.10f",Mean_Comp_Energy_H[i][j]);
+                }
+                fprintf(fp1,"\n");
+        }
+        fclose(fp1);
+}
+
+
+
+void PairLJCutHARSAT::AT_Update_Compensation_Energy(){
+
+    MPI_Allreduce(&Comp_Energy_H[0][0],&Comp_Energy_all_H[0][0],AT_Bin_Num*atom->nmoltypesH,MPI_DOUBLE,MPI_SUM,world);
+    MPI_Allreduce(&Comp_Energy_Num_H[0][0],&Comp_Energy_Num_all_H[0][0],AT_Bin_Num*atom->nmoltypesH,MPI_INT,MPI_SUM,world);
+
+    for(int j = 0;j < atom->nmoltypesH; j++){
+        for(int i = 0;i < AT_Bin_Num; i++){
+            Mean_Energy_H[i][j] = Comp_Energy_all_H[i][j] / Comp_Energy_Num_all_H[i][j];
+            Mean_Comp_Energy_H[i][j] = (Comp_Counter_H * Mean_Comp_Energy_H[i][j] + Mean_Energy_H[i][j]) / (Comp_Counter_H + 1);
+            Int_Mean_Energy_H[i][j]=0;
+        }
+    }
+
+    Comp_Counter_H++;
+
+    for(int j = 0;j < atom->nmoltypesH; j++){
+        for(int i = 0;i < AT_Bin_Num; i++){
+            Comp_Energy_Num_H[i][j] = 0;
+            Comp_Energy_Num_all_H[i][j] = 0;
+            Comp_Energy_H[i][j] = 0;
+            Comp_Energy_all_H[i][j] =0;
+        }
+
+    }
+    if (me == 0)AT_Print_Compensation_Energy();
+
+
+
+}
+
+
+void PairLJCutHARSAT::Load_Compensation_Pressure(){
+
+    if(me == 0){
+        FILE *fp1;
+        char str[128];
+
+        fp1 = fopen("Mean_Comp_Energy_AT.txt","r");
+        if (fp1 == NULL) {
+            sprintf(str,"Cannot open fix Mean_Comp_Energy_AT.txt file %s","Mean_Comp_Energy_AT.txt");
+            error->one(FLERR,str);
+        }
+
+        int i1;
+
+        while (!feof(fp1)){
+                fscanf (fp1,"%d",&i1);
+                for(int j=0;j<atom->nmoltypesH;j++)fscanf (fp1,"\t%f",&Mean_Comp_Energy_H[i1-1][j]);
+                fscanf (fp1,"\n");
+                if(i1 > AT_Bin_Num){
+                    sprintf(str,"Pressure bin number mismatches %d != %d",AT_Bin_Num,i1);
+                    error->one(FLERR,str);
+                }
+
+        }
+
+        fclose(fp1);
+
+        if(me==0){
+            if(screen)fprintf(screen,"AT_Pressure componsation forces distributed successfully!\n");
+            if(logfile)fprintf(logfile,"AT_Pressure componsation forces distributed successfully!\n");
+        }
+
+    }
+
+    MPI_Bcast(Mean_Comp_Energy_H,AT_Bin_Num,MPI_DOUBLE,0,world);
+
+
+}
+
+void PairLJCutHARSAT::H_AdResS_Allocation(){
+
+    for (int i = 0; i < modify->nfix; i++){
+      if (strcmp(modify->fix[i]->style,"lambdah/calc") == 0){
+             lambda_H_fix = (FixLambdaHCalc *) modify->fix[i];
+             AT_lambda_Increment = lambda_H_fix->Pressure_lambda_Increment;
+             AT_Bin_Num = lambda_H_fix->Pressure_Bin_Num;
+             AT_Update_Frequency = lambda_H_fix->Pressure_Update_Frequency;
+             AT_Update_Time_Begin = lambda_H_fix->Pressure_Update_Time_Begin;
+             AT_Update_Time_End = lambda_H_fix->Pressure_Update_Time_End;
+
+             AT_Pressure_Comp_Flag = lambda_H_fix->Pressure_Comp_Flag;
+             AT_center_box = lambda_H_fix->center_box;
+             AT_Hybrid_Style = lambda_H_fix->Hybrid_Style;
+
+
+      }
+    }
+
+    if(me == 0){
+        if (screen){
+            fprintf(screen,"AT_lambda_Increment= %f\n",AT_lambda_Increment);
+            fprintf(screen,"AT_Bin_Num= %d\n",AT_Bin_Num);
+            fprintf(screen,"AT_Update_Frequency= %d\n",AT_Update_Frequency);
+            fprintf(screen,"AT_Update_Time_Begin= %d\n",AT_Update_Time_Begin);
+            fprintf(screen,"AT_Update_Time_End= %d\n",AT_Update_Time_End);
+            fprintf(screen,"AT_Pressure_Comp_Flag= %d\n",AT_Pressure_Comp_Flag);
+        }
+
+        if (logfile){
+            fprintf(logfile,"AT_lambda_Increment= %f\n",AT_lambda_Increment);
+            fprintf(logfile,"AT_Bin_Num= %d\n",AT_Bin_Num);
+            fprintf(logfile,"AT_Update_Frequency= %d\n",AT_Update_Frequency);
+            fprintf(logfile,"AT_Update_Time_Begin= %d\n",AT_Update_Time_Begin);
+            fprintf(logfile,"AT_Update_Time_End= %d\n",AT_Update_Time_End);
+            fprintf(logfile,"AT_Pressure_Comp_Flag= %d\n",AT_Pressure_Comp_Flag);
+        }
+    }
+
+    memory->create(Comp_Energy_Num_H,AT_Bin_Num,atom->nmoltypesH,"pairLJHAT:Comp_Energy_Num_H");
+    memory->create(Comp_Energy_Num_all_H,AT_Bin_Num,atom->nmoltypesH,"pairLJHAT:Comp_Energy_Num_all_H");
+
+    memory->create(Int_Mean_Energy_H,AT_Bin_Num,atom->nmoltypesH,"pairLJHAT:Int_Mean_Energy_H");
+    memory->create(Comp_Energy_H,AT_Bin_Num,atom->nmoltypesH,"pairLJHAT:Comp_Energy_H");
+    memory->create(Comp_Energy_all_H,AT_Bin_Num,atom->nmoltypesH,"pairLJHAT:Comp_Energy_all_H");
+    memory->create(Mean_Comp_Energy_H,AT_Bin_Num,atom->nmoltypesH,"pairLJHAT:Mean_Comp_Energy_H");
+    memory->create(Mean_Energy_H,AT_Bin_Num,atom->nmoltypesH,"pairLJHAT:Mean_Energy_H");
+
+    for(int j=0;j<atom->nmoltypesH;j++){
+        for(int i = 0;i < AT_Bin_Num; i++){
+            Int_Mean_Energy_H[i][j]=0;
+            Comp_Energy_H[i][j]=0;
+            Comp_Energy_all_H[i][j]=0;
+            Mean_Comp_Energy_H[i][j]=0;
+            Comp_Energy_Num_H[i][j] = 0;
+            Comp_Energy_Num_all_H[i][j] = 0;
+        }
+
+    }
+
+    H_AdResS_allocated = 1;
+}
+
diff --git a/src/USER-HADRESS/pair_lj_cut_hars_at.h b/src/USER-HADRESS/pair_lj_cut_hars_at.h
new file mode 100644
index 000000000..04f41cfc9
--- /dev/null
+++ b/src/USER-HADRESS/pair_lj_cut_hars_at.h
@@ -0,0 +1,119 @@
+/* -*- 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 PAIR_CLASS
+
+PairStyle(lj/cut/hars/at,PairLJCutHARSAT)
+
+#else
+
+#ifndef LMP_PAIR_LJ_CUT_HARS_AT_H
+#define LMP_PAIR_LJ_CUT_HARS_AT_H
+
+#include "pair.h"
+
+namespace LAMMPS_NS {
+
+class PairLJCutHARSAT : public Pair {
+ public:
+  PairLJCutHARSAT(class LAMMPS *);
+  virtual ~PairLJCutHARSAT();
+  virtual void compute(int, int);
+  void settings(int, char **);
+  void coeff(int, char **);
+  void init_style();
+  void init_list(int, class NeighList *);
+  double init_one(int, int);
+  void write_restart(FILE *);
+  void read_restart(FILE *);
+  void write_restart_settings(FILE *);
+  void read_restart_settings(FILE *);
+  void write_data(FILE *);
+  void write_data_all(FILE *);
+  double single(int, int, int, int, double, double, double, double &);
+  void *extract(const char *, int &);
+
+  void compute_inner();
+  void compute_middle();
+  void compute_outer(int, int);
+
+  void AT_Print_Compensation_Energy();
+  void AT_Update_Compensation_Energy();
+
+ protected:
+  double cut_global;
+  double **cut;
+  double **epsilon,**sigma;
+  double **lj1,**lj2,**lj3,**lj4,**offset;
+  double *cut_respa;
+  class FixLambdaHCalc *lambda_H_fix;
+
+  int AllAtomistic;
+
+  virtual void allocate();
+
+//private:
+  int me;
+
+  int H_AdResS_allocated;
+
+  int **Comp_Energy_Num_H,**Comp_Energy_Num_all_H, Comp_Counter_H;
+
+  double AT_lambda_Increment;
+  int AT_Bin_Num, AT_Update_Frequency, AT_Update_Time_End, AT_Update_Time_Begin;
+  int AT_Pressure_Compensation_Run;
+  int AT_Pressure_Comp_Flag;
+
+  double *AT_center_box,AT_x0lo;
+  int AT_Hybrid_Style;
+  double **Int_Mean_Energy_H, **Comp_Energy_H, **Comp_Energy_all_H, **Mean_Energy_H, **Mean_Comp_Energy_H;
+
+   int nmolecules;
+   tagint idlo,idhi;
+
+   double *AT_massproc_H,*AT_masstotal_H;
+
+   double **AT_mol_f_H, **AT_mol_f_all_H;
+
+   int *AT_molmap_H;                 // convert molecule ID to local index
+   int Load_File_Flag;
+
+   int molecules_in_group(tagint &, tagint &);
+   void Load_Compensation_Pressure();
+   void H_AdResS_Allocation();
+
+};
+
+}
+
+#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: Incorrect args for pair coefficients
+
+Self-explanatory.  Check the input script or data file.
+
+E: Pair cutoff < Respa interior cutoff
+
+One or more pairwise cutoffs are too short to use with the specified
+rRESPA cutoffs.
+
+*/
diff --git a/src/USER-HADRESS/pair_lj_cut_hars_cg.cpp b/src/USER-HADRESS/pair_lj_cut_hars_cg.cpp
new file mode 100644
index 000000000..86d61d447
--- /dev/null
+++ b/src/USER-HADRESS/pair_lj_cut_hars_cg.cpp
@@ -0,0 +1,1120 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain rights in this software.  This software is distributed under
+   the GNU General Public License.
+
+   See the README file in the top-level LAMMPS directory.
+------------------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------
+   Contributing author: Paul Crozier (SNL)
+------------------------------------------------------------------------- */
+#include "mpi.h"
+#include "math.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "pair_lj_cut_hars_cg.h"
+#include "atom.h"
+#include "atom_vec.h"
+#include "comm.h"
+#include "force.h"
+#include "neighbor.h"
+#include "neigh_list.h"
+#include "neigh_request.h"
+#include "update.h"
+#include "integrate.h"
+#include "respa.h"
+#include "math_const.h"
+#include "memory.h"
+#include "error.h"
+#include "domain.h"
+#include "iostream"
+#include "fix.h"
+#include "fix_lambdah_calc.h"
+#include "modify.h"
+
+using namespace LAMMPS_NS;
+using namespace MathConst;
+
+#define BIG MAXTAGINT
+
+/* ---------------------------------------------------------------------- */
+
+PairLJCutHARSCG::PairLJCutHARSCG(LAMMPS *lmp) : Pair(lmp)
+{
+  respa_enable = 1;
+  writedata = 1;
+
+  massproc_H = NULL;
+  masstotal_H = NULL;
+  molmap_H = NULL;
+  mol_f_H = NULL;
+  mol_f_all_H = NULL;
+  Comp_Energy_Num_H = NULL;
+  Comp_Energy_Num_all_H = NULL;
+
+  Int_Mean_Energy_H = NULL;
+  Mean_Energy_H = NULL;
+  Comp_Energy_H = NULL;
+  Comp_Energy_all_H = NULL;
+  Mean_Comp_Energy_H = NULL;
+  CG_Mean_grad_Comp_Density_Conv_H = NULL;
+
+  molmap_H = NULL;
+  nmolecules = molecules_in_group(idlo,idhi);
+
+  H_AdResS_allocated = 0;
+
+  CG_Pressure_Compensation_Run = 0;
+  Density_Compensation_Run = 0;
+  Comp_Counter_H = 0;
+  CG_Density_Comp_Flag = 0;
+  CG_Pressure_Comp_Flag = 0;
+
+
+  memory->create(massproc_H,nmolecules,"pair:massproc_H");
+  memory->create(masstotal_H,nmolecules,"pair:masstotal_H");
+  memory->create(mol_f_H,nmolecules,3,"pair:mol_f_H");
+  memory->create(mol_f_all_H,nmolecules,3,"pair:mol_f_all_H");
+
+
+  // compute masstotal for each molecule
+
+  MPI_Comm_rank(world, &me);
+  int *mask = atom->mask;
+  tagint *molecule = atom->molecule;
+  int *type = atom->type;
+  double *mass = atom->mass;
+  double *rmass = atom->rmass;
+  int nlocal = atom->nlocal;
+  tagint imol;
+  double massone;
+
+  for (int i = 0; i < nmolecules; i++) massproc_H[i] = 0.0;
+
+  for (int i = 0; i < nlocal; i++)
+  {
+//    if (mask[i] & groupbit) {
+    if (mask[i]) {
+      if (rmass) massone = rmass[i];
+      else massone = mass[type[i]];
+      imol = molecule[i];
+      if (molmap_H) imol = molmap_H[imol-idlo];
+      else imol--;
+      massproc_H[imol] += massone;
+
+    }
+  }
+
+  MPI_Allreduce(massproc_H,masstotal_H,nmolecules,MPI_DOUBLE,MPI_SUM,world);
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+PairLJCutHARSCG::~PairLJCutHARSCG()
+{
+
+
+  if (allocated) {
+
+      memory->destroy(setflag);
+      memory->destroy(cutsq);
+
+      memory->destroy(cut);
+      memory->destroy(epsilon);
+      memory->destroy(sigma);
+      memory->destroy(lj1);
+      memory->destroy(lj2);
+      memory->destroy(lj3);
+      memory->destroy(lj4);
+      memory->destroy(offset);
+      memory->destroy(massproc_H);
+      memory->destroy(masstotal_H);
+      memory->destroy(molmap_H);
+      memory->destroy(mol_f_H);
+      memory->destroy(mol_f_all_H);
+      memory->destroy(Comp_Energy_Num_H);
+      memory->destroy(Comp_Energy_Num_all_H);
+      memory->destroy(Int_Mean_Energy_H);
+      memory->destroy(Mean_Energy_H);
+      memory->destroy(Comp_Energy_H);
+      memory->destroy(Comp_Energy_all_H);
+      memory->destroy(Mean_Comp_Energy_H);
+      //    memory->destroy(CG_Mean_grad_Comp_Density_Conv_H);
+
+//    delete lambda_H_fix;
+}
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::compute(int eflag, int vflag)
+{
+  int i,j,ii,jj,inum,jnum,itype,jtype;
+  double xtmp,ytmp,ztmp,delx,dely,delz,evdwl,fpair;
+  double rsq,r2inv,r6inv,forcelj, factor_lj,Vij;
+  int *ilist,*jlist,*numneigh,**firstneigh;
+  int imoltype,jmoltype;
+
+  evdwl = 0.0;
+  if (eflag || vflag) ev_setup(eflag,vflag);
+  else evflag = vflag_fdotr = 0;
+
+  double **x = atom->x;
+  double **f = atom->f;
+  double *lambdaH = atom->lambdaH;
+  double **gradlambdaH = atom->gradlambdaH;
+  double **comH = atom->comH;
+  int *replambdaH = atom->replambdaH;
+  tagint *molecule = atom->molecule;
+  double *mass = atom->mass;
+  int *moltypeH = atom->moltypeH;
+  int *type = atom->type;
+  int nlocal = atom->nlocal;
+  double *special_lj = force->special_lj;
+  int newton_pair = force->newton_pair;
+
+  int ibin, jbin;
+
+  inum = list->inum;
+  ilist = list->ilist;
+  numneigh = list->numneigh;
+  firstneigh = list->firstneigh;
+
+  double iLambda, jLambda, ijLambda;
+  int imol,jmol;
+
+
+
+  int This_Step = update->ntimestep;
+  if(This_Step >= CG_Update_Time_Begin && This_Step <= CG_Update_Time_End && CG_Pressure_Comp_Flag != 0){
+      CG_Pressure_Compensation_Run = 1;
+      if(me==0 && This_Step == CG_Update_Time_Begin){
+          if(screen)fprintf(screen,"\nStart of constant-pressure route\n");
+          if(logfile)fprintf(logfile,"\nStart of constant-pressure route\n");
+      }
+  }
+
+
+  if(update->ntimestep<CG_Restart_Time_Step+1)return;
+
+
+  for (int i = 0; i < nmolecules; i++) {
+      mol_f_H[i][0] = mol_f_H[i][1] = mol_f_H[i][2] = 0;
+      mol_f_all_H[i][0] = mol_f_all_H[i][1] = mol_f_all_H[i][2] = 0;
+  }
+
+
+  Density_Compensation_Run = lambda_H_fix->Density_Compensation_Run;
+
+  if(Density_Compensation_Run){
+      CG_Mean_grad_Comp_Density_Conv_H = lambda_H_fix->Mean_grad_Comp_Density_Conv_H;
+  }
+
+  for (ii = 0; ii < inum; ii++) {
+
+    i = ilist[ii];
+    if(replambdaH[i] == 0)continue;
+
+    xtmp = comH[i][0];
+    ytmp = comH[i][1];
+    ztmp = comH[i][2];
+
+//    itype = moltypeH[i];
+    itype = type[i];
+    jlist = firstneigh[i];
+    jnum = numneigh[i];
+    imoltype = itype - 1;
+
+    iLambda = 1 - lambdaH[i];
+
+    for (jj = 0; jj < jnum; jj++) {
+
+      j = jlist[jj];
+      factor_lj = special_lj[sbmask(j)];
+      j &= NEIGHMASK;
+      jLambda = 1 - lambdaH[j];
+
+      if(replambdaH[j] == 0)continue;
+
+      if((iLambda==0 && jLambda==0) && AllCoarseGrained != 1)continue;
+
+      delx = xtmp - comH[j][0];
+      dely = ytmp - comH[j][1];
+      delz = ztmp - comH[j][2];
+
+      domain->minimum_image(delx,dely,delz);
+
+      rsq = delx*delx + dely*dely + delz*delz;
+      jtype = type[j];
+      //jtype = moltypeH[j];
+      jmoltype = jtype - 1;
+
+//      if (rsq < cutsq[itype][jtype] && lj1[itype][jtype] != 0) {
+      if (rsq < cutsq[itype][jtype]) {
+
+
+          imol = molecule[i];
+          jmol = molecule[j];
+          if (molmap_H) {
+              imol = molmap_H[imol-idlo];
+              jmol = molmap_H[jmol-idlo];
+          }
+          else {
+              imol--;
+              jmol--;
+          }
+
+
+         if(((iLambda==1 && jLambda==1) || AllCoarseGrained)){
+
+                r2inv = 1.0/rsq;
+                r6inv = r2inv*r2inv*r2inv;
+                forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+
+                fpair = factor_lj*forcelj*r2inv;
+                mol_f_H[imol][0] += delx*fpair;
+                mol_f_H[imol][1] += dely*fpair;
+                mol_f_H[imol][2] += delz*fpair;
+
+                if (newton_pair || j < nlocal) {
+                  mol_f_H[jmol][0] -= delx*fpair;
+                  mol_f_H[jmol][1] -= dely*fpair;
+                  mol_f_H[jmol][2] -= delz*fpair;
+                }
+
+                if (eflag) {
+                    evdwl = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+                            offset[itype][jtype];
+                  evdwl *= factor_lj;
+                }
+
+                if (evflag) ev_tally(i,j,nlocal,newton_pair,
+                                     evdwl,0.0,fpair,delx,dely,delz);
+
+            }
+
+            else if(iLambda != 0 || jLambda != 0){
+
+                ijLambda = 0.5 * (iLambda + jLambda);
+                r2inv = 1.0/rsq;
+                r6inv = r2inv*r2inv*r2inv;
+                forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+                fpair = factor_lj*(forcelj*ijLambda)*r2inv;
+
+                Vij = 0.5*(r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+                        offset[itype][jtype]);
+
+
+                ibin = floor(iLambda/CG_lambda_Increment);
+                if(ibin==CG_Bin_Num)ibin = CG_Bin_Num - 1;
+
+                if(CG_Pressure_Compensation_Run != 0 && iLambda != 0 && iLambda != 1)Comp_Energy_H[ibin][imoltype] += Vij;
+
+                mol_f_H[imol][0] += delx*fpair + Vij*gradlambdaH[i][0];
+                mol_f_H[imol][1] += dely*fpair + Vij*gradlambdaH[i][1];
+                mol_f_H[imol][2] += delz*fpair + Vij*gradlambdaH[i][2];
+
+                if (newton_pair || j < nlocal) {
+
+                  jbin = floor(jLambda/CG_lambda_Increment);
+                  if(jbin==CG_Bin_Num)jbin = CG_Bin_Num - 1;
+                  if(CG_Pressure_Compensation_Run != 0 && jLambda != 0 && jLambda != 1)Comp_Energy_H[jbin][jmoltype] += Vij;
+
+                  mol_f_H[jmol][0] -= delx*fpair - Vij*gradlambdaH[j][0];
+                  mol_f_H[jmol][1] -= dely*fpair - Vij*gradlambdaH[j][1];
+                  mol_f_H[jmol][2] -= delz*fpair - Vij*gradlambdaH[j][2];
+
+                }
+
+                if (eflag) {
+                    evdwl = ijLambda*Vij*2.0;
+                    evdwl *= factor_lj;
+                }
+
+                if (evflag) ev_tally(i,j,nlocal,newton_pair,
+                                 evdwl,0.0,fpair,delx,dely,delz);
+
+            }
+        }
+
+      }
+    }
+
+
+  MPI_Allreduce(&mol_f_H[0][0],&mol_f_all_H[0][0],3*nmolecules,MPI_DOUBLE,MPI_SUM,world);
+
+  if(CG_Pressure_Compensation_Run != 0 && CG_Pressure_Comp_Flag != 0){
+      for (int i = 0; i < nlocal; i++){
+          iLambda = 1 - lambdaH[i];
+          if(replambdaH[i] != 0 && lambdaH[i] != 0 && lambdaH[i] != 1){
+              ibin = floor(iLambda/CG_lambda_Increment);
+              if(ibin==CG_Bin_Num)ibin = CG_Bin_Num - 1;
+              itype = moltypeH[i] - 1;
+              Comp_Energy_Num_H[ibin][itype]++;
+
+          }
+      }
+
+      if(This_Step % CG_Update_Frequency == 0)CG_Update_Compensation_Energy();
+  }
+
+
+  double mol_mass,mass_frac;
+  double Grad_Density,r;
+  if(AllCoarseGrained != 1 && (CG_Density_Comp_Flag != 0 || CG_Pressure_Comp_Flag != 0)){
+
+      for (int i = 0; i < nlocal; i++){
+            imol = molecule[i];
+            if (molmap_H)imol = molmap_H[imol-idlo];
+            else imol--;
+            mol_mass = masstotal_H[imol];
+            mass_frac = mass[type[i]] / mol_mass;
+            iLambda = 1 - lambdaH[i];
+
+            if(iLambda != 0 && iLambda != 1){
+
+                ibin = floor(iLambda/CG_lambda_Increment);
+                itype = moltypeH[i] - 1;
+
+                f[i][0] += mass_frac*(mol_f_all_H[imol][0]-gradlambdaH[i][0]*Mean_Comp_Energy_H[ibin][itype]);
+                f[i][1] += mass_frac*(mol_f_all_H[imol][1]-gradlambdaH[i][1]*Mean_Comp_Energy_H[ibin][itype]);
+                f[i][2] += mass_frac*(mol_f_all_H[imol][2]-gradlambdaH[i][2]*Mean_Comp_Energy_H[ibin][itype]);
+
+                if (evflag) ev_tally(i,i,nlocal,newton_pair,
+                                     -0.5*Int_Mean_Energy_H[ibin][itype],0.0,0.0,0.0,0.0,0.0);
+
+
+                if(CG_Density_Comp_Flag != 0){
+
+                    if(CG_Hybrid_Style == 0){
+                        ibin = floor((comH[i][0]-CG_x0lo)/CG_Density_Bin_Size);
+                        f[i][0] += mass_frac*(-1.0*CG_Mean_grad_Comp_Density_Conv_H[ibin][itype]);
+                    }
+                    else if(CG_Hybrid_Style == 1){
+                        delx = comH[i][0] - CG_center_box[0];
+                        dely = comH[i][1] - CG_center_box[1];
+                        delz = comH[i][2] - CG_center_box[2];
+                        r = sqrt(delx*delx + dely*dely + delz*delz);
+                        ibin = floor(r/CG_Density_Bin_Size);
+
+                        Grad_Density = CG_Mean_grad_Comp_Density_Conv_H[ibin][itype] / r;
+                        f[i][0] += -mass_frac * Grad_Density * delx;
+                        f[i][1] += -mass_frac * Grad_Density * dely;
+                        f[i][2] += -mass_frac * Grad_Density * delz;
+                    }
+                    else if(CG_Hybrid_Style == 2){
+                        delx = comH[i][0] - CG_center_box[0];
+                        dely = comH[i][1] - CG_center_box[1];
+                        r = sqrt(delx*delx + dely*dely);
+                        ibin = floor(r/CG_Density_Bin_Size);
+
+                        Grad_Density = CG_Mean_grad_Comp_Density_Conv_H[ibin][itype] / r;
+                        f[i][0] += -mass_frac * Grad_Density * delx;
+                        f[i][1] += -mass_frac * Grad_Density * dely;
+                    }
+
+                }
+            }
+            else{
+                f[i][0] += mass_frac*mol_f_all_H[imol][0];
+                f[i][1] += mass_frac*mol_f_all_H[imol][1];
+                f[i][2] += mass_frac*mol_f_all_H[imol][2];
+            }
+
+     }
+
+  }
+  else{
+
+      for (int i = 0; i < nlocal; i++){
+            imol = molecule[i];
+            if (molmap_H)imol = molmap_H[imol-idlo];
+            else imol--;
+            mol_mass = masstotal_H[imol];
+            mass_frac = mass[type[i]] / mol_mass;
+
+            f[i][0] += mass_frac*mol_f_all_H[imol][0];
+            f[i][1] += mass_frac*mol_f_all_H[imol][1];
+            f[i][2] += mass_frac*mol_f_all_H[imol][2];
+      }
+
+  }
+
+
+
+  if(This_Step == CG_Update_Time_End){
+      CG_Pressure_Compensation_Run = 0;
+      if(me == 0){
+          if(screen)fprintf(screen,"\nEnd of constant-pressure route\n");
+          if(logfile)fprintf(logfile,"\nEnd of constant-pressure route\n");
+
+      }
+  }
+
+
+  if (vflag_fdotr) virial_fdotr_compute();
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::compute_inner()
+{
+
+    error->all(FLERR,"Rrespa has not been included!");
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::compute_middle()
+{
+    error->all(FLERR,"Rrespa has not been included!");
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::compute_outer(int eflag, int vflag)
+{
+    error->all(FLERR,"Rrespa has not been included!");
+}
+
+/* ----------------------------------------------------------------------
+   allocate all arrays
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::allocate()
+{
+
+  allocated = 1;
+  int n = atom->ntypes;
+
+  memory->create(setflag,n+1,n+1,"pairLJHCG:setflag");
+  for (int i = 1; i <= n; i++)
+    for (int j = i; j <= n; j++)
+      setflag[i][j] = 0;
+
+  memory->create(cutsq,n+1,n+1,"pairLJHCG:cutsq");
+  memory->create(cut,n+1,n+1,"pairLJHCG:cut");
+  memory->create(epsilon,n+1,n+1,"pairLJHCG:epsilon");
+  memory->create(sigma,n+1,n+1,"pairLJHCG:sigma");
+  memory->create(lj1,n+1,n+1,"pairLJHCG:lj1");
+  memory->create(lj2,n+1,n+1,"pairLJHCG:lj2");
+  memory->create(lj3,n+1,n+1,"pairLJHCG:lj3");
+  memory->create(lj4,n+1,n+1,"pairLJHCG:lj4");
+  memory->create(offset,n+1,n+1,"pairLJHCG:offset");
+
+
+
+}
+
+/* ----------------------------------------------------------------------
+   global settings
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::settings(int narg, char **arg)
+{
+  if (narg != 3) error->all(FLERR,"Illegal pair_style command");
+
+  cut_global = force->numeric(FLERR,arg[0]);
+
+  AllCoarseGrained  = force->numeric(FLERR,arg[1]);
+
+  Load_File_Flag = force->numeric(FLERR,arg[2]);
+  // reset cutoffs that have been explicitly set
+
+  if (allocated) {
+    int i,j;
+    for (i = 1; i <= atom->ntypes; i++)
+      for (j = i+1; j <= atom->ntypes; j++)
+        if (setflag[i][j]) cut[i][j] = cut_global;
+  }
+
+}
+
+/* ----------------------------------------------------------------------
+   set coeffs for one or more type pairs
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::coeff(int narg, char **arg)
+{
+
+  if (narg < 4 || narg > 5)
+    error->all(FLERR,"Incorrect args for pair coefficients");
+  if (!allocated) allocate();
+
+  int ilo,ihi,jlo,jhi;
+
+  force->bounds(arg[0],atom->ntypes,ilo,ihi);
+  force->bounds(arg[1],atom->ntypes,jlo,jhi);
+
+
+
+  double epsilon_one = force->numeric(FLERR,arg[2]);
+  double sigma_one = force->numeric(FLERR,arg[3]);
+
+  double cut_one = cut_global;
+  if (narg == 5) cut_one = force->numeric(FLERR,arg[4]);
+
+  int count = 0;
+  for (int i = ilo; i <= ihi; i++) {
+    for (int j = MAX(jlo,i); j <= jhi; j++) {
+      epsilon[i][j] = epsilon_one;
+      sigma[i][j] = sigma_one;
+      cut[i][j] = cut_one;
+      setflag[i][j] = 1;
+      count++;
+
+    }
+  }
+
+  if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients");
+}
+
+/* ----------------------------------------------------------------------
+   init specific to this pair style
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::init_style()
+{
+  // request regular or rRESPA neighbor lists
+    if(me == 0){
+        if (screen)fprintf(screen,"CG_H_AdResS_allocated flag = %d\n",H_AdResS_allocated);
+        if (logfile)fprintf(logfile,"CG_H_AdResS_allocated flag = %d\n",H_AdResS_allocated);
+    }
+
+    if(!H_AdResS_allocated)H_AdResS_Allocation();
+
+
+    int This_Step = update->ntimestep;
+    CG_Restart_Time_Step = This_Step;
+
+    if((This_Step >= CG_Update_Time_End || Load_File_Flag)  && CG_Pressure_Comp_Flag != 0)Load_Compensation_Pressure();
+
+  int irequest;
+
+  if (update->whichflag == 1 && strstr(update->integrate_style,"respa")) {
+    int respa = 0;
+    if (((Respa *) update->integrate)->level_inner >= 0) respa = 1;
+    if (((Respa *) update->integrate)->level_middle >= 0) respa = 2;
+
+    if (respa == 0)irequest = neighbor->request(this,instance_me);
+    else if (respa == 1) {
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 1;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respainner = 1;
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 3;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respaouter = 1;
+    } else {
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 1;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respainner = 1;
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 2;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respamiddle = 1;
+      irequest = neighbor->request(this,instance_me);
+      neighbor->requests[irequest]->id = 3;
+      neighbor->requests[irequest]->half = 0;
+      neighbor->requests[irequest]->respaouter = 1;
+    }
+
+  } else irequest = neighbor->request(this,instance_me);
+
+  // set rRESPA cutoffs
+
+  if (strstr(update->integrate_style,"respa") &&
+      ((Respa *) update->integrate)->level_inner >= 0)
+    cut_respa = ((Respa *) update->integrate)->cutoff;
+  else cut_respa = NULL;
+}
+
+/* ----------------------------------------------------------------------
+   neighbor callback to inform pair style of neighbor list to use
+   regular or rRESPA
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::init_list(int id, NeighList *ptr)
+{
+  if (id == 0) list = ptr;
+  else if (id == 1) listinner = ptr;
+  else if (id == 2) listmiddle = ptr;
+  else if (id == 3) listouter = ptr;
+}
+
+/* ----------------------------------------------------------------------
+   init for one type pair i,j and corresponding j,i
+------------------------------------------------------------------------- */
+
+double PairLJCutHARSCG::init_one(int i, int j)
+{
+  if (setflag[i][j] == 0) {
+    epsilon[i][j] = mix_energy(epsilon[i][i],epsilon[j][j],
+                               sigma[i][i],sigma[j][j]);
+    sigma[i][j] = mix_distance(sigma[i][i],sigma[j][j]);
+    cut[i][j] = mix_distance(cut[i][i],cut[j][j]);
+  }
+
+
+  lj1[i][j] = 48.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
+  lj2[i][j] = 24.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
+  lj3[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],12.0);
+  lj4[i][j] = 4.0 * epsilon[i][j] * pow(sigma[i][j],6.0);
+
+
+  if (offset_flag) {
+    double ratio = sigma[i][j] / cut[i][j];
+    offset[i][j] = 4.0 * epsilon[i][j] * (pow(ratio,12.0) - pow(ratio,6.0));
+  } else offset[i][j] = 0.0;
+
+  lj1[j][i] = lj1[i][j];
+  lj2[j][i] = lj2[i][j];
+  lj3[j][i] = lj3[i][j];
+  lj4[j][i] = lj4[i][j];
+  offset[j][i] = offset[i][j];
+
+  // check interior rRESPA cutoff
+
+  if (cut_respa && cut[i][j] < cut_respa[3])
+    error->all(FLERR,"Pair cutoff < Respa interior cutoff");
+
+  // compute I,J contribution to long-range tail correction
+  // count total # of atoms of type I and J via Allreduce
+
+  if (tail_flag) {
+    int *type = atom->type;
+    int nlocal = atom->nlocal;
+
+    double count[2],all[2];
+    count[0] = count[1] = 0.0;
+    for (int k = 0; k < nlocal; k++) {
+      if (type[k] == i) count[0] += 1.0;
+      if (type[k] == j) count[1] += 1.0;
+    }
+    MPI_Allreduce(count,all,2,MPI_DOUBLE,MPI_SUM,world);
+
+    double sig2 = sigma[i][j]*sigma[i][j];
+    double sig6 = sig2*sig2*sig2;
+    double rc3 = cut[i][j]*cut[i][j]*cut[i][j];
+    double rc6 = rc3*rc3;
+    double rc9 = rc3*rc6;
+    etail_ij = 8.0*MY_PI*all[0]*all[1]*epsilon[i][j] *
+      sig6 * (sig6 - 3.0*rc6) / (9.0*rc9);
+    ptail_ij = 16.0*MY_PI*all[0]*all[1]*epsilon[i][j] *
+      sig6 * (2.0*sig6 - 3.0*rc6) / (9.0*rc9);
+  }
+
+  return cut[i][j];
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::write_restart(FILE *fp)
+{
+  write_restart_settings(fp);
+
+  int i,j;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      fwrite(&setflag[i][j],sizeof(int),1,fp);
+      if (setflag[i][j]) {
+        fwrite(&epsilon[i][j],sizeof(double),1,fp);
+        fwrite(&sigma[i][j],sizeof(double),1,fp);
+        fwrite(&cut[i][j],sizeof(double),1,fp);
+      }
+    }
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::read_restart(FILE *fp)
+{
+  read_restart_settings(fp);
+  allocate();
+
+  int i,j;
+  int me = comm->me;
+  for (i = 1; i <= atom->ntypes; i++)
+    for (j = i; j <= atom->ntypes; j++) {
+      if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
+      MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
+      if (setflag[i][j]) {
+        if (me == 0) {
+          fread(&epsilon[i][j],sizeof(double),1,fp);
+          fread(&sigma[i][j],sizeof(double),1,fp);
+          fread(&cut[i][j],sizeof(double),1,fp);
+        }
+        MPI_Bcast(&epsilon[i][j],1,MPI_DOUBLE,0,world);
+        MPI_Bcast(&sigma[i][j],1,MPI_DOUBLE,0,world);
+        MPI_Bcast(&cut[i][j],1,MPI_DOUBLE,0,world);
+      }
+    }
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes to restart file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::write_restart_settings(FILE *fp)
+{
+  fwrite(&cut_global,sizeof(double),1,fp);
+  fwrite(&offset_flag,sizeof(int),1,fp);
+  fwrite(&mix_flag,sizeof(int),1,fp);
+  fwrite(&tail_flag,sizeof(int),1,fp);
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 reads from restart file, bcasts
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::read_restart_settings(FILE *fp)
+{
+  int me = comm->me;
+  if (me == 0) {
+    fread(&cut_global,sizeof(double),1,fp);
+    fread(&offset_flag,sizeof(int),1,fp);
+    fread(&mix_flag,sizeof(int),1,fp);
+    fread(&tail_flag,sizeof(int),1,fp);
+  }
+  MPI_Bcast(&cut_global,1,MPI_DOUBLE,0,world);
+  MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
+  MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
+  MPI_Bcast(&tail_flag,1,MPI_INT,0,world);
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes to data file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::write_data(FILE *fp)
+{
+  for (int i = 1; i <= atom->ntypes; i++)
+    fprintf(fp,"%d %g %g\n",i,epsilon[i][i],sigma[i][i]);
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 writes all pairs to data file
+------------------------------------------------------------------------- */
+
+void PairLJCutHARSCG::write_data_all(FILE *fp)
+{
+  for (int i = 1; i <= atom->ntypes; i++)
+    for (int j = i; j <= atom->ntypes; j++)
+      fprintf(fp,"%d %d %g %g %g\n",i,j,epsilon[i][j],sigma[i][j],cut[i][j]);
+}
+
+/* ---------------------------------------------------------------------- */
+
+double PairLJCutHARSCG::single(int i, int j, int itype, int jtype, double rsq,
+                         double factor_coul, double factor_lj,
+                         double &fforce)
+{
+  double r2inv,r6inv,forcelj,philj;
+
+  r2inv = 1.0/rsq;
+  r6inv = r2inv*r2inv*r2inv;
+  forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]);
+  fforce = factor_lj*forcelj*r2inv;
+
+  philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) -
+    offset[itype][jtype];
+  return factor_lj*philj;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void *PairLJCutHARSCG::extract(const char *str, int &dim)
+{
+  dim = 2;
+  if (strcmp(str,"epsilon") == 0) return (void *) epsilon;
+  if (strcmp(str,"sigma") == 0) return (void *) sigma;
+  return NULL;
+}
+
+
+
+int PairLJCutHARSCG::molecules_in_group(tagint &idlo, tagint &idhi)
+{
+  int i;
+
+  memory->destroy(molmap_H);
+  molmap_H = NULL;
+
+  // find lo/hi molecule ID for any atom in group
+  // warn if atom in group has ID = 0
+
+  tagint *molecule = atom->molecule;
+  int *mask = atom->mask;
+  int nlocal = atom->nlocal;
+
+  tagint lo = BIG;
+  tagint hi = -BIG;
+  int flag = 0;
+  for (i = 0; i < nlocal; i++)
+  {
+//    if (mask[i] & groupbit) {
+      if (mask[i]) {
+      if (molecule[i] == 0) flag = 1;
+      lo = MIN(lo,molecule[i]);
+      hi = MAX(hi,molecule[i]);
+    }
+  }
+
+  int flagall;
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,"Atom with molecule ID = 0 included in "
+                   "compute molecule group");
+
+  MPI_Allreduce(&lo,&idlo,1,MPI_LMP_TAGINT,MPI_MIN,world);
+  MPI_Allreduce(&hi,&idhi,1,MPI_LMP_TAGINT,MPI_MAX,world);
+  if (idlo == BIG) return 0;
+
+  // molmap = vector of length nlen
+  // set to 1 for IDs that appear in group across all procs, else 0
+
+  tagint nlen_tag = idhi-idlo+1;
+  if (nlen_tag > MAXSMALLINT)
+    error->all(FLERR,"Too many molecules for compute");
+  int nlen = (int) nlen_tag;
+
+  memory->create(molmap_H,nlen,"pair:molmap_H");
+  for (i = 0; i < nlen; i++) molmap_H[i] = 0;
+
+  for (i = 0; i < nlocal; i++)
+   // if (mask[i] & groupbit)
+       if (mask[i])
+      molmap_H[molecule[i]-idlo] = 1;
+
+  int *molmapall;
+  memory->create(molmapall,nlen,"pair:molmapall");
+  MPI_Allreduce(molmap_H,molmapall,nlen,MPI_INT,MPI_MAX,world);
+
+  // nmolecules = # of non-zero IDs in molmap
+  // molmap[i] = index of molecule, skipping molecules not in group with -1
+
+  int nmolecules = 0;
+  for (i = 0; i < nlen; i++)
+    if (molmapall[i]) molmap_H[i] = nmolecules++;
+    else molmap_H[i] = -1;
+  memory->destroy(molmapall);
+
+  // warn if any molecule has some atoms in group and some not in group
+
+  flag = 0;
+  for (i = 0; i < nlocal; i++) {
+//    if (mask[i] & groupbit) continue;
+      if (mask[i]) continue;
+    if (molecule[i] < idlo || molecule[i] > idhi) continue;
+    if (molmap_H[molecule[i]-idlo] >= 0) flag = 1;
+  }
+
+  MPI_Allreduce(&flag,&flagall,1,MPI_INT,MPI_SUM,world);
+  if (flagall && comm->me == 0)
+    error->warning(FLERR,
+                   "One or more compute molecules has atoms not in group");
+
+  // if molmap simply stores 1 to Nmolecules, then free it
+
+  if (idlo == 1 && idhi == nmolecules && nlen == nmolecules) {
+    memory->destroy(molmap_H);
+    molmap_H = NULL;
+  }
+  return nmolecules;
+}
+
+
+
+void PairLJCutHARSCG::CG_Print_Compensation_Energy(){
+
+    FILE *fp1;
+
+    fp1 = fopen("Mean_Comp_Energy_CG.txt","w");
+    if (fp1 == NULL) {
+        char str[128];
+        sprintf(str,"Cannot open Mean_Comp_Energy_CG.txt file %s","Mean_Comp_Energy_CG.txt");
+        error->one(FLERR,str);
+
+    }
+
+    for(int i = 0;i < CG_Bin_Num; i++){
+        fprintf(fp1,"%d",i+1);
+        for(int k = 0; k < atom->nmoltypesH;k++)
+            fprintf(fp1,"\t%.10f",Mean_Comp_Energy_H[i][k]);
+
+        fprintf(fp1,"\n");
+    }
+
+    fclose(fp1);
+
+}
+
+
+
+void PairLJCutHARSCG::CG_Update_Compensation_Energy(){
+
+    MPI_Allreduce(&Comp_Energy_H[0][0],&Comp_Energy_all_H[0][0],CG_Bin_Num*(atom->nmoltypesH+1),MPI_DOUBLE,MPI_SUM,world);
+    MPI_Allreduce(&Comp_Energy_Num_H[0][0],&Comp_Energy_Num_all_H[0][0],CG_Bin_Num*(atom->nmoltypesH+1),MPI_INT,MPI_SUM,world);
+
+    for(int k = 0; k < atom->nmoltypesH;k++)for(int i = 0;i < CG_Bin_Num; i++)Mean_Energy_H[i][k] = Comp_Energy_all_H[i][k] / Comp_Energy_Num_all_H[i][k];
+    for(int k = 0; k < atom->nmoltypesH;k++)for(int i = 0;i < CG_Bin_Num; i++)Mean_Comp_Energy_H[i][k] = (Comp_Counter_H * Mean_Comp_Energy_H[i][k] + Mean_Energy_H[i][k]) / (Comp_Counter_H + 1);
+    for(int k = 0; k < atom->nmoltypesH;k++)for(int i = 0;i < CG_Bin_Num; i++)Int_Mean_Energy_H[i][k]=0;
+    for(int k = 0; k < atom->nmoltypesH;k++)for(int i = 0;i < CG_Bin_Num; i++)for(int j = 0;j <= i; j++)Int_Mean_Energy_H[i][k] += Mean_Comp_Energy_H[j][k] * CG_lambda_Increment;
+
+    Comp_Counter_H++;
+
+    for(int k = 0; k < atom->nmoltypesH;k++){
+        for(int i = 0;i < CG_Bin_Num; i++){
+            Comp_Energy_Num_H[i][k] = 0;
+            Comp_Energy_Num_all_H[i][k] = 0;
+            Comp_Energy_H[i][k] = 0;
+            Comp_Energy_all_H[i][k] =0;
+        }
+    }
+
+    if (me == 0)CG_Print_Compensation_Energy();
+
+
+}
+
+
+void PairLJCutHARSCG::Load_Compensation_Pressure(){
+
+    if(me == 0){
+        FILE *fp1;
+        char str[128];
+
+        fp1 = fopen("Mean_Comp_Energy_CG.txt","r");
+        if (fp1 == NULL) {
+            sprintf(str,"Cannot open fix Mean_Comp_Energy_CG.txt file %s","Mean_Comp_Energy_CG.txt");
+            error->one(FLERR,str);
+        }
+
+        int i1;
+        float i2;
+
+        while (!feof(fp1)){
+            fscanf (fp1,"%d",&i1);
+            for(int k = 0; k < atom->nmoltypesH;k++){
+                fscanf (fp1,"\t%f",&i2);
+                Mean_Comp_Energy_H[i1-1][k] = i2;
+                if(i1 > CG_Bin_Num){
+                    sprintf(str,"CG drift force compensation bin number mismatches %d != %d",CG_Bin_Num,i1);
+                    error->one(FLERR,str);
+                }
+            }
+
+        }
+    }
+
+
+    if(me==0){
+        if(screen)fprintf(screen,"CG_Pressure componsation forces distributed successfully!\n");
+        if(logfile)fprintf(logfile,"CG_Pressure componsation forces distributed successfully!\n");
+    }
+
+    MPI_Bcast(Mean_Comp_Energy_H,CG_Bin_Num*(atom->nmoltypesH+1),MPI_DOUBLE,0,world);
+}
+
+
+void PairLJCutHARSCG::H_AdResS_Allocation(){
+
+
+    for (int i = 0; i < modify->nfix; i++){
+
+        if (strcmp(modify->fix[i]->style,"LambdaH/calc") == 0){
+
+            lambda_H_fix = (FixLambdaHCalc *) modify->fix[i];
+            CG_lambda_Increment = lambda_H_fix->Pressure_lambda_Increment;
+            CG_Bin_Num = lambda_H_fix->Pressure_Bin_Num;
+            CG_Update_Frequency = lambda_H_fix->Pressure_Update_Frequency;
+            CG_Update_Time_Begin = lambda_H_fix->Pressure_Update_Time_Begin;
+            CG_Update_Time_End = lambda_H_fix->Pressure_Update_Time_End;
+
+            CG_Density_Bin_Num = lambda_H_fix->Density_Bin_Num;
+            CG_Density_Bin_Size = lambda_H_fix->Density_Bin_Size;
+            CG_Density_Update_Frequency = lambda_H_fix->Density_Update_Frequency;
+            CG_Density_Update_Time_Begin = lambda_H_fix->Density_Update_Time_Begin;
+            CG_Density_Update_Time_End = lambda_H_fix->Density_Update_Time_End;
+
+            CG_Pressure_Comp_Flag = lambda_H_fix->Pressure_Comp_Flag;
+            CG_Density_Comp_Flag = lambda_H_fix->Density_Comp_Flag;
+            CG_center_box = lambda_H_fix->center_box;
+            CG_Hybrid_Style = lambda_H_fix->Hybrid_Style;
+            CG_x0lo = lambda_H_fix->x0lo;
+            CG_x0BoxSize = lambda_H_fix->x0BoxSize;
+        }
+    }
+
+    if(me == 0){
+        if (screen){
+            fprintf(screen,"CG_lambda_Increment= %f\n",CG_lambda_Increment);
+            fprintf(screen,"CG_Bin_Num= %d\n",CG_Bin_Num);
+            fprintf(screen,"CG_Update_Frequency= %d\n",CG_Update_Frequency);
+            fprintf(screen,"CG_Update_Time_Begin= %d\n",CG_Update_Time_Begin);
+            fprintf(screen,"CG_Update_Time_End= %d\n",CG_Update_Time_End);
+            fprintf(screen,"CG_Pressure_Comp_Flag= %d\n",CG_Pressure_Comp_Flag);
+            fprintf(screen,"CG_Density_Comp_Flag= %d\n",CG_Density_Comp_Flag);
+            fprintf(screen,"CG_Hybrid_Style= %d\n",CG_Hybrid_Style);
+
+        }
+
+        if (logfile){
+            fprintf(logfile,"CG_lambda_Increment= %f\n",CG_lambda_Increment);
+            fprintf(logfile,"CG_Bin_Num= %d\n",CG_Bin_Num);
+            fprintf(logfile,"CG_Update_Frequency= %d\n",CG_Update_Frequency);
+            fprintf(logfile,"CG_Update_Time_Begin= %d\n",CG_Update_Time_Begin);
+            fprintf(logfile,"CG_Update_Time_End= %d\n",CG_Update_Time_End);
+            fprintf(logfile,"CG_Pressure_Comp_Flag= %d\n",CG_Pressure_Comp_Flag);
+            fprintf(logfile,"CG_Density_Comp_Flag= %d\n",CG_Density_Comp_Flag);
+            fprintf(logfile,"CG_Hybrid_Style= %d\n",CG_Hybrid_Style);
+
+        }
+
+
+    }
+
+
+    memory->create(Comp_Energy_Num_H,CG_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:Comp_Energy_Num_H");
+    memory->create(Comp_Energy_Num_all_H,CG_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:Comp_Energy_Num_all_H");
+    memory->create(Int_Mean_Energy_H,CG_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:Int_Mean_Energy_H");
+    memory->create(Comp_Energy_H,CG_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:Comp_Energy_H");
+    memory->create(Comp_Energy_all_H,CG_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:Comp_Energy_all_H");
+    memory->create(Mean_Comp_Energy_H,CG_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:Mean_Comp_Energy_H");
+    memory->create(Mean_Energy_H,CG_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:Mean_Energy_H");
+
+    memory->create(CG_Mean_grad_Comp_Density_Conv_H,CG_Density_Bin_Num,atom->nmoltypesH+1,"pairLJHCG:CG_Mean_grad_Comp_Density_Conv_H");
+    CG_Mean_grad_Comp_Density_Conv_H = lambda_H_fix->Mean_grad_Comp_Density_Conv_H;
+
+
+    for(int i = 0;i < CG_Bin_Num; i++){
+        for(int j = 0; j < atom->nmoltypesH; j++){
+            Int_Mean_Energy_H[i][j] = 0;
+            Comp_Energy_H[i][j] = 0;
+            Comp_Energy_all_H[i][j] = 0;
+            Mean_Comp_Energy_H[i][j] = 0;
+            Comp_Energy_Num_H[i][j] = 0;
+            Comp_Energy_Num_all_H[i][j] = 0;
+        }
+    }
+
+
+    H_AdResS_allocated = 1;
+
+}
diff --git a/src/USER-HADRESS/pair_lj_cut_hars_cg.h b/src/USER-HADRESS/pair_lj_cut_hars_cg.h
new file mode 100644
index 000000000..df47c27ec
--- /dev/null
+++ b/src/USER-HADRESS/pair_lj_cut_hars_cg.h
@@ -0,0 +1,123 @@
+/* -*- 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 PAIR_CLASS
+
+PairStyle(lj/cut/hars/cg,PairLJCutHARSCG)
+
+#else
+
+#ifndef LMP_PAIR_LJ_CUT_HARS_CG_H
+#define LMP_PAIR_LJ_CUT_HARS_CG_H
+
+#include "pair.h"
+
+namespace LAMMPS_NS {
+
+class PairLJCutHARSCG : public Pair {
+ public:
+  PairLJCutHARSCG(class LAMMPS *);
+  virtual ~PairLJCutHARSCG();
+  virtual void compute(int, int);
+  void settings(int, char **);
+  void coeff(int, char **);
+  void init_style();
+  void init_list(int, class NeighList *);
+  double init_one(int, int);
+  void write_restart(FILE *);
+  void read_restart(FILE *);
+  void write_restart_settings(FILE *);
+  void read_restart_settings(FILE *);
+  void write_data(FILE *);
+  void write_data_all(FILE *);
+  double single(int, int, int, int, double, double, double, double &);
+  void *extract(const char *, int &);
+
+  void compute_inner();
+  void compute_middle();
+  void compute_outer(int, int);
+
+  void CG_Print_Compensation_Energy();
+  void CG_Update_Compensation_Energy();
+
+ protected:
+  double cut_global;
+  double **cut;
+  double **epsilon,**sigma;
+  double **lj1,**lj2,**lj3,**lj4,**offset;
+  double *cut_respa;
+  class FixLambdaHCalc *lambda_H_fix;
+  int AllCoarseGrained;
+
+  double *CG_Ave_Mean_Density_H,CG_grad_Ave_Mean_Density_H;
+ //private:
+
+  int me;
+  virtual void allocate();
+
+  int H_AdResS_allocated;
+  int **Comp_Energy_Num_H,**Comp_Energy_Num_all_H, Comp_Counter_H;
+
+  double CG_lambda_Increment;
+  int CG_Bin_Num, CG_Update_Frequency, CG_Update_Time_End, CG_Update_Time_Begin;
+  int CG_Pressure_Compensation_Run, Density_Compensation_Run;
+
+  int CG_Pressure_Comp_Flag, CG_Density_Comp_Flag;
+
+  double CG_Density_Bin_Size,**CG_Mean_grad_Comp_Density_Conv_H,CG_x0BoxSize;
+  int CG_Density_Bin_Num,CG_Density_Update_Frequency,CG_Density_Update_Time_Begin,CG_Density_Update_Time_End;
+  double **Int_Mean_Energy_H, **Comp_Energy_H, **Comp_Energy_all_H, **Mean_Energy_H, **Mean_Comp_Energy_H;
+
+  double *CG_center_box, CG_x0lo;
+  int CG_Hybrid_Style;
+    int nmolecules;
+    tagint idlo,idhi;
+
+    double *massproc_H,*masstotal_H;
+
+    double **mol_f_H, **mol_f_all_H;
+
+   int CG_Restart_Time_Step;
+    //double **drift_f_H, **drift_f_all_H;
+    //int nbin_H;
+    int *molmap_H;                 // convert molecule ID to local index
+    int Load_File_Flag;
+
+    int molecules_in_group(tagint &, tagint &);
+    void Load_Compensation_Pressure();
+    void H_AdResS_Allocation();
+};
+
+}
+
+#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: Incorrect args for pair coefficients
+
+Self-explanatory.  Check the input script or data file.
+
+E: Pair cutoff < Respa interior cutoff
+
+One or more pairwise cutoffs are too short to use with the specified
+rRESPA cutoffs.
+
+*/
diff --git a/src/USER-HADRESS/read_data.cpp b/src/USER-HADRESS/read_data.cpp
new file mode 100644
index 000000000..478412ae0
--- /dev/null
+++ b/src/USER-HADRESS/read_data.cpp
@@ -0,0 +1,2023 @@
+/* ----------------------------------------------------------------------
+   LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
+   http://lammps.sandia.gov, Sandia National Laboratories
+   Steve Plimpton, sjplimp@sandia.gov
+
+   Copyright (2003) Sandia Corporation.  Under the terms of Contract
+   DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
+   certain rights in this software.  This software is distributed under
+   the GNU General Public License.
+
+   See the README file in the top-level LAMMPS directory.
+------------------------------------------------------------------------- */
+
+// lmptype.h must be first b/c this file uses MAXBIGINT and includes mpi.h
+// due to OpenMPI bug which sets INT64_MAX via its mpi.h
+//   before lmptype.h can set flags to insure it is done correctly
+
+#include "lmptype.h"
+#include <mpi.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "read_data.h"
+#include "atom.h"
+#include "atom_vec.h"
+#include "atom_vec_ellipsoid.h"
+#include "atom_vec_line.h"
+#include "atom_vec_tri.h"
+#include "force.h"
+#include "molecule.h"
+#include "group.h"
+#include "comm.h"
+#include "update.h"
+#include "modify.h"
+#include "fix.h"
+#include "force.h"
+#include "pair.h"
+#include "domain.h"
+#include "bond.h"
+#include "angle.h"
+#include "dihedral.h"
+#include "improper.h"
+#include "special.h"
+#include "irregular.h"
+#include "error.h"
+#include "memory.h"
+
+using namespace LAMMPS_NS;
+
+#define MAXLINE 256
+#define LB_FACTOR 1.1
+#define CHUNK 1024
+#define DELTA 4            // must be 2 or larger
+#define MAXBODY 32         // max # of lines in one body
+
+                           // customize for new sections
+#define NSECTIONS 25       // change when add to header::section_keywords
+
+enum{NONE,APPEND,VALUE,MERGE};
+
+// pair style suffixes to ignore
+// when matching Pair Coeffs comment to currently-defined pair style
+
+const char *suffixes[] = {"/cuda","/gpu","/opt","/omp","/kk",
+                          "/coul/cut","/coul/long","/coul/msm",
+                          "/coul/dsf","/coul/debye","/coul/charmm",
+                          NULL};
+
+/* ---------------------------------------------------------------------- */
+
+ReadData::ReadData(LAMMPS *lmp) : Pointers(lmp)
+{
+  MPI_Comm_rank(world,&me);
+  line = new char[MAXLINE];
+  copy = new char[MAXLINE];
+  keyword = new char[MAXLINE];
+  style = new char[MAXLINE];
+  buffer = new char[CHUNK*MAXLINE];
+  narg = maxarg = 0;
+  arg = NULL;
+  fp = NULL;
+
+  // customize for new sections
+  // pointers to atom styles that store extra info
+
+  nellipsoids = 0;
+  avec_ellipsoid = (AtomVecEllipsoid *) atom->style_match("ellipsoid");
+  nlines = 0;
+  avec_line = (AtomVecLine *) atom->style_match("line");
+  ntris = 0;
+  avec_tri = (AtomVecTri *) atom->style_match("tri");
+  nbodies = 0;
+  avec_body = (AtomVecBody *) atom->style_match("body");
+}
+
+/* ---------------------------------------------------------------------- */
+
+ReadData::~ReadData()
+{
+  delete [] line;
+  delete [] copy;
+  delete [] keyword;
+  delete [] style;
+  delete [] buffer;
+  memory->sfree(arg);
+
+  for (int i = 0; i < nfix; i++) {
+    delete [] fix_header[i];
+    delete [] fix_section[i];
+  }
+  memory->destroy(fix_index);
+  memory->sfree(fix_header);
+  memory->sfree(fix_section);
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::command(int narg, char **arg)
+{
+  if (narg < 1) error->all(FLERR,"Illegal read_data command");
+
+  // optional args
+
+  addflag = NONE;
+  coeffflag = 1;
+  id_offset = 0;
+  offsetflag = shiftflag = 0;
+  toffset = boffset = aoffset = doffset = ioffset = 0;
+  shift[0] = shift[1] = shift[2] = 0.0;
+  extra_atom_types = extra_bond_types = extra_angle_types =
+    extra_dihedral_types = extra_improper_types = 0;
+
+  groupbit = 0;
+
+  nfix = 0;
+  fix_index = NULL;
+  fix_header = NULL;
+  fix_section = NULL;
+
+  int iarg = 1;
+  while (iarg < narg) {
+    if (strcmp(arg[iarg],"add") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal read_data command");
+      if (strcmp(arg[iarg+1],"append") == 0) addflag = APPEND;
+      else if (strcmp(arg[iarg+1],"merge") == 0) addflag = MERGE;
+      else {
+        addflag = VALUE;
+        bigint offset = force->bnumeric(FLERR,arg[iarg+1]);
+        if (offset > MAXTAGINT)
+          error->all(FLERR,"Read data add offset is too big");
+        id_offset = offset;
+      }
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"offset") == 0) {
+      if (iarg+6 > narg) error->all(FLERR,"Illegal read_data command");
+      offsetflag = 1;
+      toffset = force->inumeric(FLERR,arg[iarg+1]);
+      boffset = force->inumeric(FLERR,arg[iarg+2]);
+      aoffset = force->inumeric(FLERR,arg[iarg+3]);
+      doffset = force->inumeric(FLERR,arg[iarg+4]);
+      ioffset = force->inumeric(FLERR,arg[iarg+5]);
+      if (toffset < 0 || boffset < 0 || aoffset < 0 ||
+          doffset < 0 || ioffset < 0)
+        error->all(FLERR,"Illegal read_data command");
+      iarg += 6;
+    } else if (strcmp(arg[iarg],"shift") == 0) {
+      if (iarg+4 > narg) error->all(FLERR,"Illegal read_data command");
+      shiftflag = 1;
+      shift[0] = force->numeric(FLERR,arg[iarg+1]);
+      shift[1] = force->numeric(FLERR,arg[iarg+2]);
+      shift[2] = force->numeric(FLERR,arg[iarg+3]);
+      if (domain->dimension == 2 && shift[2] != 0.0)
+        error->all(FLERR,"Non-zero read_data shift z value for 2d simulation");
+      iarg += 4;
+    } else if (strcmp(arg[iarg],"nocoeff") == 0) {
+      coeffflag = 0;
+      iarg ++;
+    } else if (strcmp(arg[iarg],"extra/atom/types") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal read_data command");
+      extra_atom_types = force->inumeric(FLERR,arg[iarg+1]);
+      if (extra_atom_types < 0) error->all(FLERR,"Illegal read_data command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"extra/bond/types") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal read_data command");
+      if (!atom->avec->bonds_allow)
+        error->all(FLERR,"No bonds allowed with this atom style");
+      extra_bond_types = force->inumeric(FLERR,arg[iarg+1]);
+      if (extra_bond_types < 0) error->all(FLERR,"Illegal read_data command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"extra/angle/types") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal read_data command");
+      if (!atom->avec->angles_allow)
+        error->all(FLERR,"No angles allowed with this atom style");
+      extra_angle_types = force->inumeric(FLERR,arg[iarg+1]);
+      if (extra_angle_types < 0) error->all(FLERR,"Illegal read_data command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"extra/dihedral/types") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal read_data command");
+      if (!atom->avec->dihedrals_allow)
+        error->all(FLERR,"No dihedrals allowed with this atom style");
+      extra_dihedral_types = force->inumeric(FLERR,arg[iarg+1]);
+      if (extra_dihedral_types < 0)
+        error->all(FLERR,"Illegal read_data command");
+      iarg += 2;
+    } else if (strcmp(arg[iarg],"extra/improper/types") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal read_data command");
+      if (!atom->avec->impropers_allow)
+        error->all(FLERR,"No impropers allowed with this atom style");
+      extra_improper_types = force->inumeric(FLERR,arg[iarg+1]);
+      if (extra_improper_types < 0)
+        error->all(FLERR,"Illegal read_data command");
+      iarg += 2;
+
+    } else if (strcmp(arg[iarg],"group") == 0) {
+      if (iarg+2 > narg) error->all(FLERR,"Illegal read_data command");
+      int igroup = group->find_or_create(arg[iarg+1]);
+      groupbit = group->bitmask[igroup];
+      iarg += 2;
+
+    } else if (strcmp(arg[iarg],"fix") == 0) {
+      if (iarg+4 > narg)
+        error->all(FLERR,"Illegal read_data command");
+      memory->grow(fix_index,nfix+1,"read_data:fix_index");
+      fix_header = (char **)
+        memory->srealloc(fix_header,(nfix+1)*sizeof(char *),
+                         "read_data:fix_header");
+      fix_section = (char **)
+        memory->srealloc(fix_section,(nfix+1)*sizeof(char *),
+                         "read_data:fix_section");
+      fix_index[nfix] = modify->find_fix(arg[iarg+1]);
+      if (fix_index[nfix] < 0)
+        error->all(FLERR,"Fix ID for read_data does not exist");
+      if (strcmp(arg[iarg+2],"NULL") == 0) fix_header[nfix] = NULL;
+      else {
+        int n = strlen(arg[iarg+2]) + 1;
+        fix_header[nfix] = new char[n];
+        strcpy(fix_header[nfix],arg[iarg+2]);
+      }
+      int n = strlen(arg[iarg+3]) + 1;
+      fix_section[nfix] = new char[n];
+      strcpy(fix_section[nfix],arg[iarg+3]);
+      nfix++;
+      iarg += 4;
+
+    } else error->all(FLERR,"Illegal read_data command");
+  }
+
+  // error checks
+
+  if (domain->dimension == 2 && domain->zperiodic == 0)
+    error->all(FLERR,"Cannot run 2d simulation with nonperiodic Z dimension");
+  if (domain->box_exist && !addflag)
+    error->all(FLERR,"Cannot read_data without add keyword "
+               "after simulation box is defined");
+  if (!domain->box_exist && addflag)
+    error->all(FLERR,"Cannot use read_data add before "
+               "simulation box is defined");
+  if (offsetflag && addflag == NONE)
+    error->all(FLERR,"Cannot use read_data offset without add flag");
+  if (shiftflag && addflag == NONE)
+    error->all(FLERR,"Cannot use read_data shift without add flag");
+  if (addflag != NONE &&
+      (extra_atom_types || extra_bond_types || extra_angle_types ||
+       extra_dihedral_types || extra_improper_types))
+    error->all(FLERR,"Cannot use read_data extra with add flag");
+
+  // first time system initialization
+
+  if (addflag == NONE) {
+    domain->box_exist = 1;
+    update->ntimestep = 0;
+  }
+
+  // compute atomID offset for addflag = MERGE
+
+  if (addflag == APPEND) {
+    tagint *tag = atom->tag;
+    int nlocal = atom->nlocal;
+    tagint max = 0;
+    for (int i = 0; i < nlocal; i++) max = MAX(max,tag[i]);
+    MPI_Allreduce(&max,&id_offset,1,MPI_LMP_TAGINT,MPI_MAX,world);
+  }
+
+  // set up pointer to hold original styles while we replace them with "zero"
+  Pair *saved_pair = NULL;
+  Bond *saved_bond = NULL;
+  Angle *saved_angle = NULL;
+  Dihedral *saved_dihedral = NULL;
+  Improper *saved_improper = NULL;
+  KSpace *saved_kspace = NULL;
+
+  if (coeffflag == 0) {
+    char *coeffs[2];
+    coeffs[0] = (char *) "10.0";
+    coeffs[1] = (char *) "nocoeff";
+
+    saved_pair = force->pair;
+    force->pair = NULL;
+    force->create_pair("zero",0);
+    if (force->pair) force->pair->settings(2,coeffs);
+
+    coeffs[0] = coeffs[1];
+    saved_bond = force->bond;
+    force->bond = NULL;
+    force->create_bond("zero",0);
+    if (force->bond) force->bond->settings(1,coeffs);
+
+    saved_angle = force->angle;
+    force->angle = NULL;
+    force->create_angle("zero",0);
+    if (force->angle) force->angle->settings(1,coeffs);
+
+    saved_dihedral = force->dihedral;
+    force->dihedral = NULL;
+    force->create_dihedral("zero",0);
+    if (force->dihedral) force->dihedral->settings(1,coeffs);
+
+    saved_improper = force->improper;
+    force->improper = NULL;
+    force->create_improper("zero",0);
+    if (force->improper) force->improper->settings(1,coeffs);
+
+    saved_kspace = force->kspace;
+    force->kspace = NULL;
+  }
+
+  // -----------------------------------------------------------------
+
+  // perform 1-pass read if no molecular topology in file
+  // perform 2-pass read if molecular topology,
+  //   first pass calculates max topology/atom
+
+  // flags for this data file
+
+  int atomflag,topoflag;
+  int bondflag,angleflag,dihedralflag,improperflag;
+  int ellipsoidflag,lineflag,triflag,bodyflag;
+
+  atomflag = topoflag = 0;
+  bondflag = angleflag = dihedralflag = improperflag = 0;
+  ellipsoidflag = lineflag = triflag = bodyflag = 0;
+
+  // values in this data file
+
+  natoms = ntypes = 0;
+  nbonds = nangles = ndihedrals = nimpropers = 0;
+  nbondtypes = nangletypes = ndihedraltypes = nimpropertypes = 0;
+  triclinic = 0;
+  keyword[0] = '\0';
+
+  nlocal_previous = atom->nlocal;
+  int firstpass = 1;
+
+  while (1) {
+
+    // open file on proc 0
+
+    if (me == 0) {
+      if (firstpass && screen) fprintf(screen,"Reading data file ...\n");
+      open(arg[0]);
+    } else fp = NULL;
+
+    // read header info
+
+    header(firstpass);
+
+    // problem setup using info from header
+    // only done once, if firstpass and first data file
+    // apply extra settings before grow(), even if no topology in file
+    // deallocate() insures new settings are used for topology arrays
+    // if per-atom topology is in file, another grow() is done below
+
+    if (firstpass && addflag == NONE) {
+      atom->bond_per_atom = atom->extra_bond_per_atom;
+      atom->angle_per_atom = atom->extra_angle_per_atom;
+      atom->dihedral_per_atom = atom->extra_dihedral_per_atom;
+      atom->improper_per_atom = atom->extra_improper_per_atom;
+
+      int n;
+      if (comm->nprocs == 1) n = static_cast<int> (atom->natoms);
+      else n = static_cast<int> (LB_FACTOR * atom->natoms / comm->nprocs);
+
+      atom->allocate_type_arrays();
+      atom->deallocate_topology();
+      atom->avec->grow(n);
+
+      domain->boxlo[0] = boxlo[0]; domain->boxhi[0] = boxhi[0];
+      domain->boxlo[1] = boxlo[1]; domain->boxhi[1] = boxhi[1];
+      domain->boxlo[2] = boxlo[2]; domain->boxhi[2] = boxhi[2];
+
+      if (triclinic) {
+        domain->triclinic = 1;
+        domain->xy = xy; domain->xz = xz; domain->yz = yz;
+      }
+
+      domain->print_box("  ");
+      domain->set_initial_box();
+      domain->set_global_box();
+      comm->set_proc_grid();
+      domain->set_local_box();
+    }
+
+    // change simulation box to be union of existing box and new box + shift
+    // only done if firstpass and not first data file
+
+    if (firstpass && addflag != NONE) {
+      domain->boxlo[0] = MIN(domain->boxlo[0],boxlo[0]+shift[0]);
+      domain->boxhi[0] = MAX(domain->boxhi[0],boxhi[0]+shift[0]);
+      domain->boxlo[1] = MIN(domain->boxlo[1],boxlo[1]+shift[1]);
+      domain->boxhi[1] = MAX(domain->boxhi[1],boxhi[1]+shift[1]);
+      domain->boxlo[2] = MIN(domain->boxlo[2],boxlo[2]+shift[2]);
+      domain->boxhi[2] = MAX(domain->boxhi[2],boxhi[2]+shift[2]);
+
+      // NOTE: not sure what to do about tilt value in subsequent data files
+      //if (triclinic) {
+      //  domain->xy = xy; domain->xz = xz; domain->yz = yz;
+      // }
+
+      domain->print_box("  ");
+      domain->set_initial_box();
+      domain->set_global_box();
+      comm->set_proc_grid();
+      domain->set_local_box();
+    }
+
+    // customize for new sections
+    // read rest of file in free format
+
+    while (strlen(keyword)) {
+
+      // if special fix matches, it processes section
+
+      if (nfix) {
+        int i;
+        for (i = 0; i < nfix; i++)
+          if (strcmp(keyword,fix_section[i]) == 0) {
+            if (firstpass) fix(fix_index[i],keyword);
+            else skip_lines(modify->fix[fix_index[i]]->
+                            read_data_skip_lines(keyword));
+            parse_keyword(0);
+            break;
+          }
+        if (i < nfix) continue;
+      }
+
+      if (strcmp(keyword,"Atoms") == 0) {
+        atomflag = 1;
+        if (firstpass) {
+          if (me == 0 && !style_match(style,atom->atom_style))
+            error->warning(FLERR,"Atom style in data file differs "
+                           "from currently defined atom style");
+          atoms();
+        } else skip_lines(natoms);
+      } else if (strcmp(keyword,"Velocities") == 0) {
+        if (atomflag == 0)
+          error->all(FLERR,"Must read Atoms before Velocities");
+        if (firstpass) velocities();
+        else skip_lines(natoms);
+
+      } else if (strcmp(keyword,"Bonds") == 0) {
+        topoflag = bondflag = 1;
+        if (nbonds == 0)
+          error->all(FLERR,"Invalid data file section: Bonds");
+        if (atomflag == 0) error->all(FLERR,"Must read Atoms before Bonds");
+        bonds(firstpass);
+      } else if (strcmp(keyword,"Angles") == 0) {
+        topoflag = angleflag = 1;
+        if (nangles == 0)
+          error->all(FLERR,"Invalid data file section: Angles");
+        if (atomflag == 0) error->all(FLERR,"Must read Atoms before Angles");
+        angles(firstpass);
+      } else if (strcmp(keyword,"Dihedrals") == 0) {
+        topoflag = dihedralflag = 1;
+        if (ndihedrals == 0)
+          error->all(FLERR,"Invalid data file section: Dihedrals");
+        if (atomflag == 0) error->all(FLERR,"Must read Atoms before Dihedrals");
+        dihedrals(firstpass);
+      } else if (strcmp(keyword,"Impropers") == 0) {
+        topoflag = improperflag = 1;
+        if (nimpropers == 0)
+          error->all(FLERR,"Invalid data file section: Impropers");
+        if (atomflag == 0) error->all(FLERR,"Must read Atoms before Impropers");
+        impropers(firstpass);
+
+      } else if (strcmp(keyword,"Ellipsoids") == 0) {
+        ellipsoidflag = 1;
+        if (!avec_ellipsoid)
+          error->all(FLERR,"Invalid data file section: Ellipsoids");
+        if (atomflag == 0)
+          error->all(FLERR,"Must read Atoms before Ellipsoids");
+        if (firstpass)
+          bonus(nellipsoids,(AtomVec *) avec_ellipsoid,"ellipsoids");
+        else skip_lines(nellipsoids);
+      } else if (strcmp(keyword,"Lines") == 0) {
+        lineflag = 1;
+        if (!avec_line)
+          error->all(FLERR,"Invalid data file section: Lines");
+        if (atomflag == 0) error->all(FLERR,"Must read Atoms before Lines");
+        if (firstpass) bonus(nlines,(AtomVec *) avec_line,"lines");
+        else skip_lines(nlines);
+      } else if (strcmp(keyword,"Triangles") == 0) {
+        triflag = 1;
+        if (!avec_tri)
+          error->all(FLERR,"Invalid data file section: Triangles");
+        if (atomflag == 0) error->all(FLERR,"Must read Atoms before Triangles");
+        if (firstpass) bonus(ntris,(AtomVec *) avec_tri,"triangles");
+        else skip_lines(ntris);
+      } else if (strcmp(keyword,"Bodies") == 0) {
+        bodyflag = 1;
+        if (!avec_body)
+          error->all(FLERR,"Invalid data file section: Bodies");
+        if (atomflag == 0) error->all(FLERR,"Must read Atoms before Bodies");
+        bodies(firstpass);
+
+      } else if (strcmp(keyword,"Masses") == 0) {
+        if (firstpass) mass();
+        else skip_lines(ntypes);
+      } else if (strcmp(keyword,"Pair Coeffs") == 0) {
+        if (force->pair == NULL)
+          error->all(FLERR,"Must define pair_style before Pair Coeffs");
+        if (firstpass) {
+          if (me == 0 && !style_match(style,force->pair_style))
+            error->warning(FLERR,"Pair style in data file differs "
+                           "from currently defined pair style");
+          paircoeffs();
+        } else skip_lines(ntypes);
+      } else if (strcmp(keyword,"PairIJ Coeffs") == 0) {
+        if (force->pair == NULL)
+          error->all(FLERR,"Must define pair_style before PairIJ Coeffs");
+        if (firstpass) {
+          if (me == 0 && !style_match(style,force->pair_style))
+            error->warning(FLERR,"Pair style in data file differs "
+                           "from currently defined pair style");
+          pairIJcoeffs();
+        } else skip_lines(ntypes*(ntypes+1)/2);
+      } else if (strcmp(keyword,"Bond Coeffs") == 0) {
+        if (atom->avec->bonds_allow == 0)
+          error->all(FLERR,"Invalid data file section: Bond Coeffs");
+        if (force->bond == NULL)
+          error->all(FLERR,"Must define bond_style before Bond Coeffs");
+        if (firstpass) {
+          if (me == 0 && !style_match(style,force->bond_style))
+            error->warning(FLERR,"Bond style in data file differs "
+                           "from currently defined bond style");
+          bondcoeffs();
+        } else skip_lines(nbondtypes);
+      } else if (strcmp(keyword,"Angle Coeffs") == 0) {
+        if (atom->avec->angles_allow == 0)
+          error->all(FLERR,"Invalid data file section: Angle Coeffs");
+        if (force->angle == NULL)
+          error->all(FLERR,"Must define angle_style before Angle Coeffs");
+        if (firstpass) {
+          if (me == 0 && !style_match(style,force->angle_style))
+            error->warning(FLERR,"Angle style in data file differs "
+                           "from currently defined angle style");
+          anglecoeffs(0);
+        } else skip_lines(nangletypes);
+      } else if (strcmp(keyword,"Dihedral Coeffs") == 0) {
+        if (atom->avec->dihedrals_allow == 0)
+          error->all(FLERR,"Invalid data file section: Dihedral Coeffs");
+        if (force->dihedral == NULL)
+          error->all(FLERR,"Must define dihedral_style before Dihedral Coeffs");
+        if (firstpass) {
+          if (me == 0 && !style_match(style,force->dihedral_style))
+            error->warning(FLERR,"Dihedral style in data file differs "
+                           "from currently defined dihedral style");
+          dihedralcoeffs(0);
+        } else skip_lines(ndihedraltypes);
+      } else if (strcmp(keyword,"Improper Coeffs") == 0) {
+        if (atom->avec->impropers_allow == 0)
+          error->all(FLERR,"Invalid data file section: Improper Coeffs");
+        if (force->improper == NULL)
+          error->all(FLERR,"Must define improper_style before Improper Coeffs");
+        if (firstpass) {
+          if (me == 0 && !style_match(style,force->improper_style))
+            error->warning(FLERR,"Improper style in data file differs "
+                           "from currently defined improper style");
+          impropercoeffs(0);
+        } else skip_lines(nimpropertypes);
+
+      } else if (strcmp(keyword,"BondBond Coeffs") == 0) {
+        if (atom->avec->angles_allow == 0)
+          error->all(FLERR,"Invalid data file section: BondBond Coeffs");
+        if (force->angle == NULL)
+          error->all(FLERR,"Must define angle_style before BondBond Coeffs");
+        if (firstpass) anglecoeffs(1);
+        else skip_lines(nangletypes);
+      } else if (strcmp(keyword,"BondAngle Coeffs") == 0) {
+        if (atom->avec->angles_allow == 0)
+          error->all(FLERR,"Invalid data file section: BondAngle Coeffs");
+        if (force->angle == NULL)
+          error->all(FLERR,"Must define angle_style before BondAngle Coeffs");
+        if (firstpass) anglecoeffs(2);
+        else skip_lines(nangletypes);
+
+      } else if (strcmp(keyword,"MiddleBondTorsion Coeffs") == 0) {
+        if (atom->avec->dihedrals_allow == 0)
+          error->all(FLERR,
+                     "Invalid data file section: MiddleBondTorsion Coeffs");
+        if (force->dihedral == NULL)
+          error->all(FLERR,
+                     "Must define dihedral_style before "
+                     "MiddleBondTorsion Coeffs");
+        if (firstpass) dihedralcoeffs(1);
+        else skip_lines(ndihedraltypes);
+      } else if (strcmp(keyword,"EndBondTorsion Coeffs") == 0) {
+        if (atom->avec->dihedrals_allow == 0)
+          error->all(FLERR,"Invalid data file section: EndBondTorsion Coeffs");
+        if (force->dihedral == NULL)
+          error->all(FLERR,
+                     "Must define dihedral_style before EndBondTorsion Coeffs");
+        if (firstpass) dihedralcoeffs(2);
+        else skip_lines(ndihedraltypes);
+      } else if (strcmp(keyword,"AngleTorsion Coeffs") == 0) {
+        if (atom->avec->dihedrals_allow == 0)
+          error->all(FLERR,"Invalid data file section: AngleTorsion Coeffs");
+        if (force->dihedral == NULL)
+          error->all(FLERR,
+                     "Must define dihedral_style before AngleTorsion Coeffs");
+        if (firstpass) dihedralcoeffs(3);
+        else skip_lines(ndihedraltypes);
+      } else if (strcmp(keyword,"AngleAngleTorsion Coeffs") == 0) {
+        if (atom->avec->dihedrals_allow == 0)
+          error->all(FLERR,
+                     "Invalid data file section: AngleAngleTorsion Coeffs");
+        if (force->dihedral == NULL)
+          error->all(FLERR,
+                     "Must define dihedral_style before "
+                     "AngleAngleTorsion Coeffs");
+        if (firstpass) dihedralcoeffs(4);
+        else skip_lines(ndihedraltypes);
+      } else if (strcmp(keyword,"BondBond13 Coeffs") == 0) {
+        if (atom->avec->dihedrals_allow == 0)
+          error->all(FLERR,"Invalid data file section: BondBond13 Coeffs");
+        if (force->dihedral == NULL)
+          error->all(FLERR,
+                     "Must define dihedral_style before BondBond13 Coeffs");
+        if (firstpass) dihedralcoeffs(5);
+        else skip_lines(ndihedraltypes);
+
+      } else if (strcmp(keyword,"AngleAngle Coeffs") == 0) {
+        if (atom->avec->impropers_allow == 0)
+          error->all(FLERR,"Invalid data file section: AngleAngle Coeffs");
+        if (force->improper == NULL)
+          error->all(FLERR,
+                     "Must define improper_style before AngleAngle Coeffs");
+        if (firstpass) impropercoeffs(1);
+        else skip_lines(nimpropertypes);
+
+      } else {
+        char str[128];
+        sprintf(str,"Unknown identifier in data file: %s",keyword);
+        error->all(FLERR,str);
+      }
+
+      parse_keyword(0);
+    }
+
+    // error if natoms > 0 yet no atoms were read
+
+    if (natoms > 0 && atomflag == 0)
+      error->all(FLERR,"No atoms in data file");
+
+    // close file
+
+    if (me == 0) {
+      if (compressed) pclose(fp);
+      else fclose(fp);
+      fp = NULL;
+    }
+
+    // done if this was 2nd pass
+
+    if (!firstpass) break;
+
+    // at end of 1st pass, error check for required sections
+    // customize for new sections
+
+    if ((nbonds && !bondflag) || (nangles && !angleflag) ||
+        (ndihedrals && !dihedralflag) || (nimpropers && !improperflag))
+      error->one(FLERR,"Needed molecular topology not in data file");
+
+    if ((nellipsoids && !ellipsoidflag) || (nlines && !lineflag) ||
+        (ntris && !triflag) || (nbodies && !bodyflag))
+      error->one(FLERR,"Needed bonus data not in data file");
+
+    // break out of loop if no molecular topology in file
+    // else make 2nd pass
+
+    if (!topoflag) break;
+    firstpass = 0;
+
+    // reallocate bond,angle,diehdral,improper arrays via grow()
+    // will use new bond,angle,dihedral,improper per-atom values from 1st pass
+    // will also observe extra settings even if bond/etc topology not in file
+    // leaves other atom arrays unchanged, since already nmax in length
+
+    if (addflag == NONE) atom->deallocate_topology();
+    atom->avec->grow(atom->nmax);
+  }
+  
+  // assign atoms added by this data file to specified group
+
+  if (groupbit) {
+    int *mask = atom->mask;
+    int nlocal = atom->nlocal;
+    for (int i = nlocal_previous; i < nlocal; i++)
+      mask[i] |= groupbit;
+  }
+
+  // create special bond lists for molecular systems
+
+  if (atom->molecular == 1) {
+    Special special(lmp);
+    special.build();
+  }
+
+  // for atom style template systems, count total bonds,angles,etc
+
+  if (atom->molecular == 2) {
+    Molecule **onemols = atom->avec->onemols;
+    int *molindex = atom->molindex;
+    int *molatom = atom->molatom;
+    int nlocal = atom->nlocal;
+
+    int imol,iatom;
+    bigint nbonds,nangles,ndihedrals,nimpropers;
+    nbonds = nangles = ndihedrals = nimpropers = 0;
+
+    for (int i = 0; i < nlocal; i++) {
+      imol = molindex[i];
+      iatom = molatom[i];
+      nbonds += onemols[imol]->num_bond[iatom];
+      nangles += onemols[imol]->num_angle[iatom];
+      ndihedrals += onemols[imol]->num_dihedral[iatom];
+      nimpropers += onemols[imol]->num_improper[iatom];
+    }
+
+    MPI_Allreduce(&nbonds,&atom->nbonds,1,MPI_LMP_BIGINT,MPI_SUM,world);
+    MPI_Allreduce(&nangles,&atom->nangles,1,MPI_LMP_BIGINT,MPI_SUM,world);
+    MPI_Allreduce(&ndihedrals,&atom->ndihedrals,1,MPI_LMP_BIGINT,MPI_SUM,world);
+    MPI_Allreduce(&nimpropers,&atom->nimpropers,1,MPI_LMP_BIGINT,MPI_SUM,world);
+
+    if (!force->newton_bond) {
+      atom->nbonds /= 2;
+      atom->nangles /= 3;
+      atom->ndihedrals /= 4;
+      atom->nimpropers /= 4;
+    }
+
+    if (me == 0) {
+      if (atom->nbonds) {
+        if (screen)
+          fprintf(screen,"  " BIGINT_FORMAT " template bonds\n",atom->nbonds);
+        if (logfile)
+          fprintf(logfile,"  " BIGINT_FORMAT " template bonds\n",atom->nbonds);
+      }
+      if (atom->nangles) {
+        if (screen)
+          fprintf(screen,"  " BIGINT_FORMAT " template angles\n",
+                  atom->nangles);
+        if (logfile)
+          fprintf(logfile,"  " BIGINT_FORMAT " template angles\n",
+                  atom->nangles);
+      }
+      if (atom->ndihedrals) {
+        if (screen)
+          fprintf(screen,"  " BIGINT_FORMAT " template dihedrals\n",
+                  atom->nbonds);
+        if (logfile)
+          fprintf(logfile,"  " BIGINT_FORMAT " template bonds\n",
+                  atom->ndihedrals);
+      }
+      if (atom->nimpropers) {
+        if (screen)
+          fprintf(screen,"  " BIGINT_FORMAT " template impropers\n",
+                  atom->nimpropers);
+        if (logfile)
+          fprintf(logfile,"  " BIGINT_FORMAT " template impropers\n",
+                  atom->nimpropers);
+      }
+    }
+  }
+
+  // for atom style template systems
+  // insure nbondtypes,etc are still consistent with template molecules,
+  //   in case data file re-defined them
+
+  if (atom->molecular == 2) atom->avec->onemols[0]->check_attributes(1);
+
+  // if adding atoms, migrate atoms to new processors
+  // use irregular() b/c box size could have changed dramaticaly
+  // resulting in procs now owning very different subboxes
+  // with their previously owned atoms now far outside the subbox
+
+  if (addflag != NONE) {
+    if (domain->triclinic) domain->x2lamda(atom->nlocal);
+    Irregular *irregular = new Irregular(lmp);
+    irregular->migrate_atoms(1);
+    delete irregular;
+    if (domain->triclinic) domain->lamda2x(atom->nlocal);
+  }
+
+  // shrink-wrap the box if necessary and move atoms to new procs
+  // if atoms are lost is b/c data file box was far from shrink-wrapped
+  // do not use irregular() comm, which would not lose atoms,
+  //   b/c then user could specify data file box as far too big and empty
+  // do comm->init() but not comm->setup() b/c pair/neigh cutoffs not yet set
+  // need call to map_set() b/c comm->exchange clears atom map
+
+  if (domain->nonperiodic == 2) {
+    if (domain->triclinic) domain->x2lamda(atom->nlocal);
+    domain->reset_box();
+    comm->init();
+    comm->exchange();
+    if (atom->map_style) atom->map_set();
+    if (domain->triclinic) domain->lamda2x(atom->nlocal);
+
+    bigint natoms;
+    bigint nblocal = atom->nlocal;
+    MPI_Allreduce(&nblocal,&natoms,1,MPI_LMP_BIGINT,MPI_SUM,world);
+    if (natoms != atom->natoms)
+      error->all(FLERR,
+                 "Read_data shrink wrap did not assign all atoms correctly");
+  }
+
+  // restore old styles, when reading with nocoeff flag given
+  if (coeffflag == 0) {
+    if (force->pair) delete force->pair;
+    force->pair = saved_pair;
+
+    if (force->bond) delete force->bond;
+    force->bond = saved_bond;
+
+    if (force->angle) delete force->angle;
+    force->angle = saved_angle;
+
+    if (force->dihedral) delete force->dihedral;
+    force->dihedral = saved_dihedral;
+
+    if (force->improper) delete force->improper;
+    force->improper = saved_improper;
+
+    force->kspace = saved_kspace;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read free-format header of data file
+   1st line and blank lines are skipped
+   non-blank lines are checked for header keywords and leading value is read
+   header ends with EOF or non-blank line containing no header keyword
+     if EOF, line is set to blank line
+     else line has first keyword line for rest of file
+   some logic differs if adding atoms
+------------------------------------------------------------------------- */
+
+void ReadData::header(int firstpass)
+{
+  int n;
+  char *ptr;
+
+  // customize for new sections
+
+  const char *section_keywords[NSECTIONS] =
+    {"Atoms","Velocities","Ellipsoids","Lines","Triangles","Bodies",
+     "Bonds","Angles","Dihedrals","Impropers",
+     "Masses","Pair Coeffs","PairIJ Coeffs","Bond Coeffs","Angle Coeffs",
+     "Dihedral Coeffs","Improper Coeffs",
+     "BondBond Coeffs","BondAngle Coeffs","MiddleBondTorsion Coeffs",
+     "EndBondTorsion Coeffs","AngleTorsion Coeffs",
+     "AngleAngleTorsion Coeffs","BondBond13 Coeffs","AngleAngle Coeffs"};
+
+  // skip 1st line of file
+
+  if (me == 0) {
+    char *eof = fgets(line,MAXLINE,fp);
+    if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
+  }
+
+  while (1) {
+
+    // read a line and bcast length
+
+    if (me == 0) {
+      if (fgets(line,MAXLINE,fp) == NULL) n = 0;
+      else n = strlen(line) + 1;
+    }
+    MPI_Bcast(&n,1,MPI_INT,0,world);
+
+    // if n = 0 then end-of-file so return with blank line
+
+    if (n == 0) {
+      line[0] = '\0';
+      return;
+    }
+
+    MPI_Bcast(line,n,MPI_CHAR,0,world);
+
+    // trim anything from '#' onward
+    // if line is blank, continue
+
+    if ((ptr = strchr(line,'#'))) *ptr = '\0';
+    if (strspn(line," \t\n\r") == strlen(line)) continue;
+
+    // allow special fixes first chance to match and process the line
+    // if fix matches, continue to next header line
+
+    if (nfix) {
+      for (n = 0; n < nfix; n++) {
+        if (!fix_header[n]) continue;
+        if (strstr(line,fix_header[n])) {
+          modify->fix[fix_index[n]]->read_data_header(line);
+          break;
+        }
+      }
+      if (n < nfix) continue;
+    }
+
+    // search line for header keyword and set corresponding variable
+    // customize for new header lines
+
+    if (strstr(line,"atoms")) {
+      sscanf(line,BIGINT_FORMAT,&natoms);
+      if (addflag == NONE) atom->natoms = natoms;
+      else if (firstpass) atom->natoms += natoms;
+
+    // check for these first
+    // otherwise "triangles" will be matched as "angles"
+
+    } else if (strstr(line,"ellipsoids")) {
+      if (!avec_ellipsoid)
+        error->all(FLERR,"No ellipsoids allowed with this atom style");
+      sscanf(line,BIGINT_FORMAT,&nellipsoids);
+    } else if (strstr(line,"lines")) {
+      if (!avec_line)
+        error->all(FLERR,"No lines allowed with this atom style");
+      sscanf(line,BIGINT_FORMAT,&nlines);
+    } else if (strstr(line,"triangles")) {
+      if (!avec_tri)
+        error->all(FLERR,"No triangles allowed with this atom style");
+      sscanf(line,BIGINT_FORMAT,&ntris);
+    } else if (strstr(line,"bodies")) {
+      if (!avec_body)
+        error->all(FLERR,"No bodies allowed with this atom style");
+      sscanf(line,BIGINT_FORMAT,&nbodies);
+
+    } else if (strstr(line,"bonds")) {
+      sscanf(line,BIGINT_FORMAT,&nbonds);
+      if (addflag == NONE) atom->nbonds = nbonds;
+      else if (firstpass) atom->nbonds += nbonds;
+    } else if (strstr(line,"angles")) {
+      sscanf(line,BIGINT_FORMAT,&nangles);
+      if (addflag == NONE) atom->nangles = nangles;
+      else if (firstpass) atom->nangles += nangles;
+    } else if (strstr(line,"dihedrals")) {
+      sscanf(line,BIGINT_FORMAT,&ndihedrals);
+      if (addflag == NONE) atom->ndihedrals = ndihedrals;
+      else if (firstpass) atom->ndihedrals += ndihedrals;
+    } else if (strstr(line,"impropers")) {
+      sscanf(line,BIGINT_FORMAT,&nimpropers);
+      if (addflag == NONE) atom->nimpropers = nimpropers;
+      else if (firstpass) atom->nimpropers += nimpropers;
+
+    // Atom class type settings are only set by first data file
+
+    } else if (strstr(line,"atom types")) {
+      sscanf(line,"%d",&ntypes);
+      if (addflag == NONE) atom->ntypes = ntypes + extra_atom_types;
+    } else if (strstr(line,"mol_H types")){
+        sscanf(line,"%d",&atom->nmoltypesH);
+    }
+    else if (strstr(line,"bond types")) {
+      sscanf(line,"%d",&nbondtypes);
+      if (addflag == NONE) atom->nbondtypes = nbondtypes + extra_bond_types;
+    } else if (strstr(line,"angle types")) {
+      sscanf(line,"%d",&nangletypes);
+      if (addflag == NONE) atom->nangletypes = nangletypes + extra_angle_types;
+    } else if (strstr(line,"dihedral types")) {
+      sscanf(line,"%d",&ndihedraltypes);
+      if (addflag == NONE)
+        atom->ndihedraltypes = ndihedraltypes + extra_dihedral_types;
+    } else if (strstr(line,"improper types")) {
+      sscanf(line,"%d",&nimpropertypes);
+      if (addflag == NONE)
+        atom->nimpropertypes = nimpropertypes + extra_improper_types;
+
+    // these settings only used by first data file
+
+    } else if (strstr(line,"extra bond per atom")) {
+      if (addflag == NONE) sscanf(line,"%d",&atom->extra_bond_per_atom);
+    } else if (strstr(line,"extra angle per atom")) {
+      if (addflag == NONE) sscanf(line,"%d",&atom->extra_angle_per_atom);
+    } else if (strstr(line,"extra dihedral per atom")) {
+      if (addflag == NONE) sscanf(line,"%d",&atom->extra_dihedral_per_atom);
+    } else if (strstr(line,"extra improper per atom")) {
+      if (addflag == NONE) sscanf(line,"%d",&atom->extra_improper_per_atom);
+    } else if (strstr(line,"extra special per atom")) {
+      if (addflag == NONE) sscanf(line,"%d",&force->special_extra);
+
+    // local copy of box info
+    // so can treat differently for first vs subsequent data files
+
+    } else if (strstr(line,"xlo xhi")) {
+      sscanf(line,"%lg %lg",&boxlo[0],&boxhi[0]);
+    } else if (strstr(line,"ylo yhi")) {
+      sscanf(line,"%lg %lg",&boxlo[1],&boxhi[1]);
+    } else if (strstr(line,"zlo zhi")) {
+      sscanf(line,"%lg %lg",&boxlo[2],&boxhi[2]);
+    } else if (strstr(line,"xy xz yz")) {
+      triclinic = 1;
+      sscanf(line,"%lg %lg %lg",&xy,&xz,&yz);
+
+    } else break;
+  }
+
+  // error check on total system size
+
+  if (atom->natoms < 0 || atom->natoms >= MAXBIGINT ||
+      atom->nbonds < 0 || atom->nbonds >= MAXBIGINT ||
+      atom->nangles < 0 || atom->nangles >= MAXBIGINT ||
+      atom->ndihedrals < 0 || atom->ndihedrals >= MAXBIGINT ||
+      atom->nimpropers < 0 || atom->nimpropers >= MAXBIGINT)
+    error->all(FLERR,"System in data file is too big");
+
+  // check that exiting string is a valid section keyword
+
+  parse_keyword(1);
+  for (n = 0; n < NSECTIONS; n++)
+    if (strcmp(keyword,section_keywords[n]) == 0) break;
+  if (n == NSECTIONS) {
+    char str[128];
+    sprintf(str,"Unknown identifier in data file: %s",keyword);
+    error->all(FLERR,str);
+  }
+
+  // error checks on header values
+  // must be consistent with atom style and other header values
+
+  if ((atom->nbonds || atom->nbondtypes) &&
+      atom->avec->bonds_allow == 0)
+    error->all(FLERR,"No bonds allowed with this atom style");
+  if ((atom->nangles || atom->nangletypes) &&
+      atom->avec->angles_allow == 0)
+    error->all(FLERR,"No angles allowed with this atom style");
+  if ((atom->ndihedrals || atom->ndihedraltypes) &&
+      atom->avec->dihedrals_allow == 0)
+    error->all(FLERR,"No dihedrals allowed with this atom style");
+  if ((atom->nimpropers || atom->nimpropertypes) &&
+      atom->avec->impropers_allow == 0)
+    error->all(FLERR,"No impropers allowed with this atom style");
+
+  if (atom->nbonds > 0 && atom->nbondtypes <= 0)
+    error->all(FLERR,"Bonds defined but no bond types");
+  if (atom->nangles > 0 && atom->nangletypes <= 0)
+    error->all(FLERR,"Angles defined but no angle types");
+  if (atom->ndihedrals > 0 && atom->ndihedraltypes <= 0)
+    error->all(FLERR,"Dihedrals defined but no dihedral types");
+  if (atom->nimpropers > 0 && atom->nimpropertypes <= 0)
+    error->all(FLERR,"Impropers defined but no improper types");
+
+  if (atom->molecular == 2) {
+    if (atom->nbonds || atom->nangles || atom->ndihedrals || atom->nimpropers)
+      error->all(FLERR,"No molecule topology allowed with atom style template");
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read all atoms
+------------------------------------------------------------------------- */
+
+void ReadData::atoms()
+{
+  int nchunk,eof;
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  reading atoms ...\n");
+    if (logfile) fprintf(logfile,"  reading atoms ...\n");
+  }
+
+  bigint nread = 0;
+
+  while (nread < natoms) {
+    nchunk = MIN(natoms-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    atom->data_atoms(nchunk,buffer,id_offset,toffset,shiftflag,shift);
+    nread += nchunk;
+  }
+
+  // check that all atoms were assigned correctly
+
+  bigint n = atom->nlocal;
+  bigint sum;
+  MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
+  bigint nassign = sum - (atom->natoms - natoms);
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " atoms\n",nassign);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " atoms\n",nassign);
+  }
+
+  if (sum != atom->natoms)
+    error->all(FLERR,"Did not assign all atoms correctly");
+
+  // check that atom IDs are valid
+
+  atom->tag_check();
+
+  // create global mapping of atoms
+
+  if (atom->map_style) {
+    atom->map_init();
+    atom->map_set();
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read all velocities
+   to find atoms, must build atom map if not a molecular system
+------------------------------------------------------------------------- */
+
+void ReadData::velocities()
+{
+  int nchunk,eof;
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  reading velocities ...\n");
+    if (logfile) fprintf(logfile,"  reading velocities ...\n");
+  }
+
+  int mapflag = 0;
+  if (atom->map_style == 0) {
+    mapflag = 1;
+    atom->map_init();
+    atom->map_set();
+  }
+
+  bigint nread = 0;
+
+  while (nread < natoms) {
+    nchunk = MIN(natoms-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    atom->data_vels(nchunk,buffer,id_offset);
+    nread += nchunk;
+  }
+
+  if (mapflag) {
+    atom->map_delete();
+    atom->map_style = 0;
+  }
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " velocities\n",natoms);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " velocities\n",natoms);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   scan or read all bonds
+------------------------------------------------------------------------- */
+
+void ReadData::bonds(int firstpass)
+{
+  int nchunk,eof;
+
+  if (me == 0) {
+    if (firstpass) {
+      if (screen) fprintf(screen,"  scanning bonds ...\n");
+      if (logfile) fprintf(logfile,"  scanning bonds ...\n");
+    } else {
+      if (screen) fprintf(screen,"  reading bonds ...\n");
+      if (logfile) fprintf(logfile,"  reading bonds ...\n");
+    }
+  }
+
+  // allocate count if firstpass
+
+  int nlocal = atom->nlocal;
+  int *count = NULL;
+  if (firstpass) {
+    memory->create(count,nlocal,"read_data:count");
+    for (int i = 0; i < nlocal; i++) count[i] = 0;
+  }
+
+  // read and process bonds
+
+  bigint nread = 0;
+
+  while (nread < nbonds) {
+    nchunk = MIN(nbonds-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    atom->data_bonds(nchunk,buffer,count,id_offset,boffset);
+    nread += nchunk;
+  }
+
+  // if firstpass: tally max bond/atom and return
+  // if addflag = NONE, store max bond/atom with extra
+  // else just check actual max does not exceed existing max
+
+  if (firstpass) {
+    int max = 0;
+    for (int i = nlocal_previous; i < nlocal; i++) max = MAX(max,count[i]);
+    int maxall;
+    MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
+    if (addflag == NONE) maxall += atom->extra_bond_per_atom;
+
+    if (me == 0) {
+      if (screen) fprintf(screen,"  %d = max bonds/atom\n",maxall);
+      if (logfile) fprintf(logfile,"  %d = max bonds/atom\n",maxall);
+    }
+
+    if (addflag != NONE) {
+      if (maxall > atom->bond_per_atom)
+        error->all(FLERR,"Subsequent read data induced "
+                   "too many bonds per atom");
+    } else atom->bond_per_atom = maxall;
+
+    memory->destroy(count);
+    return;
+  }
+
+  // if 2nd pass: check that bonds were assigned correctly
+
+  bigint n = 0;
+  for (int i = nlocal_previous; i < nlocal; i++) n += atom->num_bond[i];
+  bigint sum;
+  MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
+  int factor = 1;
+  if (!force->newton_bond) factor = 2;
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " bonds\n",sum/factor);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " bonds\n",sum/factor);
+  }
+
+  if (sum != factor*nbonds)
+    error->all(FLERR,"Bonds assigned incorrectly");
+}
+
+/* ----------------------------------------------------------------------
+   scan or read all angles
+------------------------------------------------------------------------- */
+
+void ReadData::angles(int firstpass)
+{
+  int nchunk,eof;
+
+  if (me == 0) {
+    if (firstpass) {
+      if (screen) fprintf(screen,"  scanning angles ...\n");
+      if (logfile) fprintf(logfile,"  scanning angles ...\n");
+    } else {
+      if (screen) fprintf(screen,"  reading angles ...\n");
+      if (logfile) fprintf(logfile,"  reading angles ...\n");
+    }
+  }
+
+  // allocate count if firstpass
+
+  int nlocal = atom->nlocal;
+  int *count = NULL;
+  if (firstpass) {
+    memory->create(count,nlocal,"read_data:count");
+    for (int i = 0; i < nlocal; i++) count[i] = 0;
+  }
+
+  // read and process angles
+
+  bigint nread = 0;
+
+  while (nread < nangles) {
+    nchunk = MIN(nangles-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    atom->data_angles(nchunk,buffer,count,id_offset,aoffset);
+    nread += nchunk;
+  }
+
+  // if firstpass: tally max angle/atom and return
+  // if addflag = NONE, store max angle/atom with extra
+  // else just check actual max does not exceed existing max
+
+  if (firstpass) {
+    int max = 0;
+    for (int i = nlocal_previous; i < nlocal; i++) max = MAX(max,count[i]);
+    int maxall;
+    MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
+    if (addflag == NONE) maxall += atom->extra_angle_per_atom;
+
+    if (me == 0) {
+      if (screen) fprintf(screen,"  %d = max angles/atom\n",maxall);
+      if (logfile) fprintf(logfile,"  %d = max angles/atom\n",maxall);
+    }
+
+    if (addflag != NONE) {
+      if (maxall > atom->angle_per_atom)
+        error->all(FLERR,"Subsequent read data induced "
+                   "too many angles per atom");
+    } else atom->angle_per_atom = maxall;
+
+    memory->destroy(count);
+    return;
+  }
+
+  // if 2nd pass: check that angles were assigned correctly
+
+  bigint n = 0;
+  for (int i = nlocal_previous; i < nlocal; i++) n += atom->num_angle[i];
+  bigint sum;
+  MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
+  int factor = 1;
+  if (!force->newton_bond) factor = 3;
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " angles\n",sum/factor);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " angles\n",sum/factor);
+  }
+
+  if (sum != factor*nangles)
+    error->all(FLERR,"Angles assigned incorrectly");
+}
+
+/* ----------------------------------------------------------------------
+   scan or read all dihedrals
+------------------------------------------------------------------------- */
+
+void ReadData::dihedrals(int firstpass)
+{
+  int nchunk,eof;
+
+  if (me == 0) {
+    if (firstpass) {
+      if (screen) fprintf(screen,"  scanning dihedrals ...\n");
+      if (logfile) fprintf(logfile,"  scanning dihedrals ...\n");
+    } else {
+      if (screen) fprintf(screen,"  reading dihedrals ...\n");
+      if (logfile) fprintf(logfile,"  reading dihedrals ...\n");
+    }
+  }
+
+  // allocate count if firstpass
+
+  int nlocal = atom->nlocal;
+  int *count = NULL;
+  if (firstpass) {
+    memory->create(count,nlocal,"read_data:count");
+    for (int i = 0; i < nlocal; i++) count[i] = 0;
+  }
+
+  // read and process dihedrals
+
+  bigint nread = 0;
+
+  while (nread < ndihedrals) {
+    nchunk = MIN(ndihedrals-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    atom->data_dihedrals(nchunk,buffer,count,id_offset,doffset);
+    nread += nchunk;
+  }
+
+  // if firstpass: tally max dihedral/atom and return
+  // if addflag = NONE, store max dihedral/atom with extra
+  // else just check actual max does not exceed existing max
+
+  if (firstpass) {
+    int max = 0;
+    for (int i = 0; i < nlocal; i++) max = MAX(max,count[i]);
+    int maxall;
+    MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
+    if (addflag == NONE) maxall += atom->extra_dihedral_per_atom;
+
+    if (me == 0) {
+      if (screen) fprintf(screen,"  %d = max dihedrals/atom\n",maxall);
+      if (logfile) fprintf(logfile,"  %d = max dihedrals/atom\n",maxall);
+    }
+
+    if (addflag != NONE) {
+      if (maxall > atom->dihedral_per_atom)
+        error->all(FLERR,"Subsequent read data induced "
+                   "too many dihedrals per atom");
+    } else atom->dihedral_per_atom = maxall;
+
+    memory->destroy(count);
+    return;
+  }
+
+  // if 2nd pass: check that dihedrals were assigned correctly
+
+  bigint n = 0;
+  for (int i = nlocal_previous; i < nlocal; i++) n += atom->num_dihedral[i];
+  bigint sum;
+  MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
+  int factor = 1;
+  if (!force->newton_bond) factor = 4;
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " dihedrals\n",sum/factor);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " dihedrals\n",sum/factor);
+  }
+
+  if (sum != factor*ndihedrals)
+    error->all(FLERR,"Dihedrals assigned incorrectly");
+}
+
+/* ----------------------------------------------------------------------
+   scan or read all impropers
+------------------------------------------------------------------------- */
+
+void ReadData::impropers(int firstpass)
+{
+  int nchunk,eof;
+
+  if (me == 0) {
+    if (firstpass) {
+      if (screen) fprintf(screen,"  scanning impropers ...\n");
+      if (logfile) fprintf(logfile,"  scanning impropers ...\n");
+    } else {
+      if (screen) fprintf(screen,"  reading impropers ...\n");
+      if (logfile) fprintf(logfile,"  reading impropers ...\n");
+    }
+  }
+
+  // allocate count if firstpass
+
+  int nlocal = atom->nlocal;
+  int *count = NULL;
+  if (firstpass) {
+    memory->create(count,nlocal,"read_data:count");
+    for (int i = 0; i < nlocal; i++) count[i] = 0;
+  }
+
+  // read and process impropers
+
+  bigint nread = 0;
+
+  while (nread < nimpropers) {
+    nchunk = MIN(nimpropers-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    atom->data_impropers(nchunk,buffer,count,id_offset,ioffset);
+    nread += nchunk;
+  }
+
+  // if firstpass: tally max improper/atom and return
+  // if addflag = NONE, store max improper/atom
+  // else just check it does not exceed existing max
+
+  if (firstpass) {
+    int max = 0;
+    for (int i = nlocal_previous; i < nlocal; i++) max = MAX(max,count[i]);
+    int maxall;
+    MPI_Allreduce(&max,&maxall,1,MPI_INT,MPI_MAX,world);
+    if (addflag == NONE) maxall += atom->extra_improper_per_atom;
+
+    if (me == 0) {
+      if (screen) fprintf(screen,"  %d = max impropers/atom\n",maxall);
+      if (logfile) fprintf(logfile,"  %d = max impropers/atom\n",maxall);
+    }
+
+    if (addflag != NONE) {
+      if (maxall > atom->improper_per_atom)
+        error->all(FLERR,"Subsequent read data induced "
+                   "too many impropers per atom");
+    } else atom->improper_per_atom = maxall;
+
+    memory->destroy(count);
+    return;
+  }
+
+  // if 2nd pass: check that impropers were assigned correctly
+
+  bigint n = 0;
+  for (int i = nlocal_previous; i < nlocal; i++) n += atom->num_improper[i];
+  bigint sum;
+  MPI_Allreduce(&n,&sum,1,MPI_LMP_BIGINT,MPI_SUM,world);
+  int factor = 1;
+  if (!force->newton_bond) factor = 4;
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " impropers\n",sum/factor);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " impropers\n",sum/factor);
+  }
+
+  if (sum != factor*nimpropers)
+    error->all(FLERR,"Impropers assigned incorrectly");
+}
+
+/* ----------------------------------------------------------------------
+   read all bonus data
+   to find atoms, must build atom map if not a molecular system
+------------------------------------------------------------------------- */
+
+void ReadData::bonus(bigint nbonus, AtomVec *ptr, const char *type)
+{
+  int nchunk,eof;
+
+  int mapflag = 0;
+  if (atom->map_style == 0) {
+    mapflag = 1;
+    atom->map_init();
+    atom->map_set();
+  }
+
+  bigint nread = 0;
+  bigint natoms = nbonus;
+
+  while (nread < natoms) {
+    nchunk = MIN(natoms-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    atom->data_bonus(nchunk,buffer,ptr,id_offset);
+    nread += nchunk;
+  }
+
+  if (mapflag) {
+    atom->map_delete();
+    atom->map_style = 0;
+  }
+
+  if (me == 0) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " %s\n",natoms,type);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " %s\n",natoms,type);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   read all body data
+   variable amount of info per body, described by ninteger and ndouble
+   to find atoms, must build atom map if not a molecular system
+   if not firstpass, just read past data, but no processing of data
+------------------------------------------------------------------------- */
+
+void ReadData::bodies(int firstpass)
+{
+  int m,nchunk,nline,nmax,ninteger,ndouble,nword,ncount,onebody,tmp;
+  char *eof;
+
+  int mapflag = 0;
+  if (atom->map_style == 0 && firstpass) {
+    mapflag = 1;
+    atom->map_init();
+    atom->map_set();
+  }
+
+  // nmax = max # of bodies to read in this chunk
+  // nchunk = actual # read
+
+  bigint nread = 0;
+  bigint natoms = nbodies;
+
+  while (nread < natoms) {
+    if (natoms-nread > CHUNK) nmax = CHUNK;
+    else nmax = natoms-nread;
+
+    if (me == 0) {
+      nchunk = 0;
+      nline = 0;
+      m = 0;
+
+      while (nchunk < nmax && nline <= CHUNK-MAXBODY) {
+        eof = fgets(&buffer[m],MAXLINE,fp);
+        if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
+        sscanf(&buffer[m],"%d %d %d",&tmp,&ninteger,&ndouble);
+        m += strlen(&buffer[m]);
+
+        // read lines one at a time into buffer and count words
+        // count to ninteger and ndouble until have enough lines
+
+        onebody = 0;
+
+        nword = 0;
+        while (nword < ninteger) {
+          eof = fgets(&buffer[m],MAXLINE,fp);
+          if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
+          ncount = atom->count_words(&buffer[m],copy);
+	  if (ncount == 0)
+	    error->one(FLERR,"Too few values in body lines in data file");
+	  nword += ncount;
+          m += strlen(&buffer[m]);
+          onebody++;
+        }
+        if (nword > ninteger) 
+          error->one(FLERR,"Too many values in body lines in data file");
+
+        nword = 0;
+        while (nword < ndouble) {
+          eof = fgets(&buffer[m],MAXLINE,fp);
+          if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
+          ncount = atom->count_words(&buffer[m],copy);
+	  if (ncount == 0)
+	    error->one(FLERR,"Too few values in body lines in data file");
+	  nword += ncount;
+          m += strlen(&buffer[m]);
+          onebody++;
+        }
+        if (nword > ndouble) 
+          error->one(FLERR,"Too many values in body lines in data file");
+
+        if (onebody+1 > MAXBODY)
+          error->one(FLERR,
+                     "Too many lines in one body in data file - boost MAXBODY");
+
+        nchunk++;
+        nline += onebody+1;
+      }
+
+      if (buffer[m-1] != '\n') strcpy(&buffer[m++],"\n");
+      m++;
+    }
+
+    MPI_Bcast(&nchunk,1,MPI_INT,0,world);
+    MPI_Bcast(&m,1,MPI_INT,0,world);
+    MPI_Bcast(buffer,m,MPI_CHAR,0,world);
+
+    if (firstpass) atom->data_bodies(nchunk,buffer,avec_body,id_offset);
+    nread += nchunk;
+  }
+
+  if (mapflag && firstpass) {
+    atom->map_delete();
+    atom->map_style = 0;
+  }
+
+  if (me == 0 && firstpass) {
+    if (screen) fprintf(screen,"  " BIGINT_FORMAT " bodies\n",natoms);
+    if (logfile) fprintf(logfile,"  " BIGINT_FORMAT " bodies\n",natoms);
+  }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::mass()
+{
+  char *next;
+  char *buf = new char[ntypes*MAXLINE];
+
+  int eof = comm->read_lines_from_file(fp,ntypes,MAXLINE,buf);
+  if (eof) error->all(FLERR,"Unexpected end of data file");
+
+  char *original = buf;
+  for (int i = 0; i < ntypes; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    atom->set_mass(buf,toffset);
+    buf = next + 1;
+  }
+  delete [] original;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::paircoeffs()
+{
+  char *next;
+  char *buf = new char[ntypes*MAXLINE];
+
+  int eof = comm->read_lines_from_file(fp,ntypes,MAXLINE,buf);
+  if (eof) error->all(FLERR,"Unexpected end of data file");
+
+  char *original = buf;
+  for (int i = 0; i < ntypes; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    parse_coeffs(buf,NULL,1,2,toffset);
+    if (narg == 0) error->all(FLERR,"Unexpected end of PairCoeffs section");
+    force->pair->coeff(narg,arg);
+    buf = next + 1;
+  }
+  delete [] original;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::pairIJcoeffs()
+{
+  int i,j;
+  char *next;
+
+  int nsq = ntypes * (ntypes+1) / 2;
+  char *buf = new char[nsq * MAXLINE];
+
+  int eof = comm->read_lines_from_file(fp,nsq,MAXLINE,buf);
+  if (eof) error->all(FLERR,"Unexpected end of data file");
+
+  char *original = buf;
+  for (i = 0; i < ntypes; i++)
+    for (j = i; j < ntypes; j++) {
+      next = strchr(buf,'\n');
+      *next = '\0';
+      parse_coeffs(buf,NULL,0,2,toffset);
+      if (narg == 0) error->all(FLERR,"Unexpected end of PairCoeffs section");
+      force->pair->coeff(narg,arg);
+      buf = next + 1;
+    }
+  delete [] original;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::bondcoeffs()
+{
+  char *next;
+  char *buf = new char[nbondtypes*MAXLINE];
+
+  int eof = comm->read_lines_from_file(fp,nbondtypes,MAXLINE,buf);
+  if (eof) error->all(FLERR,"Unexpected end of data file");
+
+  char *original = buf;
+  for (int i = 0; i < nbondtypes; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    parse_coeffs(buf,NULL,0,1,boffset);
+    if (narg == 0) error->all(FLERR,"Unexpected end of BondCoeffs section");
+    force->bond->coeff(narg,arg);
+    buf = next + 1;
+  }
+  delete [] original;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::anglecoeffs(int which)
+{
+  char *next;
+  char *buf = new char[nangletypes*MAXLINE];
+
+  int eof = comm->read_lines_from_file(fp,nangletypes,MAXLINE,buf);
+  if (eof) error->all(FLERR,"Unexpected end of data file");
+
+  char *original = buf;
+  for (int i = 0; i < nangletypes; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    if (which == 0) parse_coeffs(buf,NULL,0,1,aoffset);
+    else if (which == 1) parse_coeffs(buf,"bb",0,1,aoffset);
+    else if (which == 2) parse_coeffs(buf,"ba",0,1,aoffset);
+    if (narg == 0) error->all(FLERR,"Unexpected end of AngleCoeffs section");
+    force->angle->coeff(narg,arg);
+    buf = next + 1;
+  }
+  delete [] original;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::dihedralcoeffs(int which)
+{
+  char *next;
+  char *buf = new char[ndihedraltypes*MAXLINE];
+
+  int eof = comm->read_lines_from_file(fp,ndihedraltypes,MAXLINE,buf);
+  if (eof) error->all(FLERR,"Unexpected end of data file");
+
+  char *original = buf;
+  for (int i = 0; i < ndihedraltypes; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    if (which == 0) parse_coeffs(buf,NULL,0,1,doffset);
+    else if (which == 1) parse_coeffs(buf,"mbt",0,1,doffset);
+    else if (which == 2) parse_coeffs(buf,"ebt",0,1,doffset);
+    else if (which == 3) parse_coeffs(buf,"at",0,1,doffset);
+    else if (which == 4) parse_coeffs(buf,"aat",0,1,doffset);
+    else if (which == 5) parse_coeffs(buf,"bb13",0,1,doffset);
+    if (narg == 0) error->all(FLERR,"Unexpected end of DihedralCoeffs section");
+    force->dihedral->coeff(narg,arg);
+    buf = next + 1;
+  }
+  delete [] original;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void ReadData::impropercoeffs(int which)
+{
+  char *next;
+  char *buf = new char[nimpropertypes*MAXLINE];
+
+  int eof = comm->read_lines_from_file(fp,nimpropertypes,MAXLINE,buf);
+  if (eof) error->all(FLERR,"Unexpected end of data file");
+
+  char *original = buf;
+  for (int i = 0; i < nimpropertypes; i++) {
+    next = strchr(buf,'\n');
+    *next = '\0';
+    if (which == 0) parse_coeffs(buf,NULL,0,1,ioffset);
+    else if (which == 1) parse_coeffs(buf,"aa",0,1,ioffset);
+    if (narg == 0) error->all(FLERR,"Unexpected end of ImproperCoeffs section");
+    force->improper->coeff(narg,arg);
+    buf = next + 1;
+  }
+  delete [] original;
+}
+
+/* ----------------------------------------------------------------------
+   read fix section, pass lines to fix to process
+   n = index of fix
+------------------------------------------------------------------------- */
+
+void ReadData::fix(int ifix, char *keyword)
+{
+  int nchunk,eof;
+
+  bigint nline = modify->fix[ifix]->read_data_skip_lines(keyword);
+
+  bigint nread = 0;
+  while (nread < nline) {
+    nchunk = MIN(nline-nread,CHUNK);
+    eof = comm->read_lines_from_file(fp,nchunk,MAXLINE,buffer);
+    if (eof) error->all(FLERR,"Unexpected end of data file");
+    modify->fix[ifix]->read_data_section(keyword,nchunk,buffer,id_offset);
+    nread += nchunk;
+  }
+}
+
+/* ----------------------------------------------------------------------
+   reallocate the count vector from cmax to amax+1 and return new length
+   zero new locations
+------------------------------------------------------------------------- */
+
+int ReadData::reallocate(int **pcount, int cmax, int amax)
+{
+  int *count = *pcount;
+  memory->grow(count,amax+1,"read_data:count");
+  for (int i = cmax; i <= amax; i++) count[i] = 0;
+  *pcount = count;
+  return amax+1;
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 opens data file
+   test if gzipped
+------------------------------------------------------------------------- */
+
+void ReadData::open(char *file)
+{
+  compressed = 0;
+  char *suffix = file + strlen(file) - 3;
+  if (suffix > file && strcmp(suffix,".gz") == 0) compressed = 1;
+  if (!compressed) fp = fopen(file,"r");
+  else {
+#ifdef LAMMPS_GZIP
+    char gunzip[128];
+    sprintf(gunzip,"gzip -c -d %s",file);
+
+#ifdef _WIN32
+    fp = _popen(gunzip,"rb");
+#else
+    fp = popen(gunzip,"r");
+#endif
+
+#else
+    error->one(FLERR,"Cannot open gzipped file");
+#endif
+  }
+
+  if (fp == NULL) {
+    char str[128];
+    sprintf(str,"Cannot open file %s",file);
+    error->one(FLERR,str);
+  }
+}
+
+/* ----------------------------------------------------------------------
+   grab next keyword
+   read lines until one is non-blank
+   keyword is all text on line w/out leading & trailing white space
+   optional style can be appended after comment char '#'
+   read one additional line (assumed blank)
+   if any read hits EOF, set keyword to empty
+   if first = 1, line variable holds non-blank line that ended header
+------------------------------------------------------------------------- */
+
+void ReadData::parse_keyword(int first)
+{
+  int eof = 0;
+  int done = 0;
+
+  // proc 0 reads upto non-blank line plus 1 following line
+  // eof is set to 1 if any read hits end-of-file
+
+  if (me == 0) {
+    if (!first) {
+      if (fgets(line,MAXLINE,fp) == NULL) eof = 1;
+    }
+    while (eof == 0 && done == 0) {
+      int blank = strspn(line," \t\n\r");
+      if ((blank == strlen(line)) || (line[blank] == '#')) {
+        if (fgets(line,MAXLINE,fp) == NULL) eof = 1;
+      } else done = 1;
+    }
+    if (fgets(buffer,MAXLINE,fp) == NULL) {
+      eof = 1;
+      buffer[0] = '\0';
+    }
+  }
+
+  // if eof, set keyword empty and return
+
+  MPI_Bcast(&eof,1,MPI_INT,0,world);
+  if (eof) {
+    keyword[0] = '\0';
+    return;
+  }
+
+  // bcast keyword line to all procs
+
+  int n;
+  if (me == 0) n = strlen(line) + 1;
+  MPI_Bcast(&n,1,MPI_INT,0,world);
+  MPI_Bcast(line,n,MPI_CHAR,0,world);
+
+  // store optional "style" following comment char '#' after keyword
+
+  char *ptr;
+  if ((ptr = strchr(line,'#'))) {
+    *ptr++ = '\0';
+    while (*ptr == ' ' || *ptr == '\t') ptr++;
+    int stop = strlen(ptr) - 1;
+    while (ptr[stop] == ' ' || ptr[stop] == '\t'
+           || ptr[stop] == '\n' || ptr[stop] == '\r') stop--;
+    ptr[stop+1] = '\0';
+    strcpy(style,ptr);
+  } else style[0] = '\0';
+
+  // copy non-whitespace portion of line into keyword
+
+  int start = strspn(line," \t\n\r");
+  int stop = strlen(line) - 1;
+  while (line[stop] == ' ' || line[stop] == '\t'
+         || line[stop] == '\n' || line[stop] == '\r') stop--;
+  line[stop+1] = '\0';
+  strcpy(keyword,&line[start]);
+}
+
+/* ----------------------------------------------------------------------
+   proc 0 reads N lines from file
+   could be skipping Natoms lines, so use bigints
+------------------------------------------------------------------------- */
+
+void ReadData::skip_lines(bigint n)
+{
+  if (me) return;
+  if (n <= 0) return;
+  char *eof = NULL;
+  for (bigint i = 0; i < n; i++) eof = fgets(line,MAXLINE,fp);
+  if (eof == NULL) error->one(FLERR,"Unexpected end of data file");
+}
+
+/* ----------------------------------------------------------------------
+   parse a line of coeffs into words, storing them in narg,arg
+   trim anything from '#' onward
+   word strings remain in line, are not copied
+   if addstr != NULL, add addstr as extra arg for class2 angle/dihedral/improper
+     if 2nd word starts with letter, then is hybrid style, add addstr after it
+     else add addstr before 2nd word
+   if dupflag, duplicate 1st word, so pair_coeff "2" becomes "2 2"
+   if noffset, add offset to first noffset args, which are atom/bond/etc types
+------------------------------------------------------------------------- */
+
+void ReadData::parse_coeffs(char *line, const char *addstr,
+                            int dupflag, int noffset, int offset)
+{
+  char *ptr;
+  if ((ptr = strchr(line,'#'))) *ptr = '\0';
+
+  narg = 0;
+  char *word = strtok(line," \t\n\r\f");
+  while (word) {
+    if (narg == maxarg) {
+      maxarg += DELTA;
+      arg = (char **)
+        memory->srealloc(arg,maxarg*sizeof(char *),"read_data:arg");
+    }
+    if (addstr && narg == 1 && !islower(word[0])) arg[narg++] = (char *) addstr;
+    arg[narg++] = word;
+    if (addstr && narg == 2 && islower(word[0])) arg[narg++] = (char *) addstr;
+    if (dupflag && narg == 1) arg[narg++] = word;
+    word = strtok(NULL," \t\n\r\f");
+  }
+
+  if (noffset) {
+    int value = force->inumeric(FLERR,arg[0]);
+    sprintf(argoffset1,"%d",value+offset);
+    arg[0] = argoffset1;
+    if (noffset == 2) {
+      value = force->inumeric(FLERR,arg[1]);
+      sprintf(argoffset2,"%d",value+offset);
+      arg[1] = argoffset2;
+    }
+  }
+}
+
+/* ----------------------------------------------------------------------
+   compare two style strings if they both exist
+   one = comment in data file section, two = currently-defined style
+   ignore suffixes listed in suffixes array at top of file
+------------------------------------------------------------------------- */
+
+int ReadData::style_match(const char *one, const char *two)
+{
+  int i,delta,len,len1,len2;
+
+  if ((one == NULL) || (two == NULL)) return 1;
+
+  len1 = strlen(one);
+  len2 = strlen(two);
+
+  for (i = 0; suffixes[i] != NULL; i++) {
+    len = strlen(suffixes[i]);
+    if ((delta = len1 - len) > 0)
+      if (strcmp(one+delta,suffixes[i]) == 0) len1 = delta;
+    if ((delta = len2 - len) > 0)
+      if (strcmp(two+delta,suffixes[i]) == 0) len2 = delta;
+  }
+
+  if ((len1 == 0) || (len1 == len2) || (strncmp(one,two,len1) == 0)) return 1;
+  return 0;
+}
diff --git a/src/USER-HADRESS/read_data.h b/src/USER-HADRESS/read_data.h
new file mode 100644
index 000000000..5463c86f0
--- /dev/null
+++ b/src/USER-HADRESS/read_data.h
@@ -0,0 +1,560 @@
+/* -*- 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(read_data,ReadData)
+
+#else
+
+#ifndef LMP_READ_DATA_H
+#define LMP_READ_DATA_H
+
+#include <stdio.h>
+#include "pointers.h"
+
+namespace LAMMPS_NS {
+
+class ReadData : protected Pointers {
+ public:
+  ReadData(class LAMMPS *);
+  ~ReadData();
+  void command(int, char **);
+
+ private:
+  int me,compressed;
+  char *line,*copy,*keyword,*buffer,*style;
+  FILE *fp;
+  char **arg;
+  int narg,maxarg;
+  char argoffset1[8],argoffset2[8];
+
+  bigint id_offset;
+
+  int nlocal_previous;
+  bigint natoms;
+  bigint nbonds,nangles,ndihedrals,nimpropers;
+  int ntypes;
+  int nbondtypes,nangletypes,ndihedraltypes,nimpropertypes;
+
+  bigint nellipsoids;
+  class AtomVecEllipsoid *avec_ellipsoid;
+  bigint nlines;
+  class AtomVecLine *avec_line;
+  bigint ntris;
+  class AtomVecTri *avec_tri;
+  bigint nbodies;
+  class AtomVecBody *avec_body;
+
+  // box info
+
+  double boxlo[3],boxhi[3];
+  double xy,xz,yz;
+  int triclinic;
+
+  // optional args
+
+  int addflag,offsetflag,shiftflag,coeffflag;
+  tagint addvalue;
+  int toffset,boffset,aoffset,doffset,ioffset;
+  double shift[3];
+  int extra_atom_types,extra_bond_types,extra_angle_types;
+  int extra_dihedral_types,extra_improper_types;
+  int groupbit;
+
+  int nfix;
+  int *fix_index;
+  char **fix_header;
+  char **fix_section;
+
+  // methods
+
+  void open(char *);
+  void scan(int &, int &, int &, int &);
+  int reallocate(int **, int, int);
+  void header(int);
+  void parse_keyword(int);
+  void skip_lines(bigint);
+  void parse_coeffs(char *, const char *, int, int, int);
+  int style_match(const char *, const char *);
+
+  void atoms();
+  void velocities();
+
+  void bonds(int);
+  void bond_scan(int, char *, int *);
+  void angles(int);
+  void dihedrals(int);
+  void impropers(int);
+
+  void bonus(bigint, class AtomVec *, const char *);
+  void bodies(int);
+
+  void mass();
+  void paircoeffs();
+  void pairIJcoeffs();
+  void bondcoeffs();
+  void anglecoeffs(int);
+  void dihedralcoeffs(int);
+  void impropercoeffs(int);
+
+  void fix(int, char *);
+};
+
+}
+
+#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: Read data add offset is too big
+
+It cannot be larger than the size of atom IDs, e.g. the maximum 32-bit
+integer.
+
+E: Non-zero read_data shift z value for 2d simulation
+
+Self-explanatory.
+
+E: No bonds allowed with this atom style
+
+Self-explanatory.
+
+E: No angles allowed with this atom style
+
+Self-explanatory.
+
+E: No dihedrals allowed with this atom style
+
+Self-explanatory.
+
+E: No impropers allowed with this atom style
+
+Self-explanatory.
+
+E: Fix ID for read_data does not exist
+
+Self-explanatory.
+
+E: Cannot run 2d simulation with nonperiodic Z dimension
+
+Use the boundary command to make the z dimension periodic in order to
+run a 2d simulation.
+
+E: Cannot read_data without add keyword after simulation box is defined
+
+Self-explanatory.
+
+E: Cannot use read_data add before simulation box is defined
+
+Self-explanatory.
+
+E: Cannot use read_data offset without add flag
+
+Self-explanatory.
+
+E: Cannot use read_data shift without add flag
+
+Self-explanatory.
+
+E: Cannot use read_data extra with add flag
+
+Self-explanatory.
+
+W: Atom style in data file differs from currently defined atom style
+
+Self-explanatory.
+
+E: Must read Atoms before Velocities
+
+The Atoms section of a data file must come before a Velocities
+section.
+
+E: Invalid data file section: Bonds
+
+Atom style does not allow bonds.
+
+E: Must read Atoms before Bonds
+
+The Atoms section of a data file must come before a Bonds section.
+
+E: Invalid data file section: Angles
+
+Atom style does not allow angles.
+
+E: Must read Atoms before Angles
+
+The Atoms section of a data file must come before an Angles section.
+
+E: Invalid data file section: Dihedrals
+
+Atom style does not allow dihedrals.
+
+E: Must read Atoms before Dihedrals
+
+The Atoms section of a data file must come before a Dihedrals section.
+
+E: Invalid data file section: Impropers
+
+Atom style does not allow impropers.
+
+E: Must read Atoms before Impropers
+
+The Atoms section of a data file must come before an Impropers
+section.
+
+E: Invalid data file section: Ellipsoids
+
+Atom style does not allow ellipsoids.
+
+E: Must read Atoms before Ellipsoids
+
+The Atoms section of a data file must come before a Ellipsoids
+section.
+
+E: Invalid data file section: Lines
+
+Atom style does not allow lines.
+
+E: Must read Atoms before Lines
+
+The Atoms section of a data file must come before a Lines section.
+
+E: Invalid data file section: Triangles
+
+Atom style does not allow triangles.
+
+E: Must read Atoms before Triangles
+
+The Atoms section of a data file must come before a Triangles section.
+
+E: Invalid data file section: Bodies
+
+Atom style does not allow bodies.
+
+E: Must read Atoms before Bodies
+
+The Atoms section of a data file must come before a Bodies section.
+
+E: Must define pair_style before Pair Coeffs
+
+Must use a pair_style command before reading a data file that defines
+Pair Coeffs.
+
+W: Pair style in data file differs from currently defined pair style
+
+Self-explanatory.
+
+E: Must define pair_style before PairIJ Coeffs
+
+Must use a pair_style command before reading a data file that defines
+PairIJ Coeffs.
+
+E: Invalid data file section: Bond Coeffs
+
+Atom style does not allow bonds.
+
+E: Must define bond_style before Bond Coeffs
+
+Must use a bond_style command before reading a data file that
+defines Bond Coeffs.
+
+W: Bond style in data file differs from currently defined bond style
+
+Self-explanatory.
+
+E: Invalid data file section: Angle Coeffs
+
+Atom style does not allow angles.
+
+E: Must define angle_style before Angle Coeffs
+
+Must use an angle_style command before reading a data file that
+defines Angle Coeffs.
+
+W: Angle style in data file differs from currently defined angle style
+
+Self-explanatory.
+
+E: Invalid data file section: Dihedral Coeffs
+
+Atom style does not allow dihedrals.
+
+E: Must define dihedral_style before Dihedral Coeffs
+
+Must use a dihedral_style command before reading a data file that
+defines Dihedral Coeffs.
+
+W: Dihedral style in data file differs from currently defined dihedral style
+
+Self-explanatory.
+
+E: Invalid data file section: Improper Coeffs
+
+Atom style does not allow impropers.
+
+E: Must define improper_style before Improper Coeffs
+
+Must use an improper_style command before reading a data file that
+defines Improper Coeffs.
+
+W: Improper style in data file differs from currently defined improper style
+
+Self-explanatory.
+
+E: Invalid data file section: BondBond Coeffs
+
+Atom style does not allow angles.
+
+E: Must define angle_style before BondBond Coeffs
+
+Must use an angle_style command before reading a data file that
+defines Angle Coeffs.
+
+E: Invalid data file section: BondAngle Coeffs
+
+Atom style does not allow angles.
+
+E: Must define angle_style before BondAngle Coeffs
+
+Must use an angle_style command before reading a data file that
+defines Angle Coeffs.
+
+E: Invalid data file section: MiddleBondTorsion Coeffs
+
+Atom style does not allow dihedrals.
+
+E: Must define dihedral_style before MiddleBondTorsion Coeffs
+
+Must use a dihedral_style command before reading a data file that
+defines MiddleBondTorsion Coeffs.
+
+E: Invalid data file section: EndBondTorsion Coeffs
+
+Atom style does not allow dihedrals.
+
+E: Must define dihedral_style before EndBondTorsion Coeffs
+
+Must use a dihedral_style command before reading a data file that
+defines EndBondTorsion Coeffs.
+
+E: Invalid data file section: AngleTorsion Coeffs
+
+Atom style does not allow dihedrals.
+
+E: Must define dihedral_style before AngleTorsion Coeffs
+
+Must use a dihedral_style command before reading a data file that
+defines AngleTorsion Coeffs.
+
+E: Invalid data file section: AngleAngleTorsion Coeffs
+
+Atom style does not allow dihedrals.
+
+E: Must define dihedral_style before AngleAngleTorsion Coeffs
+
+Must use a dihedral_style command before reading a data file that
+defines AngleAngleTorsion Coeffs.
+
+E: Invalid data file section: BondBond13 Coeffs
+
+Atom style does not allow dihedrals.
+
+E: Must define dihedral_style before BondBond13 Coeffs
+
+Must use a dihedral_style command before reading a data file that
+defines BondBond13 Coeffs.
+
+E: Invalid data file section: AngleAngle Coeffs
+
+Atom style does not allow impropers.
+
+E: Must define improper_style before AngleAngle Coeffs
+
+Must use an improper_style command before reading a data file that
+defines AngleAngle Coeffs.
+
+E: Unknown identifier in data file: %s
+
+A section of the data file cannot be read by LAMMPS.
+
+E: No atoms in data file
+
+The header of the data file indicated that atoms would be included,
+but they are not present.
+
+E: Needed molecular topology not in data file
+
+The header of the data file indicated bonds, angles, etc would be
+included, but they are not present.
+
+E: Needed bonus data not in data file
+
+Some atom styles require bonus data.  See the read_data doc page for
+details.
+
+E: Read_data shrink wrap did not assign all atoms correctly
+
+This is typically because the box-size specified in the data file is
+large compared to the actual extent of atoms in a shrink-wrapped
+dimension.  When LAMMPS shrink-wraps the box atoms will be lost if the
+processor they are re-assigned to is too far away.  Choose a box
+size closer to the actual extent of the atoms.
+
+E: Unexpected end of data file
+
+LAMMPS hit the end of the data file while attempting to read a
+section.  Something is wrong with the format of the data file.
+
+E: No ellipsoids allowed with this atom style
+
+Self-explanatory.  Check data file.
+
+E: No lines allowed with this atom style
+
+Self-explanatory.  Check data file.
+
+E: No triangles allowed with this atom style
+
+Self-explanatory.  Check data file.
+
+E: No bodies allowed with this atom style
+
+Self-explanatory.  Check data file.
+
+E: System in data file is too big
+
+See the setting for bigint in the src/lmptype.h file.
+
+E: Bonds defined but no bond types
+
+The data file header lists bonds but no bond types.
+
+E: Angles defined but no angle types
+
+The data file header lists angles but no angle types.
+
+E: Dihedrals defined but no dihedral types
+
+The data file header lists dihedrals but no dihedral types.
+
+E: Impropers defined but no improper types
+
+The data file header lists improper but no improper types.
+
+E: No molecule topology allowed with atom style template
+
+The data file cannot specify the number of bonds, angles, etc,
+because this info if inferred from the molecule templates.
+
+E: Did not assign all atoms correctly
+
+Atoms read in from a data file were not assigned correctly to
+processors.  This is likely due to some atom coordinates being
+outside a non-periodic simulation box.
+
+E: Subsequent read data induced too many bonds per atom
+
+See the create_box extra/bond/per/atom or read_data "extra bond per
+atom" header value to set this limit larger.
+
+E: Bonds assigned incorrectly
+
+Bonds read in from the data file were not assigned correctly to atoms.
+This means there is something invalid about the topology definitions.
+
+E: Subsequent read data induced too many angles per atom
+
+See the create_box extra/angle/per/atom or read_data "extra angle per
+atom" header value to set this limit larger.
+
+E: Angles assigned incorrectly
+
+Angles read in from the data file were not assigned correctly to
+atoms.  This means there is something invalid about the topology
+definitions.
+
+E: Subsequent read data induced too many dihedrals per atom
+
+See the create_box extra/dihedral/per/atom or read_data "extra
+dihedral per atom" header value to set this limit larger.
+
+E: Dihedrals assigned incorrectly
+
+Dihedrals read in from the data file were not assigned correctly to
+atoms.  This means there is something invalid about the topology
+definitions.
+
+E: Subsequent read data induced too many impropers per atom
+
+See the create_box extra/improper/per/atom or read_data "extra
+improper per atom" header value to set this limit larger.
+
+E: Impropers assigned incorrectly
+
+Impropers read in from the data file were not assigned correctly to
+atoms.  This means there is something invalid about the topology
+definitions.
+
+E: Too few values in body lines in data file
+
+Self-explanatory.
+
+E: Too many values in body lines in data file
+
+Self-explanatory.
+
+E: Too many lines in one body in data file - boost MAXBODY
+
+MAXBODY is a setting at the top of the src/read_data.cpp file.
+Set it larger and re-compile the code.
+
+E: Unexpected end of PairCoeffs section
+
+Read a blank line.
+
+E: Unexpected end of BondCoeffs section
+
+Read a blank line.
+
+E: Unexpected end of AngleCoeffs section
+
+Read a blank line.
+
+E: Unexpected end of DihedralCoeffs section
+
+Read a blank line.
+
+E: Unexpected end of ImproperCoeffs section
+
+Read a blank line.
+
+E: Cannot open gzipped file
+
+LAMMPS was compiled without support for reading and writing gzipped
+files through a pipeline to the gzip program with -DLAMMPS_GZIP.
+
+E: Cannot open file %s
+
+The specified file cannot be opened.  Check that the path and name are
+correct. If the file is a compressed file, also check that the gzip
+executable can be found and run.
+
+*/