diff --git a/.gitignore b/.gitignore
index fd8f967c419e269fb5a95b5521100fb17e46ed6a..0acff3188ddfe7dccaebc5e963d353482b380d38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,11 +17,13 @@
 *.log
 *.toc
 *.pdf
+_minted-*
 
 # ViM, emacs, nano, leafpad
 tags
 *.swp
 *~
+tags
 
 # Python
 *.pyc
@@ -57,7 +59,12 @@ stamp-h1
 *.tab.c
 *.tab.h
 
+# PBS/torque job logs
+*.o[0-9]*
+*.e[0-9]*
+
 # General
 *.tar.gz
 *.pdf
 */bin
+*.txt
diff --git a/Makefile.am b/Makefile.am
index 465748f063bbf78e43db8d3ec23a7278874579c0..cd0f9dd4263ca2a92e5ad09f12a46f361e135606 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,8 +5,8 @@ DIST_SUBDIRS =
 EXTRA_DIST = data environ tools
 
 if BUILD_S_OMP
-SUBDIRS += PuReMD-GPU
-DIST_SUBDIRS += PuReMD-GPU
+SUBDIRS += sPuReMD
+DIST_SUBDIRS += sPuReMD
 endif
 if BUILD_MPI
 SUBDIRS += PuReMD
diff --git a/configure.ac b/configure.ac
index 787ab511fc8d4c26104289a1b242c30fcf5b42f8..91b08a149c43fdcde22b43462ab99638a787352d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,7 +46,7 @@ AC_ARG_ENABLE([mpi-gpu],
 	      [pack_mpi_gpu_enabled=${enableval}], [pack_mpi_gpu_enabled=no])
 
 if test "x${pack_serial_enabled}" = "xyes" || test "x${pack_openmp_enabled}" = "xyes" || test "x${pack_gpu_enabled}" = "xyes"; then
-	AC_CONFIG_SUBDIRS([PuReMD-GPU])
+	AC_CONFIG_SUBDIRS([sPuReMD])
 	if test "x${pack_serial_enabled}" = "xyes" || test "x${pack_openmp_enabled}" != "xyes"; then
 		export BUILD_OPENMP="no"
 	else
diff --git a/data/benchmarks/water/ffield_Achtyl b/data/benchmarks/water/ffield_Achtyl
new file mode 100644
index 0000000000000000000000000000000000000000..ce54cb3bad2a701ff11a41f08679d98026a022d9
--- /dev/null
+++ b/data/benchmarks/water/ffield_Achtyl
@@ -0,0 +1,424 @@
+Reactive MD-force field: water/C/Ca/Ti AKS2 July 18; water from Feb 29          
+ 39       ! Number of general parameters                                        
+   50.0000 !Overcoordination parameter                                          
+    9.5469 !Overcoordination parameter                                          
+    1.6725 !Valency angle conjugation parameter                                 
+    1.7224 !Triple bond stabilisation parameter                                 
+    6.8702 !Triple bond stabilisation parameter                                 
+   54.6742 !C2-correction                                                       
+    1.0588 !Undercoordination parameter                                         
+    4.6000 !Triple bond stabilisation parameter                                 
+   12.1176 !Undercoordination parameter                                         
+   13.3056 !Undercoordination parameter                                         
+  -34.5448 !Triple bond stabilization energy                                    
+    0.0000 !Lower Taper-radius                                                  
+   10.0000 !Upper Taper-radius                                                  
+    2.8793 !Not used                                                            
+   33.8667 !Valency undercoordination                                           
+    6.0891 !Valency angle/lone pair parameter                                   
+    1.0563 !Valency angle                                                       
+    2.0384 !Valency angle parameter                                             
+    6.1431 !Not used                                                            
+    6.9290 !Double bond/angle parameter                                         
+    0.3989 !Double bond/angle parameter: overcoord                              
+    3.9954 !Double bond/angle parameter: overcoord                              
+   -2.4837 !Not used                                                            
+    8.5385 !Torsion/BO parameter                                                
+    6.7491 !Torsion overcoordination                                            
+    0.1414 !Torsion overcoordination                                            
+   -1.2327 !Conjugation 0 (not used)                                            
+    1.1348 !Conjugation                                                         
+    1.5591 !vdWaals shielding                                                   
+    0.1000 !Cutoff for bond order (*100)                                        
+    1.7602 !Valency angle conjugation parameter                                 
+    0.6991 !Overcoordination parameter                                          
+   50.0000 !Overcoordination parameter                                          
+    1.8512 !Valency/lone pair parameter                                         
+  548.6451 !Softness                                                            
+    0.0000 !Cutoff                                                              
+    5.0000 !Molecular energy (not used)                                         
+    0.0000 !Molecular energy (not used)                                         
+    0.7903 !Valency angle conjugation parameter                                 
+ 13   ! Nr of atoms; cov.r; valency;a.m;Rvdw;Evdw;gammaEEM;cov.r2;#             
+            alfa;gammavdW;valency;Eunder;Eover;chiEEM;etaEEM;n.u.               
+            cov r3;Elp;Heat inc.;n.u.;n.u.;n.u.;n.u.                            
+            ov/un;val1;n.u.;val3,vval4                                          
+ C    1.3417   4.0000  12.0000   2.0464   0.1064   0.4670   1.1681   4.0000     
+      9.0000   1.5000   4.0000  40.0000  79.5548   5.3422   4.5000   0.0000     
+      1.1437   0.0000 181.0000   5.4236  19.2788  13.5366   3.1838   0.0000     
+     -4.0998   4.8750   1.0564   4.0000   2.9663   1.2500   0.4000  21.3612     
+ H    0.9102   1.0000   1.0080   1.0996   0.1000   0.6683  -0.1000   1.0000     
+      9.2193   5.5154   1.0000   0.0000 121.1250   4.9673   6.2079   0.0000     
+     -0.1000   0.0000  55.5000   1.1004   6.8959   0.0003   3.4114   0.0000     
+     -6.5532   3.5000   1.0338   1.0000   2.8793   0.5000   0.1000   1.0000     
+ O    1.2218   2.0000  15.9990   2.2033   0.2841   0.9750   1.0727   6.0000     
+      8.8250 200.0000   4.0000  37.5000 116.0768   8.5000   7.9071   0.0000     
+      0.9049   0.5488  68.0152   2.1943   2.3055   0.0021   5.4479   0.0000     
+     -6.0011   3.6068   1.0493   4.0000   2.9225   0.5000   0.1000   1.0000     
+ N    1.2333   3.0000  14.0000   2.2375   0.1447   1.0000   1.1748   5.0000     
+      9.8626  12.6599   4.0000  30.3181 100.0000   6.0111   6.7037   0.0000     
+      1.0433   0.7872 119.9837   0.7425   6.7920   2.7271   2.2882   0.0000     
+     -2.0000   4.0000   1.0183   4.0000   2.8793   1.0000   0.1000   1.0000     
+ S    1.9405   2.0000  32.0600   2.0677   0.2099   1.0336   1.5479   6.0000     
+      9.9575   4.9055   4.0000  52.9998 112.1416   6.5000   8.2545   0.0000     
+      1.4601   9.7177  71.1843   5.7487  23.2859  12.7147   2.2882   0.0000     
+    -11.0000   2.7466   1.0338   6.2998   2.8793   1.0000   0.1000  10.0000     
+ Mg   1.8315   2.0000  24.3050   2.2464   0.1806   0.5020   1.0000   2.0000     
+     10.9186  27.1205   3.0000  38.0000   0.0000   0.9499   5.6130   0.0000     
+     -1.3000   0.0000 127.9160  49.9248   0.3370   0.0000   2.2882   0.0000     
+     -1.0823   2.3663   1.0564   6.0000   2.9663   1.0000   0.1000  10.0000     
+ P    1.5994   3.0000  30.9738   1.7000   0.1743   1.0000   1.3000   5.0000     
+      9.1909  14.9482   5.0000   0.0000   0.0000   1.6676   7.0946   0.0000     
+     -1.0000  25.0000 125.6300   0.2187  21.4305  15.1425   2.2882   0.0000     
+     -3.9294   3.4831   1.0338   5.0000   2.8793   1.0000   0.1000  10.0000     
+ Na   1.8000   1.0000  22.9898   2.8270   0.1872   0.4000  -1.0000   1.0000     
+     10.0000   2.5000   1.0000   0.0000   0.0000  -0.9871   6.7728   0.0000     
+     -1.0000   0.0000  23.0445 100.0000   1.0000   0.0000   2.2882   0.0000     
+     -2.5000   3.9900   1.0338   8.0000   2.5791   1.0000   0.1000  10.0000     
+ Ti   2.0254   4.0000  47.8800   2.2105   0.1574   0.6311   0.1000   4.0000     
+     12.7041  16.6482   4.0000   0.1000   0.0000  -1.3647   6.8406   0.0000     
+     -1.0000   0.0000 143.1770  27.6505  -0.0753   0.0064   2.2882   0.0000     
+    -15.0000   3.8359   1.0338  12.0000   2.2632   1.0000   0.1000  10.0000     
+ Cl   1.7140   1.0000  35.4500   1.9139   0.2000   0.3500  -1.0000   7.0000     
+     11.5345  10.1330   1.0000   0.0000   0.0000   9.9704   6.1703   0.0000     
+     -1.0000   1.2769 143.1770   6.2293   5.2294   0.1542   2.2882   0.0000     
+    -10.2080   2.9867   1.0338   6.2998   2.5791   1.0000   0.1000  10.0000     
+ F    1.2100   1.0000  18.9984   1.8601   0.1200   0.3000  -0.1000   7.0000     
+     11.5000   7.5000   4.0000   9.2533   0.2000   9.0000  15.0000   0.0000     
+     -1.0000  35.0000   1.5000   6.9821   4.1799   1.0561   2.2882   0.0000     
+     -7.3000   2.6656   1.0493   4.0000   2.9225   1.0000   0.1000  10.0000     
+ Ca   1.9058   2.0000  40.0870   2.3698   0.3719   0.6038  -1.0000   2.0000     
+      9.8681   5.0000   3.0000  38.0000   0.0000  -5.7471   7.3556   0.0000     
+     -1.3000   0.0000 220.0000  49.9248   0.3370   0.0000   3.7000   0.0000     
+     -3.9745   3.0069   1.0564   8.0000   2.9663   0.5000   0.1000  10.0000     
+ X   -0.1000   2.0000   1.0080   2.0000   0.0000   1.0000  -0.1000   6.0000     
+     10.0000   2.5000   4.0000   0.0000   0.0000  -0.1000  25.0000   0.0000     
+     -0.1000   0.0000  -2.3700   8.7410  13.3640   0.6690   0.1000   0.0000     
+    -11.0000   2.7466   1.0338   4.0000   2.8793   1.0000   0.1000  10.0000     
+ 62     ! Nr of bonds; Edis1;LPpen;n.u.;pbe1;pbo5;13corr;pbo6                   
+                         pbe2;pbo3;pbo4;Etrip;pbo1;pbo2;ovcorr                  
+  1  1  78.4266 115.3834  68.1631   0.5777  -0.2901   1.0000  34.9989   0.5101  
+         3.8560  -0.1640   8.2326   1.0000  -0.0585   6.7997   1.0000   0.0000  
+  1  2 191.4398   0.0000   0.0000  -0.6539   0.0000   1.0000   6.0000   0.4898  
+         6.3962   1.0000   0.0000   1.0000  -0.0607   6.9960   0.0000   0.0000  
+  2  2 161.2898   0.0000   0.0000  -0.2387   0.0000   1.0000   6.0000   0.6279  
+        13.2089   1.0000   0.0000   1.0000  -0.1674   6.9118   0.0000   0.0000  
+  1  3 170.8787 152.2997 125.6008   0.2914  -0.2305   1.0000  16.7601   0.8645  
+         3.9615  -0.5703   7.4065   1.0000  -0.2514   4.5085   0.0000   0.0000  
+  3  3 222.6268  93.7249  50.8293   0.5588  -0.1000   1.0000  29.7503   0.0125  
+         0.5865  -0.2030   9.1777   1.0000  -0.1357   6.4747   1.0000   0.0000  
+  1  4 163.8300 145.4458  89.6879  -1.3368  -0.3468   1.0000  27.5160   0.1575  
+         0.1817  -0.3114   7.1789   1.0000  -0.2345   4.5111   1.0000   0.0000  
+  3  4 130.8596 169.4551  40.0000   0.3837  -0.1639   1.0000  35.0000   0.2000  
+         1.0000  -0.3579   7.0004   1.0000  -0.1193   6.8773   1.0000   0.0000  
+  4  4 157.9384  82.5526 152.5336   0.4010  -0.1034   1.0000  12.4261   0.5828  
+         0.1578  -0.1509  11.9186   1.0000  -0.0861   5.4271   1.0000   0.0000  
+  2  3 143.3409   0.0000   0.0000  -0.4886   0.0000   1.0000   6.0000   0.3927  
+         1.3588   1.0000   0.0000   0.0000  -0.0781   4.0330   0.0000   0.0000  
+  2  4 210.1187   0.0000   0.0000  -0.3705   0.0000   1.0000   6.0000   0.3284  
+         5.8196   1.0000   0.0000   1.0000  -0.1104   5.5184   0.0000   0.0000  
+  1  5 128.9942  74.5848  55.2528   0.1035  -0.5211   1.0000  18.9617   0.6000  
+         0.2949  -0.2398   8.1175   1.0000  -0.1029   5.6731   1.0000   0.0000  
+  2  5 151.5159   0.0000   0.0000  -0.4721   0.0000   1.0000   6.0000   0.6000  
+         9.4366   1.0000   0.0000   1.0000  -0.0290   7.0050   1.0000   0.0000  
+  3  5   0.0000   0.0000   0.0000   0.5563  -0.4038   1.0000  49.5611   0.6000  
+         0.4259  -0.4577  12.7569   1.0000  -0.1100   7.1145   1.0000   0.0000  
+  4  5   0.0000   0.0000   0.0000   0.4438  -0.2034   1.0000  40.3399   0.6000  
+         0.3296  -0.3153   9.1227   1.0000  -0.1805   5.6864   1.0000   0.0000  
+  5  5  96.1871  93.7006  68.6860   0.0955  -0.4781   1.0000  17.8574   0.6000  
+         0.2723  -0.2373   9.7875   1.0000  -0.0950   6.4757   1.0000   0.0000  
+  2  6  58.6896   0.0000   0.0000  -0.0203  -0.1418   1.0000  13.1260   0.0230  
+         8.2136  -0.1310   0.0000   1.0000  -0.2692   6.4254   0.0000  24.4461  
+  3  6  87.0227   0.0000  43.3991   0.0030  -0.3000   1.0000  36.0000   0.0250  
+         0.0087  -0.2500  12.0000   1.0000  -0.0439   6.6073   1.0000  24.4461  
+  6  6  32.3808   0.0000   0.0000  -0.0076  -0.2000   0.0000  16.0000   0.2641  
+         4.8726  -0.2000  10.0000   1.0000  -0.0729   4.6319   0.0000   0.0000  
+  1  7 110.0000  92.0000   0.0000   0.2171  -0.1418   1.0000  13.1260   0.6000  
+         0.3601  -0.1310  10.7257   1.0000  -0.0869   5.3302   1.0000   0.0000  
+  2  7   0.1466   0.0000   0.0000   0.2250  -0.1418   1.0000  13.1260   0.6000  
+         0.3912  -0.1310   0.0000   1.0000  -0.1029   9.3302   0.0000   0.0000  
+  3  7 201.0058 194.1410   0.0000   1.0000  -0.5000   1.0000  25.0000   0.4873  
+         0.4358  -0.1571  15.8745   1.0000  -0.2431   6.3823   1.0000   0.0000  
+  4  7 130.0000   0.0000   0.0000   0.2171  -0.1418   1.0000  13.1260   0.6000  
+         0.3601  -0.1310  10.7257   1.0000  -0.0869   5.3302   1.0000   0.0000  
+  6  7   0.1000   0.0000   0.0000   0.2500  -0.5000   1.0000  35.0000   0.6000  
+         0.5000  -0.5000  20.0000   1.0000  -0.2000  10.0000   1.0000   0.0000  
+  7  7   0.0000   0.0000   0.0000   0.2171  -0.5000   1.0000  35.0000   0.6000  
+         0.5000  -0.5000  20.0000   1.0000  -0.2000  10.0000   1.0000   0.0000  
+  1  8   0.0000   0.0000   0.0000  -1.0000  -0.3000   1.0000  36.0000   0.7000  
+        10.1151  -0.3500  25.0000   1.0000  -0.1053   8.2003   1.0000   0.0000  
+  2  8   0.0000   0.0000   0.0000  -1.0000  -0.3000   1.0000  36.0000   0.7000  
+        10.1151  -0.3500  25.0000   1.0000  -0.1053   8.2003   1.0000   0.0000  
+  3  8  45.8933   0.0000   0.0000  -0.1511  -0.3000   1.0000  36.0000   0.3105  
+         5.8448  -0.3500  25.0000   1.0000  -0.0659   7.9140   1.0000   0.0000  
+  4  8   0.0000   0.0000   0.0000  -1.0000  -0.3000   1.0000  36.0000   0.7000  
+        10.1151  -0.3500  25.0000   1.0000  -0.1053   8.2003   1.0000   0.0000  
+  5  8   0.0000   0.0000   0.0000  -1.0000  -0.3000   1.0000  36.0000   0.7000  
+        10.1151  -0.3500  25.0000   1.0000  -0.1053   8.2003   1.0000   0.0000  
+  6  8   0.0000   0.0000   0.0000   0.2500  -0.5000   1.0000  35.0000   0.6000  
+         0.5000  -0.5000  20.0000   1.0000  -0.2000  10.0000   1.0000   0.0000  
+  7  8   0.0000   0.0000   0.0000   0.2500  -0.5000   1.0000  35.0000   0.6000  
+         0.5000  -0.5000  20.0000   1.0000  -0.2000  10.0000   1.0000   0.0000  
+  8  8  64.4508   0.0000   0.0000  -0.3738   0.3000   0.0000  25.0000   0.2158  
+         0.9915  -0.4000  12.0000   1.0000  -0.0515   5.0000   0.0000   0.0000  
+  4  6  50.0000  10.0901   0.0000  -1.0000  -0.3000   1.0000  36.0000   0.7058  
+         0.8567  -0.3487  17.4990   1.0000  -0.0794   8.2232   1.0000   0.0000  
+  1  9   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  2  9   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  3  9 130.5629  37.6984   0.0000   0.9228  -0.3000   0.0000  36.0000   0.0850  
+         0.1150  -0.2818  16.1571   1.0000  -0.1343   6.8264   0.0000   0.0000  
+  4  9 130.5629  37.6984   0.0000   0.9228  -0.3000   0.0000  36.0000   0.0850  
+         0.1150  -0.2818  16.1571   1.0000  -0.1343   6.8264   0.0000   0.0000  
+  5  9   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  6  9   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  7  9   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  8  9   0.1000   0.0000   0.0000   0.2500  -0.5000   1.0000  35.0000   0.6000  
+         0.5000  -0.5000  20.0000   1.0000  -0.2000  10.0000   1.0000   0.0000  
+  9  9  80.1930   0.0000   0.0000  -0.8469  -0.2000   0.0000  16.0000   0.2022  
+         0.7528  -0.1924  14.9725   1.0000  -0.0885   5.0000   0.0000   0.0000  
+  1 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+  2 10  98.9788   0.0000   0.0000  -0.0572  -0.2000   0.0000  16.0000   1.1523  
+         2.2822  -0.2000  15.0000   1.0000  -0.1093   5.1686   0.0000   0.0000  
+  3 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+  4 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+  5 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+  6 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+  7 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+  8 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+  9 10   0.0000   0.0000   0.0000   0.5000  -0.2000   0.0000  16.0000   0.5000  
+         1.0001  -0.2000  15.0000   1.0000  -0.1000  10.0000   0.0000   0.0000  
+ 10 10   0.2500   0.0000   0.0000   0.1803  -0.2000   0.0000  16.0000   0.3356  
+         0.9228  -0.2000  15.0000   1.0000  -0.1178   5.6715   0.0000   0.0000  
+  1 11 237.8781   0.0000   0.0000  -0.7438  -0.5000   1.0000  35.0000   1.0460  
+         3.6661  -0.2500  15.0000   1.0000  -0.0800   5.4719   1.0000   0.0000  
+  2 11   0.0000   0.0000   0.0000  -0.4643   0.0000   1.0000   6.0000   0.6151  
+        12.3710   1.0000   0.0000   1.0000  -0.1008   8.5980   0.0000   0.0000  
+  3 11   0.0000   0.0000   0.0000  -0.4643   0.0000   1.0000   6.0000   0.6151  
+        12.3710   1.0000   0.0000   1.0000  -0.1008   8.5980   0.0000   0.0000  
+  4 11   0.0000   0.0000   0.0000  -0.4643   0.0000   1.0000   6.0000   0.6151  
+        12.3710   1.0000   0.0000   1.0000  -0.1008   8.5980   0.0000   0.0000  
+  5 11   0.0000   0.0000   0.0000  -0.4643   0.0000   1.0000   6.0000   0.6151  
+        12.3710   1.0000   0.0000   1.0000  -0.1008   8.5980   0.0000   0.0000  
+ 11 11 250.0765   0.0000   0.0000   0.2298  -0.3500   1.0000  25.0000   0.8427  
+         0.1167  -0.2500  15.0000   1.0000  -0.1506   7.3516   1.0000   0.0000  
+  1 12   0.0000   0.0000   0.0000  -0.0203  -0.1418   1.0000  13.1260   0.0230  
+         8.2136  -0.2500  20.0000   1.0000  -0.2692   6.4254   0.0000  24.4461  
+  2 12   0.0000   0.0000   0.0000  -0.0203  -0.1418   1.0000  13.1260   0.0230  
+         8.2136  -0.2500  20.0000   1.0000  -0.2692   6.4254   0.0000  24.4461  
+  3 12  49.4055   0.0000   0.0000   0.9603  -0.3000   0.0000  36.0000   0.0025  
+         0.4232  -0.2500  12.0000   1.0000  -0.1619   9.6512   0.0000  24.4461  
+ 12 12  22.8272   0.0000   0.0000   0.6166  -0.2000   0.0000  16.0000   0.8225  
+         1.0000  -0.2000  10.0000   1.0000  -0.0831   4.2291   0.0000   0.0000  
+ 26    ! Nr of off-diagonal terms; Ediss;Ro;gamma;rsigma;rpi;rpi2               
+  1  2   0.1240   1.6326   9.8721   1.1578  -1.0000  -1.0000                    
+  2  3   0.0295   1.3181  10.1225   0.9069  -1.0000  -1.0000                    
+  2  4   0.1294   1.3025   9.8751   1.0415  -1.0000  -1.0000                    
+  1  3   0.2287   2.0452   9.0166   1.4046   1.1866   1.0375                    
+  1  4   0.2000   1.8828   9.7673   1.3387   1.2578   1.1539                    
+  3  4   0.1001   2.3274   9.0974   1.5236   1.0493   1.2531                    
+  1  5   0.1408   1.8161   9.9393   1.7986   1.3021   1.4031                    
+  2  5   0.0895   1.6239  10.0104   1.4640  -1.0000  -1.0000                    
+  3  5   0.1022   1.9887  10.0605   1.5799   1.4000  -1.0000                    
+  4  5   0.1505   1.9000  10.5104   1.8000   1.4000  -1.0000                    
+  2  6   0.0100   1.6000  13.2979   1.8670  -1.0000  -1.0000                    
+  3  6   0.0809   1.7000  11.4606   1.5177  -1.0000  -1.0000                    
+  3  7   0.0534   1.7520  10.4281   1.8000   1.4498  -1.0000                    
+  6  7   0.1801   1.8566   9.8498   0.1000  -1.0000  -1.0000                    
+  3  8   0.0825   1.5904  11.3396   1.5905  -1.0000  -1.0000                    
+  2  9   0.1750   1.7939  13.5000   0.0100  -1.0000  -1.0000                    
+  3  9   0.1200   1.8000  10.5000   1.6526   1.4718  -1.0000                    
+  1  9   0.2950   2.2000  11.0937   0.0100  -1.0000  -1.0000                    
+  2 10   0.0376   1.6671   9.6285   1.2123  -1.0000  -1.0000                    
+  3 10   0.1945   2.2766  11.2353  -1.0000  -1.0000  -1.0000                    
+  1 11   0.1071   1.6243  11.0402   1.3176  -1.0000  -1.0000                    
+  2 11   0.0431   1.7204  10.3632   0.5386  -1.0000  -1.0000                    
+  4  9   0.1200   1.8000  10.5000   1.6526   1.4718  -1.0000                    
+  1 12   0.2000   1.5000  14.0000   0.0010   0.0010  -1.0000                    
+  2 12   0.0100   1.0610   9.7343   0.0010   0.0010  -1.0000                    
+  3 12   0.1515   1.8913  12.5160   2.0022  -1.0000  -1.0000                    
+ 98    ! Nr of angles;at1;at2;at3;Thetao,o;ka;kb;pv1;pv2                        
+  1  1  1  74.4118  38.0306   0.9605   0.0000   0.0100  36.6918   2.3203        
+  1  1  2  67.2765  20.1739   3.3306   0.0000   0.0100   0.0000   1.1630        
+  2  1  2  74.7224  38.7524   2.1423   0.0000   0.8474   0.0000   1.3144        
+  1  2  2   0.0000   0.0000   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  2  1   0.0000   3.4110   7.7350   0.0000   0.0000   0.0000   1.0400        
+  2  2  2   0.0000  27.9213   5.8635   0.0000   0.0000   0.0000   1.0400        
+  1  1  3  61.1001  38.5283   0.4917   0.0000   4.2373   0.0000   2.1649        
+  3  1  3  72.0708  27.2877   2.3068 -10.4517   0.1000   0.0000   1.6107        
+  1  1  4  64.7353  38.2645   1.1478   0.0000   1.1834   0.0000   2.8465        
+  3  1  4  81.0672  41.9015   0.4878   0.0000   1.1019   0.0000   1.0000        
+  4  1  4  89.7621  43.0000   0.5895   0.0000   1.1155   0.0000   1.0000        
+  2  1  3  61.3200  29.1602   0.9036   0.0000   1.8063   0.0000   1.4867        
+  2  1  4  68.7361  36.7162   1.6697   0.0000   0.2000   0.0000   3.0000        
+  1  2  4   0.0000   0.0019   6.3000   0.0000   0.0000   0.0000   1.0400        
+  1  3  1  74.2533  41.5372   0.4237   0.0000   2.3660   0.0000   1.0319        
+  1  3  3  82.8809  21.0869   3.0902   0.0000   4.5310  20.1072   1.0105        
+  1  3  4  70.3730  45.0000   1.4731   0.0000   2.9000   0.0000   2.4464        
+  3  3  3  77.3022  33.4558   1.4033   0.0000   3.9048   0.0000   1.0000        
+  3  3  4  77.0669  27.6795   1.6466   0.0000   2.9000   0.0000   1.5085        
+  4  3  4  68.8583  40.4712   1.8369   0.0000   3.0072   0.0000   1.5773        
+  1  3  2  90.0000  34.3702   0.4674   0.0000   0.6101   0.0000   1.0013        
+  2  3  3  90.0000  26.3185   8.0000   0.0000   0.8615   0.0000   1.0579        
+  2  3  4  68.3253  36.1953   7.5000   0.0000   0.1000   0.0000   1.0000        
+  2  3  2  80.7909  19.0967   1.0887   0.0000   2.0594   0.0000   1.7720        
+  1  4  1  71.2077  14.1180   3.3944   0.0000   2.8702   0.0000   1.2651        
+  1  4  3  76.1064  23.7583   1.6308   0.0000   2.8701   0.0000   1.6732        
+  1  4  4  71.3624  12.8120   3.1458   0.0000   2.8701   0.0000   1.1896        
+  3  4  3  74.2922  23.0742   2.6248 -18.0069   3.0701   0.0000   1.6278        
+  3  4  4  74.0840  31.1381   1.5175  -0.9193   3.0117   0.0000   1.3541        
+  4  4  4  76.0945  32.1176   1.7767   0.0000   2.9983   0.0000   1.9677        
+  1  4  2  69.1892  14.8553   2.7174   0.0000   0.2025   0.0000   1.3071        
+  2  4  3  74.5555  45.0000   1.1948   0.0000   0.3956   0.0000   3.0000        
+  2  4  4  78.8758  45.0000   0.5964   0.0000   0.5437   0.0000   1.0000        
+  2  4  2  81.5738   7.0792   7.5000   0.0000   0.1000   0.0000   1.0000        
+  1  2  3   0.0000  21.4989   1.0000   0.0000   0.1000   0.0000   1.1358        
+  1  2  4   0.0000   0.0100   2.4974   0.0000   0.0000   0.0000   1.3777        
+  1  2  5   0.0000  15.0000   3.0000   0.0000   0.0000   0.0000   1.0400        
+  3  2  3   0.0000  15.0000   0.5640   0.0000   0.0000   0.0000   1.0400        
+  3  2  4   0.0000   1.0235   0.1000   0.0000   0.0000   0.0000   3.0000        
+  4  2  4   0.0000   0.0100   1.3170   0.0000   0.0000   0.0000   2.1165        
+  2  2  3   0.0000   2.0000   0.0839   0.0000   0.0000   0.0000   2.9374        
+  2  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  1  5  74.4180  33.4273   1.7018   0.1463   0.5000   0.0000   1.6178        
+  1  5  1  79.7037  28.2036   1.7073   0.1463   0.5000   0.0000   1.6453        
+  2  1  5  63.3289  29.4225   2.1326   0.0000   0.5000   0.0000   3.0000        
+  1  5  2  85.9449  38.3109   1.2492   0.0000   0.5000   0.0000   1.1000        
+  1  5  5  85.6645  40.0000   2.9274   0.1463   0.5000   0.0000   1.3830        
+  2  5  2  83.8555   5.1317   0.4377   0.0000   0.5000   0.0000   3.0000        
+  2  5  5  97.0064  32.1121   2.0242   0.0000   0.5000   0.0000   2.8568        
+  3  5  3  81.0926  30.2268   6.4132  -5.4471   2.5968   0.0000   3.0000        
+  1  5  3  70.0000  35.0000   3.4223   0.0000   1.3550   0.0000   1.2002        
+  1  3  5  57.3353  41.0012   1.0609   0.0000   1.3000   0.0000   3.0000        
+  3  3  5  83.9753  31.0715   3.5590   0.0000   0.8161   0.0000   1.1776        
+  2  3  5  89.8843  17.5000   3.3660   0.0000   2.0000   0.0000   2.0734        
+  2  6  2   0.0000  49.8261   0.2093   0.0000   2.0870   0.0000   2.2895        
+  2  2  6   0.0000  40.0366   3.1505   0.0000   1.1296   0.0000   1.1110        
+  6  2  6   0.0000   0.5047   0.8000   0.0000   0.8933   0.0000   4.6650        
+  2  6  6   0.0000   8.7037   0.0827   0.0000   3.5597   0.0000   1.1198        
+  3  6  3   0.0000   9.2317   0.1000   0.0000   1.0000   0.0000   1.0920        
+  6  3  6   0.0008  25.0000   8.0000   0.0000   1.0000   0.0000   3.0000        
+  2  3  6  66.0423   5.0000   1.0000   0.0000   1.0000   0.0000   1.2500        
+  2  6  3   0.0000   0.5000   0.1000   0.0000   1.0000   0.0000   3.0000        
+  3  3  6  70.0000  20.0000   1.0000   0.0000   1.0000   0.0000   1.2500        
+  3  7  3  90.0000  18.4167   0.6799  -8.0000   0.1310   0.0000   2.2321        
+  2  3  7  72.6004   9.6150   0.8905   0.0000   3.5473   0.0000   1.0400        
+  3  3  7  60.0000  40.0000   4.0000   0.0000   1.0000   0.0000   1.0400        
+  3  2  7   0.0000  10.0000   1.0000   0.0000   1.0000   0.0000   1.0400        
+  6  3  7  41.0995   3.2207   7.3523   0.0000   0.1101   0.0000   1.0947        
+  7  3  7  62.1312   7.5931   0.1000   0.0000   0.5154   0.0000   2.1744        
+  1  3  7  74.1394   8.5687   1.7132   0.0000  -0.6553   0.0000   2.2323        
+  2  7  3  75.0000  25.0000   2.0000   0.0000   1.0000   0.0000   1.2500        
+  3  7  7  70.0000  25.0000   2.0000   0.0000   1.0000   0.0000   1.2500        
+  3  9  3  90.0000  30.4624   2.1468   0.0000   0.0500   0.0000   1.9485        
+  9  3  9  90.0000   5.7486   5.0000   0.0000   2.0000   0.0000   1.1000        
+  3  3  9  62.9344  15.0215   4.3743   0.0000   0.6168   0.0000   1.1673        
+  3  9  9  33.7127   8.0623   3.4580   0.0000   0.0500   0.0000   2.6065        
+  2  3  9  90.0000   9.7766   8.0000   0.0000   0.0505   0.0000   1.7257        
+  1  3  9  90.0000  11.2108   1.4880   0.0000   0.5386   0.0000   2.1105        
+  3  2 10   0.0000   0.0100   0.0100   0.0000   0.0000   0.0000   1.1456        
+ 11  1 11  77.8443  49.0744   5.9913   0.0000   0.7835   0.0000   2.3020        
+  1 11  1   0.0000  19.9962   3.2299   0.0000   2.1012   0.0000   1.1537        
+  1 11 11   0.0000  25.0000   1.0000   0.0000   1.0000   0.0000   1.0400        
+ 11  1  2  69.6421  10.0000   2.0000   0.0000   1.0000   0.0000   1.0400        
+  4  9  4  90.0000  30.4624   2.1468   0.0000   0.0500   0.0000   1.9485        
+  3  9  4  90.0000  30.4624   2.1468   0.0000   0.0500   0.0000   1.9485        
+  9  4  9  90.0000   5.7486   5.0000   0.0000   2.0000   0.0000   1.1000        
+  3  4  9  62.9344  15.0215   4.3743   0.0000   0.6168   0.0000   1.1673        
+  4  3  9  62.9344  15.0215   4.3743   0.0000   0.6168   0.0000   1.1673        
+  4  4  9  62.9344  15.0215   4.3743   0.0000   0.6168   0.0000   1.1673        
+  4  4  9  62.9344  15.0215   4.3743   0.0000   0.6168   0.0000   1.1673        
+  4  9  9  33.7127   8.0623   3.4580   0.0000   0.0500   0.0000   2.6065        
+  2  4  9  90.0000   9.7766   8.0000   0.0000   0.0505   0.0000   1.7257        
+  1  4  9  90.0000  11.2108   1.4880   0.0000   0.5386   0.0000   2.1105        
+  3 12  3  90.0000   5.2360   6.0000   0.0000   1.9491   0.0000   1.0000        
+ 12  3 12  27.0723   4.9264   1.7778   0.0000   0.3851   0.0000   1.4855        
+  2  3 12   1.0000   1.5989   6.0000   0.0000   0.6668   0.0000   1.0000        
+  3  3 12  90.0000  10.0000   1.0000   0.0000   1.0000   0.0000   2.0000        
+  1  3 12  70.0000   0.0000   1.0000   0.0000   1.0000   0.0000   2.0000        
+ 73    ! Nr of torsions;at1;at2;at3;at4;;V1;V2;V3;V2(BO);vconj;n.u;n            
+  1  1  1  1   0.0734  56.5103   0.0000  -5.5375  -2.6113   0.0000   0.0000     
+  1  1  1  2   0.2335  44.4534   0.5000  -5.5234  -3.0000   0.0000   0.0000     
+  2  1  1  2  -0.0100  59.3937   0.5000  -8.0000  -3.0000   0.0000   0.0000     
+  1  1  1  3  -0.1605   9.1977  -1.0000  -2.5000  -2.1235   0.0000   0.0000     
+  2  1  1  3   0.4631  41.1330   0.7425  -7.5125  -1.1040   0.0000   0.0000     
+  3  1  1  3  -1.0000  30.3068  -1.0000  -8.5000  -0.0100   0.0000   0.0000     
+  1  1  3  1   1.0000  45.3654  -0.7715  -3.2711  -0.0100   0.0000   0.0000     
+  1  1  3  2   1.0000 150.0000   1.0000  -6.6407  -0.0100   0.0000   0.0000     
+  2  1  3  1   1.0000 143.9644   0.6834  -6.1023  -1.1889   0.0000   0.0000     
+  2  1  3  2  -1.0000  74.4134   1.0000  -3.3595  -3.5000   0.0000   0.0000     
+  1  1  3  3   1.0000 133.2711   0.5065  -2.5561  -0.0100   0.0000   0.0000     
+  2  1  3  3   0.2238  53.9090   0.8685  -2.7064  -3.5000   0.0000   0.0000     
+  3  1  3  1  -1.0000  66.2620   0.7534  -3.3533  -2.2258   0.0000   0.0000     
+  3  1  3  2   0.6489  19.7090  -1.0000  -3.3466  -0.1540   0.0000   0.0000     
+  3  1  3  3  -1.0000  86.4981   1.0000  -3.5833  -0.0610   0.0000   0.0000     
+  1  3  3  1   1.0000   0.1000   1.0000  -6.9024  -0.0100   0.0000   0.0000     
+  1  3  3  2   0.9093  23.6198  -0.1431  -2.4750  -3.5000   0.0000   0.0000     
+  2  3  3  2  -1.6122   5.0000  -1.0000  -2.5394  -0.9921   0.0000   0.0000     
+  1  3  3  3   2.5000   2.1016   0.9647  -2.6000  -0.9972   0.0000   0.0000     
+  2  3  3  3  -2.5000  75.7606  -0.6120  -7.8633  -1.2407   0.0000   0.0000     
+  3  3  3  3  -0.5000   5.0000   1.0000  -2.5000  -0.9000   0.0000   0.0000     
+  1  1  4  2   0.2700  43.1323  -0.4952  -7.6538  -1.9825   0.0000   0.0000     
+  2  1  4  2  -0.5047  82.9784   0.8701  -7.6680  -2.1051   0.0000   0.0000     
+  3  1  4  2   0.8306  15.5307   1.0000  -2.5000  -2.5261   0.0000   0.0000     
+  3  1  1  4  -0.8051  19.8307   1.0000  -3.7979  -0.9511   0.0000   0.0000     
+  4  1  1  4   1.0000  36.1913   1.0000  -3.4095  -1.7241   0.0000   0.0000     
+  1  1  4  1   1.0000  32.6616   0.3481  -6.4524  -1.6589   0.0000   0.0000     
+  3  1  4  1  -1.0000  -5.0000   1.0000  -2.5000  -1.8038   0.0000   0.0000     
+  2  1  1  4   0.7529  50.8010  -0.5000  -4.3471  -1.9000   0.0000   0.0000     
+  4  1  4  2   0.3787  13.7301   0.6579  -8.2500  -2.0202   0.0000   0.0000     
+  2  1  4  1  -1.0000  76.7186   0.1194  -8.0000  -1.5996   0.0000   0.0000     
+  0  1  2  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  2  2  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  2  3  0   0.0000   0.1000   0.0200  -2.5415   0.0000   0.0000   0.0000     
+  0  1  1  0   0.0000  60.0000   0.3000  -4.0000  -2.0000   0.0000   0.0000     
+  0  3  3  0   0.5511  25.4150   1.1330  -5.1903  -1.0000   0.0000   0.0000     
+  0  1  4  0   0.2176  40.4126   0.3535  -3.9875  -2.0051   0.0000   0.0000     
+  0  2  4  0   0.0000   0.1032   0.3000  -5.0965   0.0000   0.0000   0.0000     
+  0  3  4  0   1.1397  61.3225   0.5139  -3.8507  -2.7831   0.0000   0.0000     
+  0  4  4  0   0.7265  44.3155   1.0000  -4.4046  -2.0000   0.0000   0.0000     
+  4  1  4  4  -0.0949   8.7582   0.3310  -7.9430  -2.0000   0.0000   0.0000     
+  0  1  5  0   4.0885  78.7058   0.1174  -2.1639   0.0000   0.0000   0.0000     
+  0  5  5  0  -0.0170 -56.0786   0.6132  -2.2092   0.0000   0.0000   0.0000     
+  0  2  5  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  2  3  5  3   2.5000   2.5000   0.2237 -10.0000  -1.0000   0.0000   0.0000     
+  0  3  5  0  -2.5000  50.0000  -0.5000 -10.0000  -1.0000   0.0000   0.0000     
+  0  6  6  0   0.0000   0.0000   0.1200  -2.4426   0.0000   0.0000   0.0000     
+  0  2  6  0   0.0000   0.0000   0.1200  -2.4847   0.0000   0.0000   0.0000     
+  0  3  6  0   0.0000   0.0000   0.1200  -2.4703   0.0000   0.0000   0.0000     
+  1  1  1  7  -0.3232  14.3871   0.1823  -9.8682  -1.7255   0.0000   0.0000     
+  7  1  1  7  -0.1452  50.0000  -0.1915  -8.0773  -1.7255   0.0000   0.0000     
+  0  1  7  0   4.0000  45.8264   0.9000  -4.0000   0.0000   0.0000   0.0000     
+  0  7  7  0   4.0000  45.8264   0.9000  -4.0000   0.0000   0.0000   0.0000     
+  2  1  3  7  -1.5000  18.9285   0.3649  -6.1208   0.0000   0.0000   0.0000     
+  2  3  7  3   1.5000  -1.0000   0.2575  -6.2100   0.0000   0.0000   0.0000     
+  1  3  7  3  -1.4375  -0.8700   0.9861  -2.5424   0.0000   0.0000   0.0000     
+  7  3  7  3  -1.5000  21.5086  -1.0000  -4.8869   0.0000   0.0000   0.0000     
+  2  1  3  9   0.1714  69.9743   0.9170  -7.9557   0.0000   0.0000   0.0000     
+  1  1  3  9   0.2500  76.5218   1.0000  -2.5503   0.0000   0.0000   0.0000     
+  3  1  3  9  -0.2500  50.5929  -0.2500  -6.9285   0.0000   0.0000   0.0000     
+  2  3  9  3  -0.2500   0.0100  -0.5000  -4.6984   0.0000   0.0000   0.0000     
+  1  1  1 11   0.5000   0.1000   0.4683 -11.5274  -1.7255   0.0000   0.0000     
+  2  1  1 11   0.0000  49.3871   0.2000 -10.5765  -1.7255   0.0000   0.0000     
+ 11  1  1 11  -0.5000  95.4727  -0.2080  -4.8579  -1.7255   0.0000   0.0000     
+  0  1 11  0   4.0000  45.8264   0.9000  -4.0000   0.0000   0.0000   0.0000     
+  0 11 11  0   4.0000  45.8264   0.8897  -4.0000   0.0000   0.0000   0.0000     
+  2  1  4  9   0.1714  69.9743   0.9170  -7.9557   0.0000   0.0000   0.0000     
+  1  1  4  9   0.2500  76.5218   1.0000  -2.5503   0.0000   0.0000   0.0000     
+  3  1  4  9  -0.2500  50.5929  -0.2500  -6.9285   0.0000   0.0000   0.0000     
+  4  1  4  9  -0.2500  50.5929  -0.2500  -6.9285   0.0000   0.0000   0.0000     
+  4  1  3  9  -0.2500  50.5929  -0.2500  -6.9285   0.0000   0.0000   0.0000     
+  2  4  9  3  -0.2500   0.0100  -0.5000  -4.6984   0.0000   0.0000   0.0000     
+  2  4  9  4  -0.2500   0.0100  -0.5000  -4.6984   0.0000   0.0000   0.0000     
+  0    ! Nr of hydrogen bonds;at1;at2;at3;Rhb;Dehb;vhb1                         
diff --git a/data/benchmarks/water/ffield_acks2.water b/data/benchmarks/water/ffield_acks2.water
new file mode 100644
index 0000000000000000000000000000000000000000..ddf2d3cbf5f8c76d3203ee4a326ee8db23fb246e
--- /dev/null
+++ b/data/benchmarks/water/ffield_acks2.water
@@ -0,0 +1,364 @@
+Reactive MD-force field: Water                                                  
+ 39       ! Number of general parameters                                        
+   50.0000 !Overcoordination parameter                                          
+    9.5469 !Overcoordination parameter                                          
+   26.5405 !Valency angle conjugation parameter                                 
+    1.7224 !Triple bond stabilisation parameter                                 
+    6.8702 !Triple bond stabilisation parameter                                 
+   60.4850 !C2-correction                                                       
+    1.0588 !Undercoordination parameter                                         
+    4.6000 !Triple bond stabilisation parameter                                 
+   12.1176 !Undercoordination parameter                                         
+   13.3056 !Undercoordination parameter                                         
+  -70.5044 !Triple bond stabilization energy                                    
+    0.0000 !Lower Taper-radius                                                  
+   10.0000 !Upper Taper-radius                                                  
+    2.8793 !Not used                                                            
+   33.8667 !Valency undercoordination                                           
+    6.0891 !Valency angle/lone pair parameter                                   
+    1.0563 !Valency angle                                                       
+    2.0384 !Valency angle parameter                                             
+    6.1431 !Not used                                                            
+    6.9290 !Double bond/angle parameter                                         
+    0.3989 !Double bond/angle parameter: overcoord                              
+    3.9954 !Double bond/angle parameter: overcoord                              
+   -2.4837 !Not used                                                            
+    5.7796 !Torsion/BO parameter                                                
+   10.0000 !Torsion overcoordination                                            
+    1.9487 !Torsion overcoordination                                            
+   -1.2327 !Conjugation 0 (not used)                                            
+    2.1645 !Conjugation                                                         
+    1.5591 !vdWaals shielding                                                   
+    0.1000 !Cutoff for bond order (*100)                                        
+    2.1365 !Valency angle conjugation parameter                                 
+    0.6991 !Overcoordination parameter                                          
+   50.0000 !Overcoordination parameter                                          
+    1.8512 !Valency/lone pair parameter                                         
+  548.6451 !Softness                                                            
+   20.0000 !Not used                                                            
+    5.0000 !Molecular energy (not used)                                         
+    0.0000 !Molecular energy (not used)                                         
+    2.6962 !Valency angle conjugation parameter                                 
+ 15    ! Nr of atoms; cov.r; valency;a.m;Rvdw;Evdw;gammaEEM;cov.r2;#            
+            alfa;gammavdW;valency;Eunder;Eover;chiEEM;etaEEM;n.u.               
+            cov r3;Elp;Heat inc.;n.u.;n.u.;n.u.;n.u.                            
+            ov/un;val1;n.u.;val3,vval4                                          
+ C    1.3817   4.0000  12.0000   1.8903   0.1838   0.9000   1.1341   4.0000     
+      9.7559   2.1346   4.0000  34.9350  79.5548   5.9666   7.0000   0.0000     
+      1.2114   0.0000 202.5551   8.9539  34.9289  13.5366   0.8563   0.0000     
+     -2.8983   2.5000   1.0564   4.0000   2.9663   0.0000   0.0000   0.0000     
+ H    0.8930   1.0000   1.0080   1.3550   0.0930   0.8203  -0.1000   1.0000     
+      8.2230  33.2894   1.0000   0.0000 121.1250   3.7248   9.6093   1.0000     
+     -0.1000   0.0000  61.6606   3.0408   2.4197   0.0003   3.4114   0.0000     
+    -19.4571   4.2733   1.0338   1.0000   2.8793   0.0000   0.0000   0.0000     
+ O    1.2450   2.0000  15.9990   2.3890   0.1000   1.0898   1.0548   6.0000     
+      9.7300  13.8449   4.0000  37.5000 116.0768   8.5000   8.3122   2.0000     
+      0.9049   0.4056  59.0626   3.5027   0.7640   0.0021   0.9745   0.0000     
+     -3.5500   2.9000   1.0493   4.0000   2.9225   0.0000   0.0000   0.0000     
+ N    1.2333   3.0000  14.0000   1.9324   0.1376   0.8596   1.1748   5.0000     
+     10.0667   7.8431   4.0000  32.2482 100.0000   6.8418   6.3404   2.0000     
+      1.0433  13.7673 119.9837   2.1961   3.0696   2.7683   0.9745   0.0000     
+     -4.3875   2.6192   1.0183   4.0000   2.8793   0.0000   0.0000   0.0000     
+ S    1.9405   2.0000  32.0600   2.0677   0.2099   1.0336   1.5479   6.0000     
+      9.9575   4.9055   4.0000  52.9998 112.1416   6.5000   8.2545   2.0000     
+      1.4601   9.7177  71.1843   5.7487  23.2859  12.7147   0.9745   0.0000     
+    -11.0000   2.7466   1.0338   6.2998   2.8793   0.0000   0.0000   0.0000     
+ Si   2.0276   4.0000  28.0600   2.2042   0.1322   0.8218   1.5758   4.0000     
+     11.9413   2.0618   4.0000  11.8211 136.4845   1.8038   7.3852   0.0000     
+     -1.0000   0.0000 126.5182   6.4918   8.5961   0.2368   0.8563   0.0000     
+     -3.8112   3.1873   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Pt   1.9907   3.0000 195.0800   1.9980   0.2452   0.8218  -1.0000   3.0000     
+     12.8669   3.2118   3.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000 142.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -6.7740   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Zr   2.1000   4.0000  91.2240   2.1970   0.2542   0.8218  -1.0000   4.0000     
+     12.8545   3.5938   4.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000 107.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -3.2224   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Ni   1.8503   2.0000  58.6900   1.9219   0.1582   0.8218  -1.0000   2.0000     
+     12.1238   4.0351   2.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000  95.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -3.2224   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Au   1.8503   1.0000 196.9665   1.9219   0.1582   0.8218  -1.0000   1.0000     
+     12.1238   4.0351   1.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000  72.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -3.2224   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ V    2.2657   3.0000  50.9415   1.7992   0.3005   0.6743   0.1000   5.0000     
+     12.3879   5.2243   3.0000   0.0000   0.0000  -0.3628   6.6023   0.0000     
+     -1.0000   0.0000 117.6300  23.1946   6.5795   0.0000   0.8563   0.0000     
+     -3.5389   1.5012   1.0338   3.0000   3.6411   0.0000   0.0000   0.0000     
+ Bi   2.1949   3.0000 208.9804   2.4429   0.1607   0.4960   0.0535   5.0000     
+     12.9571  35.5167   3.0000   0.0000   0.0000  -0.1926   6.4153   0.0000     
+     -1.0000   0.5785  52.6300   3.8978   0.9856   0.0314   0.8563   0.0000     
+     -2.5000   5.0597   1.0338   6.0000   2.5791   0.0000   0.0000   0.0000     
+ Ti   0.1000   4.0000  47.8800   2.0000   0.1659   0.6037   0.1000   4.0000     
+     13.2535   4.0063   4.0000  -5.0000   0.0000  -0.1864   5.9304   0.0000     
+     -1.0000   0.0000 129.6300  22.8461   1.8515   0.0064   0.8563   0.0000     
+     -3.4122   3.2711   1.0338   6.2998   2.2632   0.0000   0.0000   0.0000     
+ Mo   2.4710   5.6504  95.9400   1.8000   0.3285   1.0000   0.1000   6.0000     
+     13.0000  45.0000   4.0000   0.0000   0.0000   0.6062   6.1484   0.0000     
+      0.1000   0.0000 152.6300   3.7659   0.0689   2.9902   0.8563   0.0000     
+    -16.7660   3.1072   1.0338   8.0000   3.4590   0.0000   0.0000   0.0000     
+ X   -0.1000   2.0000   1.0080   2.0000   0.0000   1.0000  -0.1000   6.0000     
+     10.0000   2.5000   4.0000   0.0000   0.0000   8.5000   1.5000   0.0000     
+     -0.1000   0.0000  -2.3700   8.7410  13.3640   0.6690   0.9745   0.0000     
+    -11.0000   2.7466   1.0338   2.0000   2.8793   0.0000   0.0000   0.0000     
+ 40      ! Nr of bonds; Edis1;LPpen;n.u.;pbe1;pbo5;13corr;pbo6                  
+                         pbe2;pbo3;pbo4;n.u.;pbo1;pbo2;ovcorr                   
+  1  1 158.2004  99.1897  78.0000  -0.7738  -0.4550   1.0000  37.6117   0.4147  
+         0.4590  -0.1000   9.1628   1.0000  -0.0777   6.7268   1.0000   0.0000  
+  1  2 169.4760   0.0000   0.0000  -0.6083   0.0000   1.0000   6.0000   0.7652  
+         5.2290   1.0000   0.0000   1.0000  -0.0500   6.9136   0.0000   0.0000  
+  2  2 153.3934   0.0000   0.0000  -0.4600   0.0000   1.0000   6.0000   0.7300  
+         6.2500   1.0000   0.0000   1.0000  -0.0790   6.0552   0.0000   0.0000  
+  1  3 158.6946 107.4583  23.3136  -0.4240  -0.1743   1.0000  10.8209   1.0000  
+         0.5322  -0.3113   7.0000   1.0000  -0.1447   5.2450   0.0000   0.0000  
+  3  3 142.2858 145.0000  50.8293   0.2506  -0.1000   1.0000  29.7503   0.6051  
+         0.3451  -0.1055   9.0000   1.0000  -0.1225   5.5000   1.0000   0.0000  
+  1  4 134.1215 140.2179  79.9745   0.0163  -0.1428   1.0000  27.0617   0.2000  
+         0.1387  -0.3681   7.1611   1.0000  -0.1000   5.0825   1.0000   0.0000  
+  3  4 130.8596 169.4551  40.0000   0.3837  -0.1639   1.0000  35.0000   0.2000  
+         1.0000  -0.3579   7.0004   1.0000  -0.1193   6.8773   1.0000   0.0000  
+  4  4 157.9384  82.5526 152.5336   0.4010  -0.1034   1.0000  12.4261   0.5828  
+         0.1578  -0.1509  11.9186   1.0000  -0.0861   5.4271   1.0000   0.0000  
+  2  3 160.0000   0.0000   0.0000  -0.5725   0.0000   1.0000   6.0000   0.5626  
+         1.1150   1.0000   0.0000   0.0000  -0.0920   4.2790   0.0000   0.0000  
+  2  4 231.8173   0.0000   0.0000  -0.3364   0.0000   1.0000   6.0000   0.4402  
+         8.8910   1.0000   0.0000   1.0000  -0.0327   6.5754   0.0000   0.0000  
+  1  5 128.9942  74.5848  55.2528   0.1035  -0.5211   1.0000  18.9617   0.6000  
+         0.2949  -0.2398   8.1175   1.0000  -0.1029   5.6731   1.0000   0.0000  
+  2  5 151.5159   0.0000   0.0000  -0.4721   0.0000   1.0000   6.0000   0.6000  
+         9.4366   1.0000   0.0000   1.0000  -0.0290   7.0050   1.0000   0.0000  
+  3  5   0.0000   0.0000   0.0000   0.5563  -0.4038   1.0000  49.5611   0.6000  
+         0.4259  -0.4577  12.7569   1.0000  -0.1100   7.1145   1.0000   0.0000  
+  4  5   0.0000   0.0000   0.0000   0.4438  -0.2034   1.0000  40.3399   0.6000  
+         0.3296  -0.3153   9.1227   1.0000  -0.1805   5.6864   1.0000   0.0000  
+  5  5  96.1871  93.7006  68.6860   0.0955  -0.4781   1.0000  17.8574   0.6000  
+         0.2723  -0.2373   9.7875   1.0000  -0.0950   6.4757   1.0000   0.0000  
+  6  6 109.1904  70.8314  30.0000   0.2765  -0.3000   1.0000  16.0000   0.1583  
+         0.2804  -0.1994   8.1117   1.0000  -0.0675   8.2993   0.0000   0.0000  
+  2  6 137.1002   0.0000   0.0000  -0.1902   0.0000   1.0000   6.0000   0.4256  
+        17.7186   1.0000   0.0000   1.0000  -0.0377   6.4281   0.0000   0.0000  
+  3  6 191.1743  52.0733  43.3991  -0.2584  -0.3000   1.0000  36.0000   0.8764  
+         1.0248  -0.3658   4.2151   1.0000  -0.5004   4.2605   1.0000   0.0000  
+  4  6 185.4488  39.2832  43.3991  -0.1922  -0.3000   1.0000  36.0000   0.8217  
+         0.8538  -0.3887   4.4334   1.0000  -0.5241   4.4529   1.0000   0.0000  
+  7  7  90.1462   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.3484  
+         1.0000  -0.2000  15.0000   1.0000  -0.1014   5.7631   0.0000   0.0000  
+  8  8  85.2900   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.5438  
+         1.0000  -0.2000  15.0000   1.0000  -0.1001   5.5699   0.0000   0.0000  
+  9  9  73.6182   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.3418  
+         1.0000  -0.2000  15.0000   1.0000  -0.1015   5.7850   0.0000   0.0000  
+ 10 10  73.6182   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.3418  
+         1.0000  -0.2000  15.0000   1.0000  -0.1015   5.7850   0.0000   0.0000  
+ 11 11  36.2751   0.0000   0.0000   0.8059  -0.3000   0.0000  16.0000   0.1826  
+         0.3414  -0.3000  16.0000   1.0000  -0.0717   7.9108   0.0000   0.0000  
+  3 11 106.8008  67.5543   0.0000   0.0323  -0.3000   1.0000  36.0000   0.1000  
+         0.2670  -0.3402  16.0000   1.0000  -0.1761   4.6698   1.0000   0.0000  
+  2 11   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  1 11   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+ 12 12  66.0677   0.0000   0.0000  -0.9557  -0.2000   0.0000  16.0000   0.2865  
+         0.5847  -0.2000  15.0000   1.0000  -0.0856   5.2857   0.0000   0.0000  
+  3 12 152.2407  57.6204   0.0000  -0.8033  -0.3000   1.0000  36.0000   0.0498  
+         1.8097  -0.3800  16.0000   1.0000  -0.2379   8.0000   1.0000   0.0000  
+  2 12  95.9209   0.0000   0.0000  -0.0153  -0.3000   1.0000  36.0000   0.0100  
+         1.0000  -0.2062   8.6647   1.0000  -0.1911   4.0000   1.0000   0.0000  
+  1 12  78.9091  40.6322   0.0000   0.0040  -0.3000   1.0000  36.0000   0.0384  
+         0.0904  -0.1209  12.3682   1.0000  -0.1613   4.3849   1.0000   0.0000  
+ 13 13  71.3016  10.0000   0.0000  -0.1571  -0.2000   0.0000  16.0000   0.3311  
+         0.1822  -0.2000  15.0000   1.0000  -0.1860   6.5172   0.0000   0.0000  
+  3 13 112.7130  29.8084   0.0000  -0.9010  -0.3000   1.0000  36.0000   0.5508  
+         0.1006  -0.2492  16.9476   1.0000  -0.1919   5.4797   1.0000   0.0000  
+  1 13   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  2 13   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  1 14   0.5356   0.9614   0.0000   0.3817  -0.3000   1.0000  36.0000   0.2142  
+         0.6116  -0.2579   6.1366   1.0000  -0.0913   6.6008   1.0000   0.0000  
+  2 14   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.3027   4.6243   1.0000  -0.4578   3.5219   1.0000   0.0000  
+  3 14 112.7070  10.0000 135.5011   0.9277  -0.2354   1.0000  19.1731   1.2334  
+         0.9822  -0.1837   7.2216   1.0000  -0.1264   6.1257   1.0000   0.0000  
+ 14 14  44.6382   0.0000   0.0000   1.0000  -0.3000   0.0000  16.0000   0.2890  
+         0.3384  -0.3000  16.0000   1.0000  -0.1862   7.4588   0.0000   0.0000  
+ 12 14  50.0000   0.0000   0.0000   0.1000  -0.3000   0.0000  16.0000   0.3000  
+         1.0000  -0.3000  16.0000   1.0000  -0.2000   8.0000   0.0000   0.0000  
+ 20    ! Nr of off-diagonal terms; Ediss;Ro;gamma;rsigma;rpi;rpi2               
+  1  2   0.1239   1.4004   9.8467   1.1210  -1.0000  -1.0000                    
+  2  3   0.0283   1.2885  10.9190   0.9215  -1.0000  -1.0000                    
+  2  4   0.1059   1.8290   9.7818   0.9598  -1.0000  -1.0000                    
+  1  3   0.1156   1.8520   9.8317   1.2854   1.1352   1.0706                    
+  1  4   0.1447   1.8766   9.7990   1.3436   1.1885   1.1363                    
+  3  4   0.1048   2.0003  10.1220   1.3173   1.1096   1.0206                    
+  2  6   0.0470   1.6738  11.6877   1.1931  -1.0000  -1.0000                    
+  3  6   0.1263   1.8163  10.6833   1.6266   1.2052  -1.0000                    
+  1 11   0.1995   2.2133  13.0000   0.0102   1.4868  -1.0000                    
+  2 11   0.1319   1.5855  12.5457   0.0099   1.5065  -1.0000                    
+  3 11   0.0813   1.8649  10.8791   1.6498   1.6445  -1.0000                    
+  1 12   0.4235   1.7716  11.3664   1.8000   1.7212  -1.0000                    
+  2 12   0.0754   1.6033  12.4204   1.6896  -1.5000  -1.0000                    
+  3 12   0.1648   2.1260  11.2425   2.0692   1.6939  -1.0000                    
+  2 13   0.1340   1.8546  11.5784   1.0000  -1.0000  -1.0000                    
+  3 13   0.1280   1.8000  10.5743   1.7358   1.5296  -1.0000                    
+  1 13   0.1301   1.9382  11.1255   0.0100  -1.0000  -1.0000                    
+  1 14   0.1495   2.0794  12.2376   0.0100   1.4060  -1.0000                    
+  2 14   0.0795   1.6794  11.2376   0.0100   1.2060  -1.0000                    
+  3 14   0.2101   2.0342  10.4729   1.6019   1.4781   1.6548                    
+ 97    ! Nr of angles;at1;at2;at3;Thetao,o;ka;kb;pv1;pv2                        
+  1  1  1  59.0573  30.7029   0.7606   0.0000   0.7180   6.2933   1.1244        
+  1  1  2  65.7758  14.5234   6.2481   0.0000   0.5665   0.0000   1.6255        
+  2  1  2  70.2607  25.2202   3.7312   0.0000   0.0050   0.0000   2.7500        
+  1  2  2   0.0000   0.0000   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  2  1   0.0000   3.4110   7.7350   0.0000   0.0000   0.0000   1.0400        
+  2  2  2   0.0000  27.9213   5.8635   0.0000   0.0000   0.0000   1.0400        
+  1  1  3  49.6811   7.1713   4.3889   0.0000   0.7171  10.2661   1.0463        
+  3  1  3  77.7473  40.1718   2.9802 -25.3063   1.6170 -46.1315   2.2503        
+  1  1  4  66.1305  12.4661   7.0000   0.0000   3.0000  50.0000   1.1880        
+  3  1  4  73.9544  12.4661   7.0000   0.0000   3.0000   0.0000   1.1880        
+  4  1  4  64.1581  12.4661   7.0000   0.0000   3.0000   0.0000   1.1880        
+  2  1  3  65.0000  13.8815   5.0583   0.0000   0.4985   0.0000   1.4900        
+  2  1  4  74.2929  31.0883   2.6184   0.0000   0.0755   0.0000   1.0500        
+  1  2  4   0.0000   0.0019   6.3000   0.0000   0.0000   0.0000   1.0400        
+  1  3  1  73.5312  44.7275   0.7354   0.0000   3.0000   0.0000   1.0684        
+  1  3  3  79.4761  36.3701   1.8943   0.0000   0.7351  67.6777   3.0000        
+  1  3  4  82.4890  31.4554   0.9953   0.0000   1.6310   0.0000   1.0783        
+  3  3  3  80.7324  30.4554   0.9953   0.0000   1.6310  50.0000   1.0783        
+  3  3  4  84.3637  31.4554   0.9953   0.0000   1.6310   0.0000   1.0783        
+  4  3  4  89.7071  31.4554   0.9953   0.0000   1.6310   0.0000   1.1519        
+  1  3  2  70.1880  20.9562   0.3864   0.0000   0.0050   0.0000   1.6924        
+  2  3  3  75.6935  50.0000   2.0000   0.0000   1.0000   0.0000   1.1680        
+  2  3  4  75.6201  18.7919   0.9833   0.0000   0.1218   0.0000   1.0500        
+  2  3  2  85.8000   9.8453   2.2720   0.0000   2.8635   0.0000   1.5800        
+  1  4  1  66.0330  22.0295   1.4442   0.0000   1.6777   0.0000   1.0500        
+  1  4  3 103.3204  33.0381   0.5787   0.0000   1.6777   0.0000   1.0500        
+  1  4  4 104.1335   8.6043   1.6495   0.0000   1.6777   0.0000   1.0500        
+  3  4  3  74.1978  42.1786   1.7845 -18.0069   1.6777   0.0000   1.0500        
+  3  4  4  74.8600  43.7354   1.1572  -0.9193   1.6777   0.0000   1.0500        
+  4  4  4  75.0538  14.8267   5.2794   0.0000   1.6777   0.0000   1.0500        
+  1  4  2  69.1106  25.5067   1.1003   0.0000   0.0222   0.0000   1.0369        
+  2  4  3  81.3686  40.0712   2.2396   0.0000   0.0222   0.0000   1.0369        
+  2  4  4  83.0104  43.4766   1.5328   0.0000   0.0222   0.0000   1.0500        
+  2  4  2  70.8687  12.0168   5.0132   0.0000   0.0222   0.0000   1.1243        
+  1  2  3   0.0000  25.0000   3.0000   0.0000   1.0000   0.0000   1.0400        
+  1  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  2  5   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  3  2  3   0.0000  15.0000   2.8900   0.0000   0.0000   0.0000   2.8774        
+  3  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  4  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  2  2  3   0.0000   8.5744   3.0000   0.0000   0.0000   0.0000   1.0421        
+  2  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  1  5  74.9397  25.0560   1.8787   0.1463   0.0559   0.0000   1.0400        
+  1  5  1  86.9521  36.9951   2.0903   0.1463   0.0559   0.0000   1.0400        
+  2  1  5  74.9397  25.0560   1.8787   0.0000   0.0000   0.0000   1.0400        
+  1  5  2  86.1791  36.9951   2.0903   0.0000   0.0000   0.0000   1.0400        
+  1  5  5  85.3644  36.9951   2.0903   0.1463   0.0559   0.0000   1.0400        
+  2  5  2  93.1959  36.9951   2.0903   0.0000   0.0000   0.0000   1.0400        
+  2  5  5  84.3331  36.9951   2.0903   0.0000   0.0000   0.0000   1.0400        
+  6  6  6  69.3456  21.7361   1.4283   0.0000  -0.2101   0.0000   1.3241        
+  2  6  6  75.6168  21.5317   1.0435   0.0000   2.5179   0.0000   1.0400        
+  2  6  2  78.3939  20.9772   0.8630   0.0000   2.8421   0.0000   1.0400        
+  3  6  6  70.3016  15.4081   1.3267   0.0000   2.1459   0.0000   1.0400        
+  2  6  3  73.8232  16.6592   3.7425   0.0000   0.8613   0.0000   1.0400        
+  3  6  3  90.0344   7.7656   1.7264   0.0000   0.7689   0.0000   1.0400        
+  6  3  6  22.1715   3.6615   0.3160   0.0000   4.1125   0.0000   1.0400        
+  2  3  6  83.7634   5.6693   2.7780   0.0000   1.6982   0.0000   1.0400        
+  3  3  6  73.4663  25.0761   0.9143   0.0000   2.2466   0.0000   1.0400        
+  2  2  6   0.0000  47.1300   6.0000   0.0000   1.6371   0.0000   1.0400        
+  6  2  6   0.0000  31.5209   6.0000   0.0000   1.6371   0.0000   1.0400        
+  3  2  6   0.0000  31.0427   4.5625   0.0000   1.6371   0.0000   1.0400        
+  2  2  5   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  3 11  3  62.4906  31.5023   1.3328   0.0000   2.8731   0.0000   1.0794        
+ 11  3 11  31.0790  19.3435   0.4919   0.0000   2.9625   0.0000   3.0000        
+  3  3 11 100.0000  14.7642   7.0000   0.0000   1.0585   0.0000   1.1599        
+  1  3 11  60.7895  13.6681   0.7546   0.0000   2.1747   0.0000   2.9508        
+  2  3 11 100.0000   5.0000   1.4335   0.0000   1.2363   0.0000   5.0000        
+  3 12 12  23.8296   8.9089   7.0000   0.0000   1.0000   0.0000   2.8891        
+  3 12  3  87.0764  19.4489   2.5080   0.0000   2.6056   0.0000   3.0000        
+ 12  3 12  72.7369  13.7522   5.0243   0.0000   2.9700   0.0000   1.5506        
+  3  3 12  68.8771  10.5000   2.5500   0.0000   2.5729   0.0000   1.5892        
+  2  3 12  99.5836   5.4142   2.2105   0.0000   1.0513   0.0000   1.1000        
+  1  3 12  90.0000  12.1772   2.2055   0.0000   1.9064   0.0000   2.6056        
+  1  1 12  71.1708  32.6379   0.4516   0.0000   2.1609   0.0000   1.1000        
+  1 12  3  90.0000  45.0000   0.9335   0.0000   0.2140   0.0000   1.4846        
+  1 12  1  87.6204  45.0000   1.2740   0.0000   1.1519   0.0000   1.1000        
+  3  1 12  54.7020   3.2967   7.0000   0.0000   2.0408   0.0000   2.4032        
+  2 12  3  90.0000  28.2099   1.8036   0.0000   1.5461   0.0000   1.2304        
+  2 12  2  90.0000  36.3001   0.6409   0.0000   3.0000   0.0000   1.7755        
+  1 12  2  89.5835  45.0000   0.8465   0.0000   1.2118   0.0000   2.2282        
+  2  1 12  68.7714  22.9669   0.4631   0.0000   2.4269   0.0000   1.4680        
+  2  2 12   0.0000  30.2898   3.9181   0.0000   0.9914   0.0000   1.3121        
+  3  2 12   0.0000   1.0000   4.1706   0.0000   1.0100   0.0000   1.1000        
+  1  2 12   0.0000   1.0000   3.9722   0.0000   1.0075   0.0000   1.2984        
+  3 13  3  73.6321  10.6453   2.7693   0.0000   0.0500   0.0000   1.9906        
+ 13  3 13 100.0000   5.0270   5.0000   0.0000   1.2768   0.0000   2.0630        
+  3  3 13  52.3127  40.0000   1.1362   0.0000   1.5100   0.0000   1.1000        
+  3 13 13  66.6695   0.0036   3.2646   0.0000   0.0581   0.0000   1.3741        
+  2  3 13 100.0000   3.8927   8.0000   0.0000   2.0000   0.0000   1.1000        
+  1  3 13  96.6040   9.4537   8.0000   0.0000   0.3285   0.0000   4.0000        
+  3 14  3  79.6765  50.0000   1.0502  -0.0016   0.1000   0.0000   1.4583        
+ 14  3 14  20.2100  37.6165   0.6059   0.0000   0.1531   0.0000   2.0586        
+  3  3 14  38.5570  11.9307   0.9911   0.0000   0.8422   0.0000   1.0500        
+  3 14 14   5.8342   0.0724   0.1000   0.0000   0.5490   0.0000   1.7839        
+  2  3 14  81.8943   7.2820   2.1490   0.0000   0.6873   0.0000   3.2184        
+  1  3 14  75.5634   8.3289   1.0236   0.0000   2.0875   0.0000   1.0500        
+ 12  3 14  30.0000   5.0000   0.5000   0.0000   0.5000   0.0000   1.2500        
+ 47    ! Nr of torsions;at1;at2;at3;at4;;V1;V2;V3;V2(BO);vconj;n.u;n            
+  1  1  1  1  -0.2500  34.7453   0.0288  -6.3507  -1.6000   0.0000   0.0000     
+  1  1  1  2  -0.2500  29.2131   0.2945  -4.9581  -2.1802   0.0000   0.0000     
+  2  1  1  2  -0.2500  31.2081   0.4539  -4.8923  -2.2677   0.0000   0.0000     
+  1  1  1  3  -0.3495  22.2142  -0.2959  -2.5000  -1.9066   0.0000   0.0000     
+  2  1  1  3   0.0646  24.3195   0.6259  -3.9603  -1.0000   0.0000   0.0000     
+  3  1  1  3  -0.5456   5.5756   0.8433  -5.1924  -1.0180   0.0000   0.0000     
+  1  1  3  1   1.7555  27.9267   0.0072  -2.6533  -1.0000   0.0000   0.0000     
+  1  1  3  2  -1.4358  36.7830  -1.0000  -8.1821  -1.0000   0.0000   0.0000     
+  2  1  3  1  -1.3959  34.5053   0.7200  -2.5714  -2.1641   0.0000   0.0000     
+  2  1  3  2  -2.5000  70.0597   1.0000  -3.5539  -2.9929   0.0000   0.0000     
+  1  1  3  3   0.6852  11.2819  -0.4784  -2.5000  -2.1085   0.0000   0.0000     
+  2  1  3  3   0.1933  80.0000   1.0000  -4.0590  -3.0000   0.0000   0.0000     
+  3  1  3  1  -1.9889  76.4820  -0.1796  -3.8301  -3.0000   0.0000   0.0000     
+  3  1  3  2   0.2160  72.7707  -0.7087  -4.2100  -3.0000   0.0000   0.0000     
+  3  1  3  3  -2.5000  71.0772   0.2542  -3.1631  -3.0000   0.0000   0.0000     
+  1  3  3  1   2.5000  -0.6002   1.0000  -3.4297  -2.8858   0.0000   0.0000     
+  1  3  3  2  -2.5000  -3.3822   0.7004  -5.4467  -2.9586   0.0000   0.0000     
+  2  3  3  2   2.5000  -4.0000   0.9000  -2.5000  -1.0000   0.0000   0.0000     
+  1  3  3  3   1.2329  -4.0000   1.0000  -2.5000  -1.7479   0.0000   0.0000     
+  2  3  3  3   0.8302  -4.0000  -0.7763  -2.5000  -1.0000   0.0000   0.0000     
+  3  3  3  3  -2.5000  -4.0000   1.0000  -2.5000  -1.0000   0.0000   0.0000     
+  0  1  2  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  2  2  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  2  3  0   0.0000   0.1000   0.0200  -2.5415   0.0000   0.0000   0.0000     
+  0  1  1  0   0.0000  50.0000   0.3000  -4.0000  -2.0000   0.0000   0.0000     
+  0  3  3  0   0.5511  25.4150   1.1330  -5.1903  -1.0000   0.0000   0.0000     
+  0  1  4  0  -2.4242 128.1636   0.3739  -6.6098  -2.0000   0.0000   0.0000     
+  0  2  4  0   0.0000   0.1000   0.0200  -2.5415   0.0000   0.0000   0.0000     
+  0  3  4  0   1.4816  55.6641   0.0004  -7.0465  -2.7203   0.0000   0.0000     
+  0  4  4  0  -0.3244  27.7086   0.0039  -2.8272  -2.0000   0.0000   0.0000     
+  4  1  4  4  -5.5181   8.9706   0.0004  -6.1782  -2.0000   0.0000   0.0000     
+  0  1  5  0   3.3423  30.3435   0.0365  -2.7171   0.0000   0.0000   0.0000     
+  0  5  5  0  -0.0555 -42.7738   0.1515  -2.2056   0.0000   0.0000   0.0000     
+  0  2  5  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  6  6  0   0.0000   0.0000   0.1200  -2.4426   0.0000   0.0000   0.0000     
+  0  2  6  0   0.0000   0.0000   0.1200  -2.4847   0.0000   0.0000   0.0000     
+  0  3  6  0   0.0000   0.0000   0.1200  -2.4703   0.0000   0.0000   0.0000     
+  2  1  3 14   1.6297  56.8132   0.3398  -2.6912  -2.1000   0.0000   0.0000     
+  1  1  3 14  -0.0427  13.4096   0.9351  -6.5245  -2.1000   0.0000   0.0000     
+  2  3 14  3   2.5000  11.6208   1.0000  -9.0000  -1.0000   0.0000   0.0000     
+  2  1  3 12  -0.2500  45.7639   0.3000  -3.5745  -2.1565   0.0000   0.0000     
+  1  1  3 12  -0.2500  69.1094   0.3000  -3.0983  -2.1565   0.0000   0.0000     
+  2  3 12  3  -0.4306   7.5000  -0.5000  -6.9948  -1.0000   0.0000   0.0000     
+  2  3 11  3   1.8627   9.7180  -1.0000  -7.2224  -1.0000   0.0000   0.0000     
+  1  3 11  3   2.5000  23.9443   1.0000  -3.2267  -1.0000   0.0000   0.0000     
+  1  1  3 11   0.9114  62.5039  -0.2389  -3.2976  -1.0000   0.0000   0.0000     
+  2  1  3 11   0.5000  35.0000   0.5000  -4.0000  -1.0000   0.0000   0.0000     
+  9    ! Nr of hydrogen bonds;at1;at2;at3;Rhb;Dehb;vhb1                         
+  3  2  3   2.1200  -3.5800   1.4500  19.5000                                   
+  3  2  4   2.0000  -6.0000   1.7976   3.0000                                   
+  4  2  3   1.2000  -2.0000   1.7976   3.0000                                   
+  4  2  4   1.2979  -6.0000   1.7976   3.0000                                   
+  3  2  5   1.5000  -2.0000   1.7976   3.0000                                   
+  4  2  5   1.5000  -2.0000   1.7976   3.0000                                   
+  5  2  3   1.5000  -2.0000   1.7976   3.0000                                   
+  5  2  4   1.5000  -2.0000   1.7976   3.0000                                   
+  5  2  5   1.5000  -2.0000   1.7976   3.0000                                   
diff --git a/data/benchmarks/water/ffield_acks2_300.water b/data/benchmarks/water/ffield_acks2_300.water
new file mode 100644
index 0000000000000000000000000000000000000000..d4d7b7b94777b6c456acb5bc1ad1e40dcfaa4da0
--- /dev/null
+++ b/data/benchmarks/water/ffield_acks2_300.water
@@ -0,0 +1,364 @@
+Reactive MD-force field: Water                                                  
+ 39       ! Number of general parameters                                        
+   50.0000 !Overcoordination parameter                                          
+    9.5469 !Overcoordination parameter                                          
+   26.5405 !Valency angle conjugation parameter                                 
+    1.7224 !Triple bond stabilisation parameter                                 
+    6.8702 !Triple bond stabilisation parameter                                 
+   60.4850 !C2-correction                                                       
+    1.0588 !Undercoordination parameter                                         
+    4.6000 !Triple bond stabilisation parameter                                 
+   12.1176 !Undercoordination parameter                                         
+   13.3056 !Undercoordination parameter                                         
+  -70.5044 !Triple bond stabilization energy                                    
+    0.0000 !Lower Taper-radius                                                  
+   10.0000 !Upper Taper-radius                                                  
+    2.8793 !Not used                                                            
+   33.8667 !Valency undercoordination                                           
+    6.0891 !Valency angle/lone pair parameter                                   
+    1.0563 !Valency angle                                                       
+    2.0384 !Valency angle parameter                                             
+    6.1431 !Not used                                                            
+    6.9290 !Double bond/angle parameter                                         
+    0.3989 !Double bond/angle parameter: overcoord                              
+    3.9954 !Double bond/angle parameter: overcoord                              
+   -2.4837 !Not used                                                            
+    5.7796 !Torsion/BO parameter                                                
+   10.0000 !Torsion overcoordination                                            
+    1.9487 !Torsion overcoordination                                            
+   -1.2327 !Conjugation 0 (not used)                                            
+    2.1645 !Conjugation                                                         
+    1.5591 !vdWaals shielding                                                   
+    0.1000 !Cutoff for bond order (*100)                                        
+    2.1365 !Valency angle conjugation parameter                                 
+    0.6991 !Overcoordination parameter                                          
+   50.0000 !Overcoordination parameter                                          
+    1.8512 !Valency/lone pair parameter                                         
+  548.6451 !Softness                                                            
+   20.0000 !Not used                                                            
+    5.0000 !Molecular energy (not used)                                         
+    0.0000 !Molecular energy (not used)                                         
+    2.6962 !Valency angle conjugation parameter                                 
+ 15    ! Nr of atoms; cov.r; valency;a.m;Rvdw;Evdw;gammaEEM;cov.r2;#            
+            alfa;gammavdW;valency;Eunder;Eover;chiEEM;etaEEM;n.u.               
+            cov r3;Elp;Heat inc.;n.u.;n.u.;n.u.;n.u.                            
+            ov/un;val1;n.u.;val3,vval4                                          
+ C    1.3817   4.0000  12.0000   1.8903   0.1838   0.9000   1.1341   4.0000     
+      9.7559   2.1346   4.0000  34.9350  79.5548   5.9666   7.0000   0.0000     
+      1.2114   0.0000 202.5551   8.9539  34.9289  13.5366   0.8563   0.0000     
+     -2.8983   2.5000   1.0564   4.0000   2.9663   0.0000   0.0000   0.0000     
+ H    0.8873   1.0000   1.0080   1.5420   0.0598   0.6883  -0.1000   1.0000     
+      8.1910  30.9706   1.0000   0.0000 121.1250   3.5768  10.5896   1.0000     
+     -0.1000   0.0000  61.6606   1.3986   2.1457   0.0003   3.4114   0.0000     
+    -15.7683   2.1488   1.0338   1.0000   2.8793   0.0000   0.0000   0.0000     
+ O    1.2450   2.0000  15.9990   2.3878   0.1023   1.0903   1.0548   6.0000     
+     10.5750  32.3923   4.0000  37.5000 116.0768   8.5000   7.5600   2.0000     
+      0.9049  -1.0100  59.0626   2.7162   3.2532   0.0021   0.9745   0.0000     
+     -3.6141   2.7025   1.0493   4.0000   2.9225   0.0000   5.4479   0.0000     
+ N    1.2333   3.0000  14.0000   1.9324   0.1376   0.8596   1.1748   5.0000     
+     10.0667   7.8431   4.0000  32.2482 100.0000   6.8418   6.3404   2.0000     
+      1.0433  13.7673 119.9837   2.1961   3.0696   2.7683   0.9745   0.0000     
+     -4.3875   2.6192   1.0183   4.0000   2.8793   0.0000   0.0000   0.0000     
+ S    1.9405   2.0000  32.0600   2.0677   0.2099   1.0336   1.5479   6.0000     
+      9.9575   4.9055   4.0000  52.9998 112.1416   6.5000   8.2545   2.0000     
+      1.4601   9.7177  71.1843   5.7487  23.2859  12.7147   0.9745   0.0000     
+    -11.0000   2.7466   1.0338   6.2998   2.8793   0.0000   0.0000   0.0000     
+ Si   2.0276   4.0000  28.0600   2.2042   0.1322   0.8218   1.5758   4.0000     
+     11.9413   2.0618   4.0000  11.8211 136.4845   1.8038   7.3852   0.0000     
+     -1.0000   0.0000 126.5182   6.4918   8.5961   0.2368   0.8563   0.0000     
+     -3.8112   3.1873   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Pt   1.9907   3.0000 195.0800   1.9980   0.2452   0.8218  -1.0000   3.0000     
+     12.8669   3.2118   3.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000 142.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -6.7740   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Zr   2.1000   4.0000  91.2240   2.1970   0.2542   0.8218  -1.0000   4.0000     
+     12.8545   3.5938   4.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000 107.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -3.2224   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Ni   1.8503   2.0000  58.6900   1.9219   0.1582   0.8218  -1.0000   2.0000     
+     12.1238   4.0351   2.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000  95.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -3.2224   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ Au   1.8503   1.0000 196.9665   1.9219   0.1582   0.8218  -1.0000   1.0000     
+     12.1238   4.0351   1.0000   0.0000   0.0000   1.8038   7.3852   0.0000     
+     -1.0000   0.0000  72.6300   6.2293   5.2294   0.1542   0.8563   0.0000     
+     -3.2224   2.9867   1.0338   6.2998   2.5791   0.0000   0.0000   0.0000     
+ V    2.2657   3.0000  50.9415   1.7992   0.3005   0.6743   0.1000   5.0000     
+     12.3879   5.2243   3.0000   0.0000   0.0000  -0.3628   6.6023   0.0000     
+     -1.0000   0.0000 117.6300  23.1946   6.5795   0.0000   0.8563   0.0000     
+     -3.5389   1.5012   1.0338   3.0000   3.6411   0.0000   0.0000   0.0000     
+ Bi   2.1949   3.0000 208.9804   2.4429   0.1607   0.4960   0.0535   5.0000     
+     12.9571  35.5167   3.0000   0.0000   0.0000  -0.1926   6.4153   0.0000     
+     -1.0000   0.5785  52.6300   3.8978   0.9856   0.0314   0.8563   0.0000     
+     -2.5000   5.0597   1.0338   6.0000   2.5791   0.0000   0.0000   0.0000     
+ Ti   0.1000   4.0000  47.8800   2.0000   0.1659   0.6037   0.1000   4.0000     
+     13.2535   4.0063   4.0000  -5.0000   0.0000  -0.1864   5.9304   0.0000     
+     -1.0000   0.0000 129.6300  22.8461   1.8515   0.0064   0.8563   0.0000     
+     -3.4122   3.2711   1.0338   6.2998   2.2632   0.0000   0.0000   0.0000     
+ Mo   2.4710   5.6504  95.9400   1.8000   0.3285   1.0000   0.1000   6.0000     
+     13.0000  45.0000   4.0000   0.0000   0.0000   0.6062   6.1484   0.0000     
+      0.1000   0.0000 152.6300   3.7659   0.0689   2.9902   0.8563   0.0000     
+    -16.7660   3.1072   1.0338   8.0000   3.4590   0.0000   0.0000   0.0000     
+ X   -0.1000   2.0000   1.0080   2.0000   0.0000   1.0000  -0.1000   6.0000     
+     10.0000   2.5000   4.0000   0.0000   0.0000   8.5000   1.5000   0.0000     
+     -0.1000   0.0000  -2.3700   8.7410  13.3640   0.6690   0.9745   0.0000     
+    -11.0000   2.7466   1.0338   2.0000   2.8793   0.0000   0.0000   0.0000     
+ 40      ! Nr of bonds; Edis1;LPpen;n.u.;pbe1;pbo5;13corr;pbo6                  
+                         pbe2;pbo3;pbo4;n.u.;pbo1;pbo2;ovcorr                   
+  1  1 158.2004  99.1897  78.0000  -0.7738  -0.4550   1.0000  37.6117   0.4147  
+         0.4590  -0.1000   9.1628   1.0000  -0.0777   6.7268   1.0000   0.0000  
+  1  2 169.4760   0.0000   0.0000  -0.6083   0.0000   1.0000   6.0000   0.7652  
+         5.2290   1.0000   0.0000   1.0000  -0.0500   6.9136   0.0000   0.0000  
+  2  2 166.8880   0.0000   0.0000  -0.2191   0.0000   1.0000   6.0000   1.0000  
+         6.1152   1.0000   0.0000   1.0000  -0.0889   6.0000   0.0000   0.0000  
+  1  3 158.6946 107.4583  23.3136  -0.4240  -0.1743   1.0000  10.8209   1.0000  
+         0.5322  -0.3113   7.0000   1.0000  -0.1447   5.2450   0.0000   0.0000  
+  3  3 200.0000 230.7321  50.8293   0.2506  -0.1000   1.0000  29.7503   0.6051  
+         0.3451  -0.1055   9.0000   1.0000  -0.1225   5.5000   1.0000   0.0000  
+  1  4 134.1215 140.2179  79.9745   0.0163  -0.1428   1.0000  27.0617   0.2000  
+         0.1387  -0.3681   7.1611   1.0000  -0.1000   5.0825   1.0000   0.0000  
+  3  4 130.8596 169.4551  40.0000   0.3837  -0.1639   1.0000  35.0000   0.2000  
+         1.0000  -0.3579   7.0004   1.0000  -0.1193   6.8773   1.0000   0.0000  
+  4  4 157.9384  82.5526 152.5336   0.4010  -0.1034   1.0000  12.4261   0.5828  
+         0.1578  -0.1509  11.9186   1.0000  -0.0861   5.4271   1.0000   0.0000  
+  2  3 163.1043   0.0000   0.0000  -0.4155   0.0000   1.0000   6.0000   0.3607  
+         1.9380   1.0000   0.0000   0.0000  -0.0778   4.3082   0.0000   0.0000  
+  2  4 231.8173   0.0000   0.0000  -0.3364   0.0000   1.0000   6.0000   0.4402  
+         8.8910   1.0000   0.0000   1.0000  -0.0327   6.5754   0.0000   0.0000  
+  1  5 128.9942  74.5848  55.2528   0.1035  -0.5211   1.0000  18.9617   0.6000  
+         0.2949  -0.2398   8.1175   1.0000  -0.1029   5.6731   1.0000   0.0000  
+  2  5 151.5159   0.0000   0.0000  -0.4721   0.0000   1.0000   6.0000   0.6000  
+         9.4366   1.0000   0.0000   1.0000  -0.0290   7.0050   1.0000   0.0000  
+  3  5   0.0000   0.0000   0.0000   0.5563  -0.4038   1.0000  49.5611   0.6000  
+         0.4259  -0.4577  12.7569   1.0000  -0.1100   7.1145   1.0000   0.0000  
+  4  5   0.0000   0.0000   0.0000   0.4438  -0.2034   1.0000  40.3399   0.6000  
+         0.3296  -0.3153   9.1227   1.0000  -0.1805   5.6864   1.0000   0.0000  
+  5  5  96.1871  93.7006  68.6860   0.0955  -0.4781   1.0000  17.8574   0.6000  
+         0.2723  -0.2373   9.7875   1.0000  -0.0950   6.4757   1.0000   0.0000  
+  6  6 109.1904  70.8314  30.0000   0.2765  -0.3000   1.0000  16.0000   0.1583  
+         0.2804  -0.1994   8.1117   1.0000  -0.0675   8.2993   0.0000   0.0000  
+  2  6 137.1002   0.0000   0.0000  -0.1902   0.0000   1.0000   6.0000   0.4256  
+        17.7186   1.0000   0.0000   1.0000  -0.0377   6.4281   0.0000   0.0000  
+  3  6 191.1743  52.0733  43.3991  -0.2584  -0.3000   1.0000  36.0000   0.8764  
+         1.0248  -0.3658   4.2151   1.0000  -0.5004   4.2605   1.0000   0.0000  
+  4  6 185.4488  39.2832  43.3991  -0.1922  -0.3000   1.0000  36.0000   0.8217  
+         0.8538  -0.3887   4.4334   1.0000  -0.5241   4.4529   1.0000   0.0000  
+  7  7  90.1462   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.3484  
+         1.0000  -0.2000  15.0000   1.0000  -0.1014   5.7631   0.0000   0.0000  
+  8  8  85.2900   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.5438  
+         1.0000  -0.2000  15.0000   1.0000  -0.1001   5.5699   0.0000   0.0000  
+  9  9  73.6182   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.3418  
+         1.0000  -0.2000  15.0000   1.0000  -0.1015   5.7850   0.0000   0.0000  
+ 10 10  73.6182   0.0000   0.0000   0.0004  -0.2000   0.0000  16.0000   0.3418  
+         1.0000  -0.2000  15.0000   1.0000  -0.1015   5.7850   0.0000   0.0000  
+ 11 11  36.2751   0.0000   0.0000   0.8059  -0.3000   0.0000  16.0000   0.1826  
+         0.3414  -0.3000  16.0000   1.0000  -0.0717   7.9108   0.0000   0.0000  
+  3 11 106.8008  67.5543   0.0000   0.0323  -0.3000   1.0000  36.0000   0.1000  
+         0.2670  -0.3402  16.0000   1.0000  -0.1761   4.6698   1.0000   0.0000  
+  2 11   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  1 11   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+ 12 12  66.0677   0.0000   0.0000  -0.9557  -0.2000   0.0000  16.0000   0.2865  
+         0.5847  -0.2000  15.0000   1.0000  -0.0856   5.2857   0.0000   0.0000  
+  3 12 152.2407  57.6204   0.0000  -0.8033  -0.3000   1.0000  36.0000   0.0498  
+         1.8097  -0.3800  16.0000   1.0000  -0.2379   8.0000   1.0000   0.0000  
+  2 12  95.9209   0.0000   0.0000  -0.0153  -0.3000   1.0000  36.0000   0.0100  
+         1.0000  -0.2062   8.6647   1.0000  -0.1911   4.0000   1.0000   0.0000  
+  1 12  78.9091  40.6322   0.0000   0.0040  -0.3000   1.0000  36.0000   0.0384  
+         0.0904  -0.1209  12.3682   1.0000  -0.1613   4.3849   1.0000   0.0000  
+ 13 13  71.3016  10.0000   0.0000  -0.1571  -0.2000   0.0000  16.0000   0.3311  
+         0.1822  -0.2000  15.0000   1.0000  -0.1860   6.5172   0.0000   0.0000  
+  3 13 112.7130  29.8084   0.0000  -0.9010  -0.3000   1.0000  36.0000   0.5508  
+         0.1006  -0.2492  16.9476   1.0000  -0.1919   5.4797   1.0000   0.0000  
+  1 13   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  2 13   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.2500  20.0000   1.0000  -0.2578   6.5219   1.0000   0.0000  
+  1 14   0.5356   0.9614   0.0000   0.3817  -0.3000   1.0000  36.0000   0.2142  
+         0.6116  -0.2579   6.1366   1.0000  -0.0913   6.6008   1.0000   0.0000  
+  2 14   0.0000   0.0000   0.0000  -0.2872  -0.3000   1.0000  36.0000   0.0082  
+         1.7973  -0.3027   4.6243   1.0000  -0.4578   3.5219   1.0000   0.0000  
+  3 14 112.7070  10.0000 135.5011   0.9277  -0.2354   1.0000  19.1731   1.2334  
+         0.9822  -0.1837   7.2216   1.0000  -0.1264   6.1257   1.0000   0.0000  
+ 14 14  44.6382   0.0000   0.0000   1.0000  -0.3000   0.0000  16.0000   0.2890  
+         0.3384  -0.3000  16.0000   1.0000  -0.1862   7.4588   0.0000   0.0000  
+ 12 14  50.0000   0.0000   0.0000   0.1000  -0.3000   0.0000  16.0000   0.3000  
+         1.0000  -0.3000  16.0000   1.0000  -0.2000   8.0000   0.0000   0.0000  
+ 20    ! Nr of off-diagonal terms; Ediss;Ro;gamma;rsigma;rpi;rpi2               
+  1  2   0.1239   1.4004   9.8467   1.1210  -1.0000  -1.0000                    
+  2  3   0.0299   1.3153  10.9102   0.9093  -1.0000  -1.0000                    
+  2  4   0.1059   1.8290   9.7818   0.9598  -1.0000  -1.0000                    
+  1  3   0.1156   1.8520   9.8317   1.2854   1.1352   1.0706                    
+  1  4   0.1447   1.8766   9.7990   1.3436   1.1885   1.1363                    
+  3  4   0.1048   2.0003  10.1220   1.3173   1.1096   1.0206                    
+  2  6   0.0470   1.6738  11.6877   1.1931  -1.0000  -1.0000                    
+  3  6   0.1263   1.8163  10.6833   1.6266   1.2052  -1.0000                    
+  1 11   0.1995   2.2133  13.0000   0.0102   1.4868  -1.0000                    
+  2 11   0.1319   1.5855  12.5457   0.0099   1.5065  -1.0000                    
+  3 11   0.0813   1.8649  10.8791   1.6498   1.6445  -1.0000                    
+  1 12   0.4235   1.7716  11.3664   1.8000   1.7212  -1.0000                    
+  2 12   0.0754   1.6033  12.4204   1.6896  -1.5000  -1.0000                    
+  3 12   0.1648   2.1260  11.2425   2.0692   1.6939  -1.0000                    
+  2 13   0.1340   1.8546  11.5784   1.0000  -1.0000  -1.0000                    
+  3 13   0.1280   1.8000  10.5743   1.7358   1.5296  -1.0000                    
+  1 13   0.1301   1.9382  11.1255   0.0100  -1.0000  -1.0000                    
+  1 14   0.1495   2.0794  12.2376   0.0100   1.4060  -1.0000                    
+  2 14   0.0795   1.6794  11.2376   0.0100   1.2060  -1.0000                    
+  3 14   0.2101   2.0342  10.4729   1.6019   1.4781   1.6548                    
+ 97    ! Nr of angles;at1;at2;at3;Thetao,o;ka;kb;pv1;pv2                        
+  1  1  1  59.0573  30.7029   0.7606   0.0000   0.7180   6.2933   1.1244        
+  1  1  2  65.7758  14.5234   6.2481   0.0000   0.5665   0.0000   1.6255        
+  2  1  2  70.2607  25.2202   3.7312   0.0000   0.0050   0.0000   2.7500        
+  1  2  2   0.0000   0.0000   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  2  1   0.0000   3.4110   7.7350   0.0000   0.0000   0.0000   1.0400        
+  2  2  2   0.0000  27.9213   5.8635   0.0000   0.0000   0.0000   1.0400        
+  1  1  3  49.6811   7.1713   4.3889   0.0000   0.7171  10.2661   1.0463        
+  3  1  3  77.7473  40.1718   2.9802 -25.3063   1.6170 -46.1315   2.2503        
+  1  1  4  66.1305  12.4661   7.0000   0.0000   3.0000  50.0000   1.1880        
+  3  1  4  73.9544  12.4661   7.0000   0.0000   3.0000   0.0000   1.1880        
+  4  1  4  64.1581  12.4661   7.0000   0.0000   3.0000   0.0000   1.1880        
+  2  1  3  65.0000  13.8815   5.0583   0.0000   0.4985   0.0000   1.4900        
+  2  1  4  74.2929  31.0883   2.6184   0.0000   0.0755   0.0000   1.0500        
+  1  2  4   0.0000   0.0019   6.3000   0.0000   0.0000   0.0000   1.0400        
+  1  3  1  73.5312  44.7275   0.7354   0.0000   3.0000   0.0000   1.0684        
+  1  3  3  79.4761  36.3701   1.8943   0.0000   0.7351  67.6777   3.0000        
+  1  3  4  82.4890  31.4554   0.9953   0.0000   1.6310   0.0000   1.0783        
+  3  3  3  80.7324  30.4554   0.9953   0.0000   1.6310  50.0000   1.0783        
+  3  3  4  84.3637  31.4554   0.9953   0.0000   1.6310   0.0000   1.0783        
+  4  3  4  89.7071  31.4554   0.9953   0.0000   1.6310   0.0000   1.1519        
+  1  3  2  70.1880  20.9562   0.3864   0.0000   0.0050   0.0000   1.6924        
+  2  3  3  75.6935  25.0000   2.0000   0.0000   1.0000   0.0000   1.1680        
+  2  3  4  75.6201  18.7919   0.9833   0.0000   0.1218   0.0000   1.0500        
+  2  3  2  77.3619   4.8342   7.1628   0.0000   2.9933   0.0000   1.5948        
+  1  4  1  66.0330  22.0295   1.4442   0.0000   1.6777   0.0000   1.0500        
+  1  4  3 103.3204  33.0381   0.5787   0.0000   1.6777   0.0000   1.0500        
+  1  4  4 104.1335   8.6043   1.6495   0.0000   1.6777   0.0000   1.0500        
+  3  4  3  74.1978  42.1786   1.7845 -18.0069   1.6777   0.0000   1.0500        
+  3  4  4  74.8600  43.7354   1.1572  -0.9193   1.6777   0.0000   1.0500        
+  4  4  4  75.0538  14.8267   5.2794   0.0000   1.6777   0.0000   1.0500        
+  1  4  2  69.1106  25.5067   1.1003   0.0000   0.0222   0.0000   1.0369        
+  2  4  3  81.3686  40.0712   2.2396   0.0000   0.0222   0.0000   1.0369        
+  2  4  4  83.0104  43.4766   1.5328   0.0000   0.0222   0.0000   1.0500        
+  2  4  2  70.8687  12.0168   5.0132   0.0000   0.0222   0.0000   1.1243        
+  1  2  3   0.0000  25.0000   3.0000   0.0000   1.0000   0.0000   1.0400        
+  1  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  2  5   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  3  2  3   0.0000   4.4124   2.5758   0.0000   0.0000   0.0000   2.9884        
+  3  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  4  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  2  2  3   0.0000  15.0000   2.2970   0.0000   0.0000   0.0000   1.3268        
+  2  2  4   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  1  1  5  74.9397  25.0560   1.8787   0.1463   0.0559   0.0000   1.0400        
+  1  5  1  86.9521  36.9951   2.0903   0.1463   0.0559   0.0000   1.0400        
+  2  1  5  74.9397  25.0560   1.8787   0.0000   0.0000   0.0000   1.0400        
+  1  5  2  86.1791  36.9951   2.0903   0.0000   0.0000   0.0000   1.0400        
+  1  5  5  85.3644  36.9951   2.0903   0.1463   0.0559   0.0000   1.0400        
+  2  5  2  93.1959  36.9951   2.0903   0.0000   0.0000   0.0000   1.0400        
+  2  5  5  84.3331  36.9951   2.0903   0.0000   0.0000   0.0000   1.0400        
+  6  6  6  69.3456  21.7361   1.4283   0.0000  -0.2101   0.0000   1.3241        
+  2  6  6  75.6168  21.5317   1.0435   0.0000   2.5179   0.0000   1.0400        
+  2  6  2  78.3939  20.9772   0.8630   0.0000   2.8421   0.0000   1.0400        
+  3  6  6  70.3016  15.4081   1.3267   0.0000   2.1459   0.0000   1.0400        
+  2  6  3  73.8232  16.6592   3.7425   0.0000   0.8613   0.0000   1.0400        
+  3  6  3  90.0344   7.7656   1.7264   0.0000   0.7689   0.0000   1.0400        
+  6  3  6  22.1715   3.6615   0.3160   0.0000   4.1125   0.0000   1.0400        
+  2  3  6  83.7634   5.6693   2.7780   0.0000   1.6982   0.0000   1.0400        
+  3  3  6  73.4663  25.0761   0.9143   0.0000   2.2466   0.0000   1.0400        
+  2  2  6   0.0000  47.1300   6.0000   0.0000   1.6371   0.0000   1.0400        
+  6  2  6   0.0000  31.5209   6.0000   0.0000   1.6371   0.0000   1.0400        
+  3  2  6   0.0000  31.0427   4.5625   0.0000   1.6371   0.0000   1.0400        
+  2  2  5   0.0000   0.0019   6.0000   0.0000   0.0000   0.0000   1.0400        
+  3 11  3  62.4906  31.5023   1.3328   0.0000   2.8731   0.0000   1.0794        
+ 11  3 11  31.0790  19.3435   0.4919   0.0000   2.9625   0.0000   3.0000        
+  3  3 11 100.0000  14.7642   7.0000   0.0000   1.0585   0.0000   1.1599        
+  1  3 11  60.7895  13.6681   0.7546   0.0000   2.1747   0.0000   2.9508        
+  2  3 11 100.0000   5.0000   1.4335   0.0000   1.2363   0.0000   5.0000        
+  3 12 12  23.8296   8.9089   7.0000   0.0000   1.0000   0.0000   2.8891        
+  3 12  3  87.0764  19.4489   2.5080   0.0000   2.6056   0.0000   3.0000        
+ 12  3 12  72.7369  13.7522   5.0243   0.0000   2.9700   0.0000   1.5506        
+  3  3 12  68.8771  10.5000   2.5500   0.0000   2.5729   0.0000   1.5892        
+  2  3 12  99.5836   5.4142   2.2105   0.0000   1.0513   0.0000   1.1000        
+  1  3 12  90.0000  12.1772   2.2055   0.0000   1.9064   0.0000   2.6056        
+  1  1 12  71.1708  32.6379   0.4516   0.0000   2.1609   0.0000   1.1000        
+  1 12  3  90.0000  45.0000   0.9335   0.0000   0.2140   0.0000   1.4846        
+  1 12  1  87.6204  45.0000   1.2740   0.0000   1.1519   0.0000   1.1000        
+  3  1 12  54.7020   3.2967   7.0000   0.0000   2.0408   0.0000   2.4032        
+  2 12  3  90.0000  28.2099   1.8036   0.0000   1.5461   0.0000   1.2304        
+  2 12  2  90.0000  36.3001   0.6409   0.0000   3.0000   0.0000   1.7755        
+  1 12  2  89.5835  45.0000   0.8465   0.0000   1.2118   0.0000   2.2282        
+  2  1 12  68.7714  22.9669   0.4631   0.0000   2.4269   0.0000   1.4680        
+  2  2 12   0.0000  30.2898   3.9181   0.0000   0.9914   0.0000   1.3121        
+  3  2 12   0.0000   1.0000   4.1706   0.0000   1.0100   0.0000   1.1000        
+  1  2 12   0.0000   1.0000   3.9722   0.0000   1.0075   0.0000   1.2984        
+  3 13  3  73.6321  10.6453   2.7693   0.0000   0.0500   0.0000   1.9906        
+ 13  3 13 100.0000   5.0270   5.0000   0.0000   1.2768   0.0000   2.0630        
+  3  3 13  52.3127  40.0000   1.1362   0.0000   1.5100   0.0000   1.1000        
+  3 13 13  66.6695   0.0036   3.2646   0.0000   0.0581   0.0000   1.3741        
+  2  3 13 100.0000   3.8927   8.0000   0.0000   2.0000   0.0000   1.1000        
+  1  3 13  96.6040   9.4537   8.0000   0.0000   0.3285   0.0000   4.0000        
+  3 14  3  79.6765  50.0000   1.0502  -0.0016   0.1000   0.0000   1.4583        
+ 14  3 14  20.2100  37.6165   0.6059   0.0000   0.1531   0.0000   2.0586        
+  3  3 14  38.5570  11.9307   0.9911   0.0000   0.8422   0.0000   1.0500        
+  3 14 14   5.8342   0.0724   0.1000   0.0000   0.5490   0.0000   1.7839        
+  2  3 14  81.8943   7.2820   2.1490   0.0000   0.6873   0.0000   3.2184        
+  1  3 14  75.5634   8.3289   1.0236   0.0000   2.0875   0.0000   1.0500        
+ 12  3 14  30.0000   5.0000   0.5000   0.0000   0.5000   0.0000   1.2500        
+ 47    ! Nr of torsions;at1;at2;at3;at4;;V1;V2;V3;V2(BO);vconj;n.u;n            
+  1  1  1  1  -0.2500  34.7453   0.0288  -6.3507  -1.6000   0.0000   0.0000     
+  1  1  1  2  -0.2500  29.2131   0.2945  -4.9581  -2.1802   0.0000   0.0000     
+  2  1  1  2  -0.2500  31.2081   0.4539  -4.8923  -2.2677   0.0000   0.0000     
+  1  1  1  3  -0.3495  22.2142  -0.2959  -2.5000  -1.9066   0.0000   0.0000     
+  2  1  1  3   0.0646  24.3195   0.6259  -3.9603  -1.0000   0.0000   0.0000     
+  3  1  1  3  -0.5456   5.5756   0.8433  -5.1924  -1.0180   0.0000   0.0000     
+  1  1  3  1   1.7555  27.9267   0.0072  -2.6533  -1.0000   0.0000   0.0000     
+  1  1  3  2  -1.4358  36.7830  -1.0000  -8.1821  -1.0000   0.0000   0.0000     
+  2  1  3  1  -1.3959  34.5053   0.7200  -2.5714  -2.1641   0.0000   0.0000     
+  2  1  3  2  -2.5000  70.0597   1.0000  -3.5539  -2.9929   0.0000   0.0000     
+  1  1  3  3   0.6852  11.2819  -0.4784  -2.5000  -2.1085   0.0000   0.0000     
+  2  1  3  3   0.1933  80.0000   1.0000  -4.0590  -3.0000   0.0000   0.0000     
+  3  1  3  1  -1.9889  76.4820  -0.1796  -3.8301  -3.0000   0.0000   0.0000     
+  3  1  3  2   0.2160  72.7707  -0.7087  -4.2100  -3.0000   0.0000   0.0000     
+  3  1  3  3  -2.5000  71.0772   0.2542  -3.1631  -3.0000   0.0000   0.0000     
+  1  3  3  1   2.5000  -0.6002   1.0000  -3.4297  -2.8858   0.0000   0.0000     
+  1  3  3  2  -2.5000  -3.3822   0.7004  -5.4467  -2.9586   0.0000   0.0000     
+  2  3  3  2   2.5000  -4.0000   0.9000  -2.5000  -1.0000   0.0000   0.0000     
+  1  3  3  3   1.2329  -4.0000   1.0000  -2.5000  -1.7479   0.0000   0.0000     
+  2  3  3  3   0.8302  -4.0000  -0.7763  -2.5000  -1.0000   0.0000   0.0000     
+  3  3  3  3  -2.5000  -4.0000   1.0000  -2.5000  -1.0000   0.0000   0.0000     
+  0  1  2  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  2  2  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  2  3  0   0.0000   0.1000   0.0200  -2.5415   0.0000   0.0000   0.0000     
+  0  1  1  0   0.0000  50.0000   0.3000  -4.0000  -2.0000   0.0000   0.0000     
+  0  3  3  0   0.5511  25.4150   1.1330  -5.1903  -1.0000   0.0000   0.0000     
+  0  1  4  0  -2.4242 128.1636   0.3739  -6.6098  -2.0000   0.0000   0.0000     
+  0  2  4  0   0.0000   0.1000   0.0200  -2.5415   0.0000   0.0000   0.0000     
+  0  3  4  0   1.4816  55.6641   0.0004  -7.0465  -2.7203   0.0000   0.0000     
+  0  4  4  0  -0.3244  27.7086   0.0039  -2.8272  -2.0000   0.0000   0.0000     
+  4  1  4  4  -5.5181   8.9706   0.0004  -6.1782  -2.0000   0.0000   0.0000     
+  0  1  5  0   3.3423  30.3435   0.0365  -2.7171   0.0000   0.0000   0.0000     
+  0  5  5  0  -0.0555 -42.7738   0.1515  -2.2056   0.0000   0.0000   0.0000     
+  0  2  5  0   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000   0.0000     
+  0  6  6  0   0.0000   0.0000   0.1200  -2.4426   0.0000   0.0000   0.0000     
+  0  2  6  0   0.0000   0.0000   0.1200  -2.4847   0.0000   0.0000   0.0000     
+  0  3  6  0   0.0000   0.0000   0.1200  -2.4703   0.0000   0.0000   0.0000     
+  2  1  3 14   1.6297  56.8132   0.3398  -2.6912  -2.1000   0.0000   0.0000     
+  1  1  3 14  -0.0427  13.4096   0.9351  -6.5245  -2.1000   0.0000   0.0000     
+  2  3 14  3   2.5000  11.6208   1.0000  -9.0000  -1.0000   0.0000   0.0000     
+  2  1  3 12  -0.2500  45.7639   0.3000  -3.5745  -2.1565   0.0000   0.0000     
+  1  1  3 12  -0.2500  69.1094   0.3000  -3.0983  -2.1565   0.0000   0.0000     
+  2  3 12  3  -0.4306   7.5000  -0.5000  -6.9948  -1.0000   0.0000   0.0000     
+  2  3 11  3   1.8627   9.7180  -1.0000  -7.2224  -1.0000   0.0000   0.0000     
+  1  3 11  3   2.5000  23.9443   1.0000  -3.2267  -1.0000   0.0000   0.0000     
+  1  1  3 11   0.9114  62.5039  -0.2389  -3.2976  -1.0000   0.0000   0.0000     
+  2  1  3 11   0.5000  35.0000   0.5000  -4.0000  -1.0000   0.0000   0.0000     
+  9    ! Nr of hydrogen bonds;at1;at2;at3;Rhb;Dehb;vhb1                         
+  3  2  3   2.1845  -2.3549   3.0582  19.1627                                   
+  3  2  4   2.0000  -6.0000   1.7976   3.0000                                   
+  4  2  3   1.2000  -2.0000   1.7976   3.0000                                   
+  4  2  4   1.2979  -6.0000   1.7976   3.0000                                   
+  3  2  5   1.5000  -2.0000   1.7976   3.0000                                   
+  4  2  5   1.5000  -2.0000   1.7976   3.0000                                   
+  5  2  3   1.5000  -2.0000   1.7976   3.0000                                   
+  5  2  4   1.5000  -2.0000   1.7976   3.0000                                   
+  5  2  5   1.5000  -2.0000   1.7976   3.0000                                   
diff --git a/doc/README.txt b/doc/README.txt
index 18e6a73d8daedbd4232cce54e91f6ca004557cd8..50a7eb96b80e70e112f4c6a69abab32dcf57b3f5 100644
--- a/doc/README.txt
+++ b/doc/README.txt
@@ -21,7 +21,7 @@
 -------------------------------------------------------------------------
 -------------------------------------------------------------------------
 -------------   Instructions to get started with the codebase   ---------
--------------				PuReMD Package Release 1.0.0.0			 ---------
+-------------         PuReMD Package Release 1.0.0.0            ---------
 -------------------------------------------------------------------------
 -------------------------------------------------------------------------
 
@@ -29,10 +29,10 @@ VERSION - 1003
 
 1. Following package for Purdue Reactive Molecular Dynamics (PuReMD) 
 consists of the following implementations: 
-	a) serial (single cpu) implementation  -	sPuReMD
-	b) GPU (single GPU) implementation		 -	PuReMD-GPU
-	c) Parallel CPU (cluster of CPUs) implementation		- PuReMD
-	d) Parallel GPU (cluster of GPUs) implementation		- PG-PuReMD
+	a) serial (single cpu) implementation -	sPuReMD
+	b) GPU (single GPU) implementation - PuReMD-GPU
+	c) Parallel CPU (cluster of CPUs) implementation - PuReMD
+	d) Parallel GPU (cluster of GPUs) implementation - PG-PuReMD
 
 2. In the current implemtations only limited ensembles are supported
 in the GPU implementations (CPU implementations supports a wide array of 
diff --git a/doc/src/manual.tex b/doc/src/manual.tex
index 257aaee3af94222f0593ab8989a504afcd69681e..069adabcd1e90252d3d035804bfe37edd6571602 100644
--- a/doc/src/manual.tex
+++ b/doc/src/manual.tex
@@ -1,21 +1,33 @@
-%%
-%% This is the PuReMD manual.
-%%
+%% PuReMD manual
+
 \documentclass{article}
 
 \usepackage{hyperref}
+\usepackage{minted}
+\usepackage{listings}
+
+\lstset{
+  basicstyle=\ttfamily,
+  mathescape
+}
 
 
-\title{PuReMD Manual \\
-  (Purdue Reactive Molecular Dynamics Program)}
+\title{Manual for PuReMD: \\
+  {\bf Pu}rdue {\bf Re}active {\bf M}olecular {\bf D}ynamics Program}
 
-\author{Hasan Metin Aktulga}
+\author{
+  H. Metin Aktulga \\
+  \texttt{hma@cse.msu.edu} \\
+  \and
+  Kurt A. O'Hearn \\
+  \texttt{ohearnku@msu.edu}
+}
 
 \begin{document}
 
 \maketitle
 
-This manual is for the two simulation programs which have
+This manual is for the PuReMD software which has
 come to existence as a result of our ReaxFF realization efforts. 
 Our initial efforts have led to the SerialReax program, which is a 
 sequential implementation for ReaxFF. SerialReax has helped us in verifying 
@@ -38,7 +50,7 @@ manual, we take PuReMD as our basis and describe it first. In a following
 section, we describe the extras that come with SerialReax which we hope 
 to incorporate into PuReMD in the near future.
 
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 \section{Input Files}
 \label{sec:puremd_inp}
 
@@ -46,6 +58,7 @@ PuReMD expects 3 input files: a geometry file describing the system to be
 simulated, a force field file containing ReaxFF parameters and a control 
 file to manage simulation variables.
 
+
 \subsection{Geometry File}
 \label{sec:puremd_geo}
 
@@ -59,9 +72,9 @@ restart from an earlier simulation check-point using a restart file
 \label{sec:puremd_pdb}
 
 For detailed and up-to-date information on the PDB format, please visit 
-\url{http://www.wwpdb.org/docs.html}. Input files of various other formats 
+\href{http://www.wwpdb.org/docs.html}{here}. Input files of various other formats 
 can easily be converted to the pdb format using the freely available 
-OpenBabel software: (\url{http://openbabel.sourceforge.net/wiki/Main_Page}).
+\href{http://openbabel.sourceforge.net/wiki/Main_Page}{OpenBabel software}).
 
 In the geometry file, each atom is assigned a unique serial id to be
 able to identify atoms easily during the simulation. PDB format limits the 
@@ -79,16 +92,14 @@ follows: The first line describes the simulation box and the second line
 gives the total number of atoms in the system. These initial two lines need 
 to be followed by a single line for each atom describing it in detail. 
 Here is what a custom geo file looks like:
-\begin{verbatim}
+\begin{lstlisting}
 BOXGEO x_len y_len z_len alpha beta gamma
 N
 1 ele1  name1  x1 y1 z1
 2 ele2  name2  x2 y2 z2
-.
-.
-.
+$\vdots$
 N eleN  nameN  xN yN zN 
-\end{verbatim}
+\end{lstlisting}
 
 First three floating point numbers on the first line give the length of 
 the simulation box in x, y, z dimensions, the remaining ones are for the 
@@ -114,8 +125,9 @@ of 6 fields:
 
 Force field file contains the ReaxFF parameters to be used during 
 the simulation. Adri van Duin is the main developer and distributor 
-for Reax force fields, you can see his contact info at 
-\url{http://www.mne.psu.edu/vanduin/}.
+for Reax force fields, you can see his contact info
+\href{http://www.mne.psu.edu/vanduin}{here}.
+
 
 \subsection{Control File} 
 \label{sec:puremd_control}
@@ -123,21 +135,62 @@ for Reax force fields, you can see his contact info at
 Parameters in the control file allow the user to tune various simulation 
 options. Parameter names are case-sensitive but their order is not important 
 (except that {\tt ensemble\_type} needs to precede both {\tt p\_mass} and 
-{\tt pressure}). Described below are the fields that you might use in a 
-control file. If a parameter is missing from the control file, its default 
+{\tt pressure}). The table below lists all parameters names which the
+software recognizes, and each parameter is described in further detail
+below. If a parameter is missing from the control file, its default 
 value (as given in each parameter's description below) will be assumed.
 Each parameter must be specified in a single line, first token should be
 the parameter and the second token should be an appropriate value. 
 Comments regarding a parameter can be included after the value field 
 on the same line.
 
+\begin{center}
+\begin{tabular}{|c|c|} \hline
+  \hyperref[sec:simulation_name]{simulation\_name} & \hyperref[sec:ensemble_type]{ensemble\_type} \\ \hline
+  \hyperref[sec:nsteps]{nsteps} & \hyperref[sec:dt]{dt} \\ \hline
+  \hyperref[sec:reposition_atoms]{reposition\_atoms} & \hyperref[sec:restrict_bonds]{restrict\_bonds} \\ \hline
+  \hyperref[sec:tabulate_long_range]{tabulate\_long\_range} & \hyperref[sec:energy_update_freq]{energy\_update\_freq} \\ \hline
+  \hyperref[sec:remove_CoM_vel]{remove\_CoM\_vel} & \hyperref[sec:nbrhood_cutoff]{nbrhood\_cutoff} \\ \hline
+  \hyperref[sec:bond_graph_cutoff]{bond\_graph\_cutoff} & \hyperref[sec:thb_cutoff]{thb\_cutoff} \\ \hline
+  \hyperref[sec:hbond_cutoff]{hbond\_cutoff} & \hyperref[sec:charge_method]{charge\_method} \\ \hline
+  \hyperref[sec:cm_q_net]{cm\_q\_net} & \hyperref[sec:cm_solver_type]{cm\_solver\_type} \\ \hline
+  \hyperref[sec:cm_solver_max_iters]{cm\_solver\_max\_iters} & \hyperref[sec:cm_solver_restart]{cm\_solver\_restart} \\ \hline
+  \hyperref[sec:cm_solver_q_err]{cm\_solver\_q\_err} & \hyperref[sec:cm_domain_sparsity]{cm\_domain\_sparsity} \\ \hline
+  \hyperref[sec:cm_solver_pre_comp_type]{cm\_solver\_pre\_comp\_type} & \hyperref[sec:cm_solver_pre_comp_refactor]{cm\_solver\_pre\_comp\_refactor} \\ \hline
+  \hyperref[sec:cm_solver_pre_comp_droptol]{cm\_solver\_pre\_comp\_droptol} & \hyperref[sec:cm_solver_pre_comp_sweeps]{cm\_solver\_pre\_comp\_sweeps} \\ \hline
+  \hyperref[sec:cm_solver_pre_app_type]{cm\_solver\_pre\_app\_type} & \hyperref[sec:cm_solver_pre_app_jacobi_iters]{cm\_solver\_pre\_app\_jacobi\_iters} \\ \hline
+  \hyperref[sec:temp_init]{temp\_init} & \hyperref[sec:temp_final]{temp\_final} \\ \hline
+  \hyperref[sec:t_mass]{t\_mass} & \hyperref[sec:t_mode]{t\_mode} \\ \hline
+  \hyperref[sec:t_rate]{t\_rate} & \hyperref[sec:t_freq]{t\_freq} \\ \hline
+  \hyperref[sec:pressure]{pressure} & \hyperref[sec:p_mass]{p\_mass} \\ \hline
+  \hyperref[sec:compress]{compress} & \hyperref[sec:press_mode]{press\_mode} \\ \hline
+  \hyperref[sec:geo_format]{geo\_format} & \hyperref[sec:write_freq]{write\_freq} \\ \hline
+  \hyperref[sec:traj_compress]{traj\_compress} & \hyperref[sec:traj_format]{traj\_format} \\ \hline
+  \hyperref[sec:traj_title]{traj\_title} & \hyperref[sec:atom_info]{atom\_info} \\ \hline
+  \hyperref[sec:atom_forces]{atom\_forces} & \hyperref[sec:atom_velocities]{atom\_velocities} \\ \hline
+  \hyperref[sec:bond_info]{bond\_info} & \hyperref[sec:angle_info]{angle\_info} \\ \hline
+  \hyperref[sec:test_forces]{test\_forces} & \hyperref[sec:molec_anal]{molec\_anal} \\ \hline
+  \hyperref[sec:freq_molec_anal]{freq\_molec\_anal} & \hyperref[sec:dipole_anal]{dipole\_anal} \\ \hline
+  \hyperref[sec:freq_dipole_anal]{freq\_dipole\_anal} & \hyperref[sec:diffusion_coef]{diffusion\_coef} \\ \hline
+  \hyperref[sec:freq_diffusion_coef]{freq\_diffusion\_coef} & \hyperref[sec:restrict_type]{restrict\_type} \\ \hline
+  \hyperref[sec:restart_format]{restart\_format} & \hyperref[sec:restart_freq]{restart\_freq} \\ \hline
+\end{tabular}
+\end{center}
+
+\subsubsection{simulation\_name}
+\label{sec:simulation_name}
+
 \begin{verbatim}
   simulation_name    test_puremd
 \end{verbatim}
 Output files produced by PuReMD will be in 
 {\tt simulation\_name.some\_extension} format. Output files will be 
-discussed in more detail in Section~\ref{sec:puremd_output}. Default value 
-is {\tt simulate}.
+discussed in more detail in Section~\ref{sec:puremd_output}.
+
+Default: {\tt default.sim}
+
+\subsubsection{ensemble\_type}
+\label{sec:ensemble_type}
 
 \begin{verbatim}
   ensemble_type    1
@@ -153,28 +206,51 @@ PuReMD. Supported ensembles are as follows:
   \item 5: NPT: anisotropic NPT with Parrinello-Rehman coupling 
     (under development)
 \end{itemize}
-{\tt ensemble\_type} is NVE by default.
+
+Default: 0 (NVE)
+
+\subsubsection{nsteps}
+\label{sec:nsteps}
 
 \begin{verbatim}
   nsteps     1000
+\end{verbatim}
+{\tt nsteps} controls the total number of steps for the simulation.
+
+Default: 0
+
+\subsubsection{dt}
+\label{sec:dt}
+
+\begin{verbatim}
   dt         0.25
 \end{verbatim}
-{\tt nsteps} controls the total number of steps for the simulation and 
-{\tt dt} controls the length of each time step (measured in femtoseconds). 
-Number of steps is 0 by default and time step length is 0.25~fs.
+{\tt dt} controls the length of each time step (in femtoseconds). 
+
+Default: 0.25
+
+\subsubsection{proc\_by\_dim}
+\label{sec:proc_by_dim}
 
 \begin{verbatim}
   proc_by_dim     1 1 3
 \end{verbatim}
-PuReMD uses the domain decomposition technique to distribute the load
-among processors, it currently does not have dynamic load balancing.
+The distributed memory version of PuReMD uses the
+domain decomposition technique to distribute the load
+among processors. It currently does not have dynamic load balancing.
 {\tt proc\_by\_dim} denotes the desired decomposition of the simulation 
 box into subdomains (first integer is the number of equal-length 
 partitions in x dimension, second integer is for y dimension and 
 the last one is for z dimension). Each subdomain is subsequently assigned 
 to a single processor. PuReMD constructs a 3D torus based on the 
-{\tt proc\_by\_dim} parameter. The default is to use a single processor. 
-SerialReax does not accept the {\tt proc\_by\_dim} parameter.
+{\tt proc\_by\_dim} parameter.
+
+Default: 1 1 1 (single processor)
+
+Note: shared memory versions of PuReMD do not accept this parameter.
+
+\subsubsection{geo\_format}
+\label{sec:geo_format}
 
 \begin{verbatim}
   geo_format     0
@@ -193,7 +269,13 @@ to 2 (for ASCII restarts) or 3 (for binary restarts) and providing the name
 of the restart file as an argument to PuReMD (instead of the GEO file name).
 Then PuReMD will read the box geometry, positions and velocities for all 
 atoms in the system from the restart file and continue execution from thereon. 
-Default is the custom geometry format.
+
+Default: 0 (custom format)
+
+\subsubsection{restart\_format}
+\label{sec:restart_format}
+\subsubsection{restart\_freq}
+\label{sec:restart_freq}
 
 \begin{verbatim}
   restart_format   1
@@ -210,6 +292,11 @@ parameter is set to a positive integer. A restart file is named as follows:
 {\tt simulation\_name.resS} where {\tt S} denotes the step that the restart 
 file is written.
 
+Defaults: 0 (ASCII), 0
+
+\subsubsection{tabulate\_long\_range}
+\label{sec:tabulate_long_range}
+
 \begin{verbatim}
   tabulate_long_range    10000
 \end{verbatim}
@@ -225,7 +312,12 @@ the appropriate interpolation function is located and energy and forces
 between the atom pair is approximated by means of cubic spline interpolation.
 This method gives significant speed-up compared to computing everything from 
 scratch each time and with only 10000 sample points it is able to provide 
-results with an accuracy at machine precision level. Default is no tabulation.
+results with an accuracy at machine precision level.
+
+Default: 0 (no tabulation)
+
+\subsubsection{energy\_update\_freq}
+\label{sec:energy_update_freq}
 
 \begin{verbatim}
   energy_update_freq     10
@@ -233,8 +325,12 @@ results with an accuracy at machine precision level. Default is no tabulation.
 This option controls the frequency of writes into output files described 
 in detail in Section~\ref{sec:puremd_output} (except for the trajectory 
 and restart files which are controlled by other parameters explained
-separately). The default value for this parameter is 0, meaning there will 
-not be any energies and performance logs output.
+separately).
+
+Default: 0 (no energies in performance logs)
+
+\subsubsection{remove\_CoM\_vel}
+\label{sec:remove_CoM_vel}
 
 \begin{verbatim}
   remove_CoM_vel     500
@@ -243,8 +339,15 @@ Removal of translational and rotational velocities around the center of
 mass needs to be done for NVT and NPT type ensembles to remove the 
 nonphysical effects of scaling velocities. In case of NVE, this is  
 unnecessary and is not done regardless of the value of {\tt remove\_CoM\_vel}.
-The default is to remove translational and rotational velocities at 
-every 250 steps.
+
+Default: 25
+
+\subsubsection{nbrhood\_cutoff}
+\label{sec:nbrhood_cutoff}
+\subsubsection{thb\_cutoff}
+\label{sec:thb_cutoff}
+\subsubsection{hbond\_cutoff}
+\label{sec:hbond_cutoff}
 
 \begin{verbatim}
   nbrhood_cutoff     5.0     
@@ -253,20 +356,25 @@ every 250 steps.
 \end{verbatim}
 These cutoff parameters are crucial for the correctness and efficiency
 of PuReMD. Normally, bonded interactions are truncated after 4-5~\AA\ in 
-ReaxFF and this is controlled by the {\tt nbrhood\_cutoff} parameter 
-whose default value is 4~\AA.
+ReaxFF and this is controlled by the {\tt nbrhood\_cutoff} parameter.
 
 {\tt thb\_cutoff} sets the bond strength threshold for valence angle 
 interactions. Bonds which are weaker than {\tt thb\_cutoff} will not 
-be included in valence angle interactions. Default for {\tt thb\_cutoff} 
-is 0.001.
+be included in valence angle interactions.
 
 {\tt hbond\_cutoff} controls the distance between the donor and acceptor 
 atoms in a hydrogen bond interaction. Its typical value is from 6\AA\ to 
 7.5~\AA. If {\tt hbond\_cutoff} is set to 0, hydrogen bond interactions 
 will be turned off completely (could be useful for improved
 performance in simulations where it is known apriori that there are no 
-hydrogen bonding interactions). Default is to set {\tt hbond\_cutoff} to 0.
+hydrogen bonding interactions).
+
+Defaults: 4.0, 0.001, 0.0
+
+\subsubsection{reneighbor}
+\label{sec:reneighbor}
+\subsubsection{vlist\_buffer}
+\label{sec:vlist_buffer}
 
 \begin{verbatim}
   reneighbor     10
@@ -275,26 +383,134 @@ hydrogen bonding interactions). Default is to set {\tt hbond\_cutoff} to 0.
 PuReMD features delayed neighbor generation by using Verlet lists. 
 {\tt reneighbor} controls the reneighboring frequency and {\tt vlist\_buffer} 
 controls the buffer space beyond the maximum ReaxFF interaction cutoff. 
-By default, {\tt vlist\_buffer} is set to 0 and reneighboring is done at 
-every step.
+
+Defaults: 1 (reneighbor every step), 0
+
+\subsubsection{charge\_method}
+\label{sec:charge_method}
+\subsubsection{cm\_q\_net}
+\label{sec:cm_q_net}
+\subsubsection{cm\_solver\_type}
+\label{sec:cm_solver_type}
+\subsubsection{cm\_solver\_max\_iters}
+\label{sec:cm_solver_max_iters}
+\subsubsection{cm\_solver\_restart}
+\label{sec:cm_solver_restart}
+\subsubsection{cm\_solver\_q\_err}
+\label{sec:cm_solver_q_err}
+\subsubsection{cm\_solver\_sparsity\_enabled}
+\label{sec:cm_solver_sparsity_enabled}
+\subsubsection{cm\_solver\_sparsity}
+\label{sec:cm_solver_sparsity}
+\subsubsection{cm\_solver\_pre\_comp\_type}
+\label{sec:cm_solver_pre_comp_type}
+\subsubsection{cm\_solver\_pre\_comp\_sweeps}
+\label{sec:cm_solver_pre_comp_sweeps}
+\subsubsection{cm\_solver\_pre\_comp\_refactor}
+\label{sec:cm_solver_pre_comp_refactor}
+\subsubsection{cm\_solver\_pre\_comp\_droptol}
+\label{sec:cm_solver_pre_comp_droptol}
+\subsubsection{cm\_solver\_pre\_app\_type}
+\label{sec:cm_solver_pre_app_type}
+\subsubsection{cm\_solver\_pre\_app\_jacobi\_iters}
+\label{sec:cm_solver_pre_app_jacobi_iters}
 
 \begin{verbatim}
-  q_err        1e-6
-  qeq_freq     1
+  charge_method                     0
+  cm_q_net                          0.0
+  cm_solver_type                    0
+  cm_solver_max_iters               20
+  cm_solver_restart                 100
+  cm_solver_q_err                   1e-6
+  cm_domain_sparsity                1.0
+  cm_solver_pre_comp_type           1
+  cm_solver_pre_comp_refactor       1000
+  cm_solver_pre_comp_droptol        0.0
+  cm_solver_pre_comp_sweeps         3
+  cm_solver_pre_app_type            0
+  cm_solver_pre_app_jacobi_iters    50
 \end{verbatim}
-PuReMD uses a preconditioned conjugate gradients (PCG) solver with a 
-diagonal preconditioner for the QEq problem. {\tt q\_err} denotes the 
-stopping criteria for the PCG solver, the norm of the relative residual. 
-A lower threshold would yield more accurate equilibration of charges at 
-the expense of an increase in computation time. A threshold of $10^{-6}$ 
-should be good enough for most cases and this is the default value.
-
-{\tt qeq\_freq} can be used to perform charge equilibration at every 
+PuReMD uses one of several charge methods for dynamically
+determining atomic charges. Unpinning these charge methods
+are iterative linear solvers with optional preconditioning.
+
+{\tt charge\_method} controls which charge method is used.
+The options are charge equilibration
+(0), electronegivity equilibration (1), or atom-condensed Kohn-Sham
+approximated to second order (2).
+
+{\tt cm\_q\_net} controls the net system charge.
+
+{\tt cm\_solver\_type} controls which linear solver is used. Options
+are GMRES with restarts (0), Householder GMRES with restarts (1),
+conjugant gradient (2), and steepest descent (3).
+
+{\tt cm\_solver\_max\_iters} controls the maximum number of iterations
+the solver is allowed to perform in order to achieve convergence of
+the solution to within the reqiured tolerance.
+
+{\tt cm\_solver\_restart} controls the maximum number of inner iterations
+that GMRES-based solvers are allowed before performing a restart.
+
+{\tt cm\_solver\_q\_err} sets the the solution tolerance for the solver.
+
+{\tt cm\_solver\_sparsity} sets the sparsification ratio of the charge matrix
+used to compute the preconditioner. Specifically, an additional distance-based
+cutoff is applied to compute elements of the (sparsified) charge matrix, and
+this matrix is in turn used to compute a preconditioner. The value of this
+parameter is multipled by the current neighbor cutoff value to obtain the new
+cutoff; hence, a value between 0.0 and 1.0, exclusive, is expected.
+
+{\tt cm\_solver\_pre\_comp\_type} sets the type of preconditioner to be
+computed. Options are none (0), Jacobi/diagonal inverse (1), incomplete
+Cholesky with dual thresholding (2), incomplete LU computed in an iterative
+fashion (3), and iterative incomplete LU single thresholding (4).
+
+{\tt cm\_solver\_pre\_comp\_refactor} sets the number of simulation steps
+after which to recompute the preconditioner.
+
+{\tt cm\_solver\_pre\_comp\_droptol} sets the dropping tolerance for
+computing incompute Cholesky or LU preconditioners.
+
+{\tt cm\_solver\_pre\_comp\_sweeps} sets the number of sweeps (iterations)
+to perform when computing incompute LU iteratively.
+
+{\tt cm\_solver\_pre\_app\_type} determines the type of method used
+to apply the preconditioner in the case of two-sided preconditioning
+(incomplete Cholesky and LU). Specifically, the application of the
+approximate triangular factors requires solving triangular linear systems,
+and this parameter controls how this is performed. Options are serial solve
+forward/backword substitution (0), solve via level scheduling (1), solve
+via graph coloring (3), or approximate solve via Jacobi iteration (4).
+
+{\tt cm\_solver\_pre\_app\_jacobi\_iters} controls how many iterations
+are performed for each approximate triangular solve via Jacobi iteration.
+
+{\tt cm\_solver\_freq} can be used to compute charges at every 
 few steps instead of the default behaviour of performing it at every 
-step. Although doing QEq less frequently would save important 
+step. Although doing this less frequently would save important 
 computational time, it is not recommended. Because this might cause wild 
 fluctuations in energies and forces.
 
+Defaults: 
+
+Notes:
+\begin{enumerate}
+  \item Only the shared memory versions of PuReMD contain all the solvers,
+    while only CG with diagonal inverse preconditioning is contained in the
+    distributed memory versions.
+  \item The full set of preconditioning options is implemented in the shared
+    memory non-GPU version of PuReMD. The other versions contain only diagonal
+    inverse preconditioning.
+\end{enumerate}
+
+\subsubsection{temp\_init}
+\label{sec:temp_init}
+\subsubsection{temp\_final}
+\label{sec:temp_final}
+\subsubsection{t\_mass}
+\label{sec:t_mass}
+
 \begin{verbatim}
   temp_init    0.0
   temp_final   300.0
@@ -307,11 +523,19 @@ is controlled via the {\tt temp\_init} parameter including the NVE ensemble.
 for {\tt temp\_final}. PuReMD features both Berendsen~\cite{ref:berendsen} 
 and Nose-Hoover~\cite{ref:klein} type thermostats as was mentioned while 
 explaining the {\tt ensemble\_type} parameter.
-\emph{Important note: Nose-Hoover thermostat in PuReMD is still under testing.}
 
-{\tt t\_mass} is the thermal inertia given in femtoseconds. Suggested (and 
-the default) value of {\tt t\_mass} is 500.0, and 0.166 for the Berendsen 
-thermostat, and for the Nose-Hoover thermostat, respectively.
+{\tt t\_mass} is the thermal inertia given in femtoseconds. Suggested
+value of {\tt t\_mass} is 500.0 and 0.166 for the Berendsen 
+thermostat and the Nose-Hoover thermostats, respectively.
+
+Defaults: 0.0, 300.0, 0.16666
+
+Note: Nose-Hoover thermostat is still under testing
+
+\subsubsection{pressure}
+\label{sec:pressure}
+\subsubsection{p\_mass}
+\label{sec:p_mass}
 
 \begin{verbatim}
   pressure      0.000101 0.000101 0.000101
@@ -332,23 +556,46 @@ to control pressure. For the sNPT ensemble, {\tt pressure} parameter
 expects 3 floating point numbers to control pressure on each dimension.
 Same things apply for {\tt p\_mass} as well.
 
+Defaults: 0.000101325, 5000.0
+
+\subsubsection{write\_freq}
+\label{sec:write_freq}
+\subsubsection{traj\_format}
+\label{sec:traj_format}
+
 \begin{verbatim}
   write_freq     100
-  traj_method      1
+  traj_format      1
 \end{verbatim}
 Trajectory of the simulation will be output to the trajectory file 
 (which will automatically be named as {\tt simulation\_name.trj}) at 
 every {\tt write\_freq} steps. For making analysis easier, the trajectory 
-file is written as an ASCII file. By default, no trajectory file
-is written.
+file is written as an ASCII file.
 
-PuReMD can output trajectories either using simple MPI send/receives 
+The distributed memory version of PuReMD
+can output trajectories either using simple MPI send/receives 
 (option 0 which is the default) or using MPI I/O calls (option 1) which 
 are part of the MPI-2 standard. The latter option is supposed to be more 
 efficient (not verified by tests though) but may not be available in some 
 MPI implementations. {\tt traj\_method} option is not applicable to 
 SerialReax simulations.
 
+Defaults: 0 (no trajectory file written), 0 (simple I/O)
+
+
+\subsubsection{traj\_title}
+\label{sec:traj_title}
+\subsubsection{atom\_info}
+\label{sec:atom_info}
+\subsubsection{atom\_forces}
+\label{sec:atom_forces}
+\subsubsection{atom\_velocities}
+\label{sec:atom_velocities}
+\subsubsection{bond\_info}
+\label{sec:bond_info}
+\subsubsection{angle\_info}
+\label{sec:angle_info}
+
 \begin{verbatim}
   traj_title          TEST
   atom_info           1
@@ -370,8 +617,7 @@ box geometry is standard. However, the latter parts of the frame can be
 customized using {\tt atom\_info}, {\tt atom\_forces}, {\tt atom\_velocities}, 
 {\tt bond\_info} and {\tt angle\_info} parameters which are already
 self-explanatory. The ordering is atoms section, bonds section and angles 
-section assuming that they are all present. By default, all atom, bond and 
-angle information outputting is turned off.
+section assuming that they are all present.
 
 One nice property of the custom trajectory format is that each part of 
 the trajectory is prepended by a number that can be used to skip that part.
@@ -384,7 +630,7 @@ within a trajectory frame as well, making it easy to skip parts which are
 not of interest to a particular trajectory analysis procedure. So the 
 general layout of our custom trajectory format is as follows (assuming 
 all trajectory options are turned on):
-\begin{verbatim}
+\begin{lstlisting}
 CHARS_TO_SKIP_SECTION
 trajectory header
 CHARS_TO_SKIP_ATOM_DESCS NUM_LINES
@@ -397,9 +643,7 @@ CHARS_TO_SKIP_BOND_LINES NUM_BOND_LINES
 frame1 bond info
 CHARS_TO_SKIP_ANGLE_LINES NUM_ANGLE_LINES
 frame1 angle info
-.
-.
-.
+$\vdots$
 CHARS_TO_SKIP_FRAME_HEADER
 frameN header
 CHARS_TO_SKIP_ATOM_LINES NUM_ATOM_LINES
@@ -408,11 +652,11 @@ CHARS_TO_SKIP_BOND_LINES NUM_BOND_LINES
 frameN bond info
 CHARS_TO_SKIP_ANGLE_LINES NUM_ANGLE_LINES
 frameN angle info
-\end{verbatim}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\end{lstlisting}
+
+Defaults: default\_title, 0, 0, 0, 0, 0 (all off)
 
 
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \section{SerialReax Extras}
 \label{sec:serialreax_extras}
 
@@ -420,27 +664,27 @@ In this section, we explain the parameters found in SerialReax but not in
 PuReMD. Our work towards adding the same functionalities into PuReMD is 
 underway.
 
-In addition to the PCG solver, SerialReax features a preconditioned GMRES 
-(PGMRES) solver and an incomplete LU factorization (ILU) based  
-preconditioning scheme. An ILU factorization essentially does the 
-same thing as an LU factorization but small terms in the matrix are dropped
-to expedite the factorization and to prevent a huge number of fill-ins in the
-factor matrices. Following are the extra control parameters found in 
-SerialReax regarding the QEq solver:
-\begin{verbatim}
-  ilu_refactor        100
-  ilu_droptol         0.01
-\end{verbatim}
-{\tt ilu\_droptol} sets the threshold for dropping small terms in the 
-resulting ILU factors. Suggested (and the default) value for 
-{\tt ilu\_droptol} is $10^{-2}$. Despite the drop rules, ILU factorization 
-is still a costly operation. So a user can choose to perform it at 
-every {\tt ilu\_refactor} steps. The fact that atoms move very slowly in an 
-MD simulation allows the use of same ILU factors as preconditioners in the 
-subsequent steps with little performance loss. For liquids, this frequency 
-can be on the order of 100-200 steps, for solids it can go up to thousands 
-of steps depending on how fast atoms are moving. The default for 
-{\tt ilu\_refactor} is 100.
+%In addition to the PCG solver, SerialReax features a preconditioned GMRES 
+%(PGMRES) solver and an incomplete LU factorization (ILU) based  
+%preconditioning scheme. An ILU factorization essentially does the 
+%same thing as an LU factorization but small terms in the matrix are dropped
+%to expedite the factorization and to prevent a huge number of fill-ins in the
+%factor matrices. Following are the extra control parameters found in 
+%SerialReax regarding the QEq solver:
+%\begin{verbatim}
+%  ilu_refactor        100
+%  ilu_droptol         0.01
+%\end{verbatim}
+%{\tt ilu\_droptol} sets the threshold for dropping small terms in the 
+%resulting ILU factors. Suggested (and the default) value for 
+%{\tt ilu\_droptol} is $10^{-2}$. Despite the drop rules, ILU factorization 
+%is still a costly operation. So a user can choose to perform it at 
+%every {\tt ilu\_refactor} steps. The fact that atoms move very slowly in an 
+%MD simulation allows the use of same ILU factors as preconditioners in the 
+%subsequent steps with little performance loss. For liquids, this frequency 
+%can be on the order of 100-200 steps, for solids it can go up to thousands 
+%of steps depending on how fast atoms are moving. The default for 
+%{\tt ilu\_refactor} is 100.
 
 \begin{verbatim}
   t_mode        0
@@ -542,28 +786,56 @@ in molecular analysis.
 \section{Compilation and Execution}
 \label{sec:puremd_execute}
 
-PuReMD is distributed in the {\tt tar.gz} compression format which can 
+PuReMD is distributed in the \mintinline{bash}{tar.gz} compression format which can 
 be extracted under a Unix system with the following command:
-\begin{verbatim}
-  gtar xvzf PuReMD.tar.gz
-\end{verbatim}
-
-This results in the creation of a new directory, named {\tt PuReMD}, will appear in the working 
-directory. It contains the source code directory ({\tt src}) 
-along with a directory for sample systems ({\tt examples}).
-
-PuReMD can be compiled by switching to the {\tt src} directory and 
-running {\tt make}. The executable, {\tt puremd}, will be created inside 
-the source directory. The Makefile that comes in the distribution assumes 
-OpenMPI as the default MPI implementation and {\tt mpicc} as the default 
-MPI compiler. In case you have a different MPI implementation, 
-please set your MPI compiler in the Makefile appropriately. 
+\mint{bash}{tar -xvf PuReMD.tar.gz}
+
+This results in the creation of a new directory, named \mintinline{bash}{PuReMD}, which will
+appear in the working directory. The base directory contains a configure script
+along with the necessary makefiles to compile a particular version of the
+software; these steps are elaborated further below.  (For developers only: see
+the documentation on the Gitlab server for how to generate these files using
+the GNU Autotools) In addition, there is also a directory with several sample
+systems and force field files (\mintinline{bash}{data/benchmarks}), and a
+directory with relevant documentation including this user manual
+({\mintinline{bash}{doc}).
+
+To build PuReMD, you must run the following sequence of commands:
+\begin{minted}{bash}
+  ./configure
+  make
+  make install # optional
+\end{minted}
+
+Upon successful compilation, a binary executable file will be located
+in \mintinline{bash}{*/bin}, where \mintinline{bash}{*} is one of the
+following directories:
+\begin{minted}{bash}
+  sPuReMD    # serial/OpenMP shared memory code
+  PuReMD-GPU # GPU shared memory code
+  PuReMD     # MPI distributed memory code
+  PG-PuReMD  # MPI+GPU shared memory code
+\end{minted}
+
+There are several different versions of PuReMD which can be compiled,
+and these versions can be enabled or disabled via the following options
+to the configure script:
+\begin{minted}{bash}
+  --enable-serial=yes  # build serial shared memory version
+  --enable-openmp=yes  # build OpenMP shared memory version
+  --enable-gpu=yes     # build GPU shared memory version
+  --enable-mpi=yes     # build MPI distributed memory version
+  --enable-mpi-gpu=yes # build MPI+GPU distributed memory version
+\end{minted}
+Furthermore, run \mintinline{bash}{./configure --help} to see the full list
+of variables and options which can be set.
 
 PuReMD requires 3 input files as mentioned in section~\ref{sec:puremd_inp}. 
-For example, the command to run {\tt puremd} with OpenMPI is as follows:
-\begin{verbatim}
-  mpirun -np #p -machinefile m.txt puremd geo ffield control
-\end{verbatim}
+For example, the command to run \mintinline{bash}{puremd} with OpenMPI is as follows:
+\begin{minted}{bash}
+  mpirun -np num_procs -machinefile m.txt PuReMD/bin/puremd
+    path/to/geo path/to/ffield path/to/control
+\end{minted}
 
 SerialReax comes in a similar distribution format and Makefile,
 so instructions for compiling and running PuReMD is applicable for 
@@ -623,7 +895,7 @@ by its unique extension:
 Apart from these, there might be some text printed to \emph{stderr} 
 for debugging purposes. If you encounter some problems with the code
 (like a segmentation fault or unexpected termination of the code),
-please contact \href{mailto:haktulga@cs.purdue.edu}{haktulga@cs.purdue.edu} with the error message 
+please contact \href{mailto:hma@cse.msu.edu}{here} with the error message 
 printed to \emph{stderr} and your input files.
 
 In addition to the output files above, SerialReax can output another
diff --git a/environ/param.gpu.water b/environ/param.gpu.water
index c60563a65262252e95ec6d82a32da97ecc389bf0..eed406e7e9e7eaad12d4c1f22e9db0aa166a5b9d 100644
--- a/environ/param.gpu.water
+++ b/environ/param.gpu.water
@@ -14,16 +14,19 @@ bond_graph_cutoff       0.3                     ! bond strength cutoff for bond
 thb_cutoff              0.001                   ! cutoff value for three body interactions (Angstroms)
 hbond_cutoff            7.50                    ! cutoff distance for hydrogen bond interactions (Angstroms)
 
-charge_freq             1                       ! frequency (sim step) at which atomic charges are computed
-qeq_solver_type         0                       ! iterative linear solver used for equilibration kernel (QEq)
-qeq_solver_q_err        1e-6                    ! relative residual norm threshold used in solver
-qeq_domain_sparsity     1.0                     ! scalar for scaling cut-off distance, used to sparsify QEq matrix (between 0.0 and 1.0)
-pre_comp_type           1                       ! method used to compute QEq preconditioner, if applicable
-pre_comp_refactor       100                     ! nsteps to recompute preconditioner
-pre_comp_droptol        0.0                     ! threshold tolerance for dropping values in preconditioner computation, if applicable
-pre_comp_sweeps         3                       ! sweeps to compute preconditioner (ILU_PAR)
-pre_app_type            1                       ! method used to apply QEq preconditioner
-pre_app_jacobi_iters    50                      ! number of Jacobi iterations used for applying QEq precondition, if applicable
+charge_method         		  0             ! charge method: 0 = QEq, 1 = EEM, 2 = ACKS2
+cm_q_net              		  0.0           ! net system charge
+cm_solver_type        		  0             ! iterative linear solver for charge method: 0 = GMRES, 1 = GMRES_H, 2 = CG, 3 = SDM
+cm_solver_max_iters   		  20            ! max solver iterations
+cm_solver_restart     		  100           ! inner iterations of GMRES before restarting
+cm_solver_q_err       		  1e-6          ! relative residual norm threshold used in solver
+cm_domain_sparsity     		  1.0           ! scalar for scaling cut-off distance, used to sparsify charge matrix (between 0.0 and 1.0)
+cm_solver_pre_comp_type           1             ! method used to compute preconditioner, if applicable
+cm_solver_pre_comp_refactor       1000          ! number of steps before recomputing preconditioner
+cm_solver_pre_comp_droptol        0.0           ! threshold tolerance for dropping values in preconditioner computation, if applicable
+cm_solver_pre_comp_sweeps         3             ! number of sweeps used to compute preconditioner (ILU_PAR)
+cm_solver_pre_app_type            1             ! method used to apply preconditioner
+cm_solver_pre_app_jacobi_iters    50            ! number of Jacobi iterations used for applying precondition, if applicable
 
 temp_init               0.0                     ! desired initial temperature of the simulated system
 temp_final              300.0                   ! desired final temperature of the simulated system
@@ -56,3 +59,6 @@ freq_dipole_anal        1                       ! calculate electric dipole mome
 diffusion_coef          0                       ! 1: calculate diffusion coefficient of the system
 freq_diffusion_coef     1                       ! calculate diffusion coefficient at every 'this many' steps
 restrict_type           2                       ! -1: all types of atoms, 0 and up: only this type of atoms
+
+restart_format          1                       ! 0: restarts in ASCII  1: restarts in binary
+restart_freq            0                       ! 0: do not output any restart files. >0: output a restart file at every 'this many' steps
diff --git a/sPuReMD/Makefile.am b/sPuReMD/Makefile.am
index 12cffee9894677d37875b1d6dc9576d723447f21..4102573deee8d6fefac290cce49f0755bd726200 100644
--- a/sPuReMD/Makefile.am
+++ b/sPuReMD/Makefile.am
@@ -4,7 +4,7 @@ bin_PROGRAMS = bin/spuremd
 bin_spuremd_SOURCES = src/ffield.c src/grid.c src/list.c src/lookup.c src/print_utils.c \
 		  src/reset_utils.c src/restart.c src/random.c src/tool_box.c src/traj.c \
 		  src/vector.c src/allocate.c src/analyze.c src/box.c src/system_props.c src/control.c \
-		  src/geo_tools.c src/neighbors.c src/lin_alg.c src/qeq.c src/bond_orders.c \
+		  src/geo_tools.c src/neighbors.c src/lin_alg.c src/charges.c src/bond_orders.c \
 		  src/single_body_interactions.c src/two_body_interactions.c \
 		  src/three_body_interactions.c src/four_body_interactions.c src/forces.c \
 		  src/integrate.c src/init_md.c src/testmd.c 
@@ -12,7 +12,7 @@ bin_spuremd_SOURCES = src/ffield.c src/grid.c src/list.c src/lookup.c src/print_
 include_HEADERS = src/mytypes.h src/ffield.h src/grid.h src/list.h src/lookup.h src/print_utils.h \
 		  src/reset_utils.h src/restart.h src/random.h src/tool_box.h src/traj.h \
 		  src/vector.h src/allocate.h src/analyze.h src/box.h src/system_props.h src/control.h \
-		  src/geo_tools.h src/neighbors.h src/lin_alg.h src/qeq.h src/bond_orders.h \
+		  src/geo_tools.h src/neighbors.h src/lin_alg.h src/charges.h src/bond_orders.h \
 		  src/single_body_interactions.h src/two_body_interactions.h \
 		  src/three_body_interactions.h src/four_body_interactions.h src/forces.h \
 		  src/integrate.h src/init_md.h
diff --git a/sPuReMD/configure.ac b/sPuReMD/configure.ac
index 578c00d4de6ee81ee70318e79c0dc266129d2b19..57b6b8ea8bcebe279ea1e14c11c28a6e66cea439 100644
--- a/sPuReMD/configure.ac
+++ b/sPuReMD/configure.ac
@@ -60,7 +60,7 @@ if test "x$ax_cv_c_compiler_vendor" = "xintel"; then
 fi
 
 # Check for OpenMP support.
-if test "x$BUILD_OPENMP" = "xyes"; then
+if test "x${BUILD_OPENMP}" = "xyes"; then
 	AC_OPENMP
 	if test "x${OPENMP_CFLAGS}" = "x"; then
 		AC_MSG_WARN([
@@ -70,7 +70,7 @@ if test "x$BUILD_OPENMP" = "xyes"; then
 	  -----------------------------------------------])
 	else
 		# bug due to recent Intel compiler change (?)
-		if test "x$ax_cv_c_compiler_vendor" = "xintel"; then
+		if test "x${ax_cv_c_compiler_vendor}" = "xintel"; then
 			OPENMP_CFLAGS="-qopenmp"
 		fi
 		AC_SUBST(AM_CFLAGS, "$OPENMP_CFLAGS")
diff --git a/sPuReMD/src/allocate.c b/sPuReMD/src/allocate.c
index c9c5321c0e7a18cec76584e97ee02509021a3671..ab075f94e4537120d9229efb1f073e886e1f28e8 100644
--- a/sPuReMD/src/allocate.c
+++ b/sPuReMD/src/allocate.c
@@ -73,6 +73,7 @@ void Reallocate_Neighbor_List( list *far_nbrs, int n, int num_intrs )
 }
 
 
+/* dynamic allocation of memory for matrix in CSR format */
 int Allocate_Matrix( sparse_matrix **pH, int n, int m )
 {
     sparse_matrix *H;
@@ -86,8 +87,8 @@ int Allocate_Matrix( sparse_matrix **pH, int n, int m )
     H->n = n;
     H->m = m;
 
-    if ( (H->start = (unsigned int*) malloc(sizeof(int) * (n + 1))) == NULL
-            || (H->j = (unsigned int*) malloc(sizeof(int) * m)) == NULL
+    if ( (H->start = (unsigned int*) malloc(sizeof(unsigned int) * (n + 1))) == NULL
+            || (H->j = (unsigned int*) malloc(sizeof(unsigned int) * m)) == NULL
             || (H->val = (real*) malloc(sizeof(real) * m)) == NULL )
     {
         return FAILURE;
@@ -97,6 +98,7 @@ int Allocate_Matrix( sparse_matrix **pH, int n, int m )
 }
 
 
+/* deallocate memory for matrix in CSR format */
 void Deallocate_Matrix( sparse_matrix *H )
 {
     free(H->start);
@@ -278,7 +280,7 @@ void Reallocate( reax_system *system, static_storage *workspace, list **lists,
 
     if ( realloc->Htop > 0 )
     {
-        Reallocate_Matrix(&(workspace->H), system->N, realloc->Htop * SAFE_ZONE, "H");
+        Reallocate_Matrix(&(workspace->H), system->N_cm, realloc->Htop * SAFE_ZONE, "H");
         realloc->Htop = -1;
 
         Deallocate_Matrix( workspace->L );
diff --git a/sPuReMD/src/qeq.c b/sPuReMD/src/charges.c
similarity index 50%
rename from sPuReMD/src/qeq.c
rename to sPuReMD/src/charges.c
index be99a1fd42194fc18b467a913f7a74485c125bec..f81fba699cf4bb451c7a71911772a3ecf1a424da 100644
--- a/sPuReMD/src/qeq.c
+++ b/sPuReMD/src/charges.c
@@ -19,18 +19,26 @@
   <http://www.gnu.org/licenses/>.
   ----------------------------------------------------------------------*/
 
-#include "qeq.h"
+#include "charges.h"
 
 #include "allocate.h"
 #include "list.h"
 #include "lin_alg.h"
 #include "print_utils.h"
 #include "tool_box.h"
+#include "vector.h"
 #if defined(HAVE_SUPERLU_MT)
 #include "slu_mt_ddefs.h"
 #endif
 
 
+typedef struct
+{
+    unsigned int j;
+    real val;
+} sparse_matrix_entry;
+
+
 #if defined(TEST_MAT)
 static sparse_matrix * create_test_mat( void )
 {
@@ -84,7 +92,7 @@ static sparse_matrix * create_test_mat( void )
 static int compare_matrix_entry(const void *v1, const void *v2)
 {
     /* larger element has larger column index */
-    return *(unsigned int *)v1 - *(unsigned int *)v2;
+    return ((sparse_matrix_entry *)v1)->j - ((sparse_matrix_entry *)v2)->j;
 }
 
 
@@ -96,57 +104,47 @@ static int compare_matrix_entry(const void *v1, const void *v2)
  */
 static void Sort_Matrix_Rows( sparse_matrix * const A )
 {
-    unsigned int i, j, k, si, ei, *temp_j;
-    real *temp_val;
+    unsigned int i, j, si, ei;
+    sparse_matrix_entry *temp;
 
-    #pragma omp parallel default(none) private(i, j, k, si, ei, temp_j, temp_val) shared(stderr)
+//    #pragma omp parallel default(none) private(i, j, si, ei, temp) shared(stderr)
     {
-        if ( ( temp_j = (unsigned int*) malloc( A->n * sizeof(unsigned int)) ) == NULL
-                || ( temp_val = (real*) malloc( A->n * sizeof(real)) ) == NULL )
+        if ( ( temp = (sparse_matrix_entry *) malloc( A->n * sizeof(sparse_matrix_entry)) ) == NULL )
         {
             fprintf( stderr, "Not enough space for matrix row sort. Terminating...\n" );
             exit( INSUFFICIENT_MEMORY );
         }
 
         /* sort each row of A using column indices */
-        #pragma omp for schedule(guided)
+//        #pragma omp for schedule(guided)
         for ( i = 0; i < A->n; ++i )
         {
             si = A->start[i];
             ei = A->start[i + 1];
-            memcpy( temp_j, A->j + si, sizeof(unsigned int) * (ei - si) );
-            memcpy( temp_val, A->val + si, sizeof(real) * (ei - si) );
 
-            //TODO: consider implementing single custom one-pass sort instead of using qsort + manual sort
+            for ( j = 0; j < (ei - si); ++j )
+            {
+                (temp + j)->j = A->j[si + j];
+                (temp + j)->val = A->val[si + j];
+            }
+
             /* polymorphic sort in standard C library using column indices */
-            qsort( temp_j, ei - si, sizeof(unsigned int), compare_matrix_entry );
+            qsort( temp, ei - si, sizeof(sparse_matrix_entry), compare_matrix_entry );
 
-            /* manually sort vals */
             for ( j = 0; j < (ei - si); ++j )
             {
-                for ( k = 0; k < (ei - si); ++k )
-                {
-                    if ( A->j[si + j] == temp_j[k] )
-                    {
-                        A->val[si + k] = temp_val[j];
-                        break;
-                    }
-
-                }
+                A->j[si + j] = (temp + j)->j;
+                A->val[si + j] = (temp + j)->val;
             }
-
-            /* copy sorted column indices */
-            memcpy( A->j + si, temp_j, sizeof(unsigned int) * (ei - si) );
         }
 
-        free( temp_val );
-        free( temp_j );
+        free( temp );
     }
 }
 
 
-static void Calculate_Droptol( const sparse_matrix * const A, real * const droptol,
-        const real dtol )
+static void Calculate_Droptol( const sparse_matrix * const A,
+        real * const droptol, const real dtol )
 {
     int i, j, k;
     real val;
@@ -207,7 +205,8 @@ static void Calculate_Droptol( const sparse_matrix * const A, real * const dropt
 #endif
             }
 
-            val = A->val[k]; // diagonal entry
+            // diagonal entry
+            val = A->val[k];
 #ifdef _OPENMP
             droptol_local[tid * A->n + i] += val * val;
 #else
@@ -275,7 +274,7 @@ static int Estimate_LU_Fill( const sparse_matrix * const A, const real * const d
 
 #if defined(HAVE_SUPERLU_MT)
 static real SuperLU_Factorize( const sparse_matrix * const A,
-        sparse_matrix * const L, sparse_matrix * const U )
+                               sparse_matrix * const L, sparse_matrix * const U )
 {
     unsigned int i, pj, count, *Ltop, *Utop, r;
     sparse_matrix *A_t;
@@ -572,7 +571,7 @@ static real SuperLU_Factorize( const sparse_matrix * const A,
 
 
 /* Diagonal (Jacobi) preconditioner computation */
-static real diag_pre_comp( const reax_system * const system, real * const Hdia_inv )
+static real diag_pre_comp( const sparse_matrix * const H, real * const Hdia_inv )
 {
     unsigned int i;
     real start;
@@ -580,10 +579,17 @@ static real diag_pre_comp( const reax_system * const system, real * const Hdia_i
     start = Get_Time( );
 
     #pragma omp parallel for schedule(static) \
-    default(none) private(i)
-    for ( i = 0; i < system->N; ++i )
+        default(none) private(i)
+    for ( i = 0; i < H->n; ++i )
     {
-        Hdia_inv[i] = 1.0 / system->reaxprm.sbp[system->atoms[i].type].eta;
+        if ( H->val[H->start[i + 1] - 1] != 0.0 )
+        {
+            Hdia_inv[i] = 1.0 / H->val[H->start[i + 1] - 1];
+        }
+        else
+        {
+            Hdia_inv[i] = 1.0;
+        }
     }
 
     return Get_Timing_Info( start );
@@ -598,15 +604,15 @@ static real ICHOLT( const sparse_matrix * const A, const real * const droptol,
     real *tmp_val;
     int i, j, pj, k1, k2, tmptop, Ltop;
     real val, start;
-    int *Utop;
+    unsigned int *Utop;
 
     start = Get_Time( );
 
-    if ( ( Utop = (int*) malloc((A->n + 1) * sizeof(int)) ) == NULL ||
+    if ( ( Utop = (unsigned int*) malloc((A->n + 1) * sizeof(unsigned int)) ) == NULL ||
             ( tmp_j = (int*) malloc(A->n * sizeof(int)) ) == NULL ||
             ( tmp_val = (real*) malloc(A->n * sizeof(real)) ) == NULL )
     {
-        fprintf( stderr, "not enough memory for ICHOLT preconditioning matrices. terminating.\n" );
+        fprintf( stderr, "[ICHOLT] Not enough memory for preconditioning matrices. terminating.\n" );
         exit( INSUFFICIENT_MEMORY );
     }
 
@@ -617,7 +623,6 @@ static real ICHOLT( const sparse_matrix * const A, const real * const droptol,
     memset( U->start, 0, (A->n + 1) * sizeof(unsigned int) );
     memset( Utop, 0, A->n * sizeof(unsigned int) );
 
-    //fprintf( stderr, "n: %d\n", A->n );
     for ( i = 0; i < A->n; ++i )
     {
         L->start[i] = Ltop;
@@ -627,7 +632,6 @@ static real ICHOLT( const sparse_matrix * const A, const real * const droptol,
         {
             j = A->j[pj];
             val = A->val[pj];
-            //fprintf( stderr, "i: %d, j: %d", i, j );
 
             if ( FABS(val) > droptol[i] )
             {
@@ -657,13 +661,12 @@ static real ICHOLT( const sparse_matrix * const A, const real * const droptol,
                 tmp_val[tmptop] = val;
                 ++tmptop;
             }
-            //fprintf( stderr, " -- done\n" );
         }
 
         // sanity check
         if ( A->j[pj] != i )
         {
-            fprintf( stderr, "i=%d, badly built A matrix!\n", i );
+            fprintf( stderr, "[ICHOLT] badly built A matrix!\n (i = %d) ", i );
             exit( NUMERIC_BREAKDOWN );
         }
 
@@ -674,8 +677,17 @@ static real ICHOLT( const sparse_matrix * const A, const real * const droptol,
             val -= (tmp_val[k1] * tmp_val[k1]);
         }
 
+#if defined(DEBUG)
+        if ( val < 0.0 )
+        {
+            fprintf( stderr, "[ICHOLT] Numeric breakdown (SQRT of negative on diagonal i = %d). Terminating.\n", i );
+            exit( NUMERIC_BREAKDOWN );
+
+        }
+#endif
+
         tmp_j[tmptop] = i;
-        tmp_val[tmptop] = SQRT(val);
+        tmp_val[tmptop] = SQRT( val );
 
         // apply the dropping rule once again
         //fprintf( stderr, "row%d: tmptop: %d\n", i, tmptop );
@@ -738,7 +750,7 @@ static real ICHOLT( const sparse_matrix * const A, const real * const droptol,
  * Fine-Grained Parallel Incomplete LU Factorization
  * SIAM J. Sci. Comp. */
 static real ICHOL_PAR( const sparse_matrix * const A, const unsigned int sweeps,
-        sparse_matrix * const U_t, sparse_matrix * const U )
+                       sparse_matrix * const U_t, sparse_matrix * const U )
 {
     unsigned int i, j, k, pj, x = 0, y = 0, ei_x, ei_y;
     real *D, *D_inv, sum, start;
@@ -757,7 +769,7 @@ static real ICHOL_PAR( const sparse_matrix * const A, const unsigned int sweeps,
     }
 
     #pragma omp parallel for schedule(static) \
-        default(none) shared(D_inv, D) private(i)
+    default(none) shared(D_inv, D) private(i)
     for ( i = 0; i < A->n; ++i )
     {
         D_inv[i] = SQRT( A->val[A->start[i + 1] - 1] );
@@ -771,7 +783,7 @@ static real ICHOL_PAR( const sparse_matrix * const A, const unsigned int sweeps,
      * transformation DAD, where D = D(1./sqrt(D(A))) */
     memcpy( DAD->start, A->start, sizeof(int) * (A->n + 1) );
     #pragma omp parallel for schedule(guided) \
-        default(none) shared(DAD, D_inv, D) private(i, pj)
+    default(none) shared(DAD, D_inv, D) private(i, pj)
     for ( i = 0; i < A->n; ++i )
     {
         /* non-diagonals */
@@ -795,7 +807,7 @@ static real ICHOL_PAR( const sparse_matrix * const A, const unsigned int sweeps,
     {
         /* for each nonzero */
         #pragma omp parallel for schedule(static) \
-            default(none) shared(DAD, stderr) private(sum, ei_x, ei_y, k) firstprivate(x, y)
+        default(none) shared(DAD, stderr) private(sum, ei_x, ei_y, k) firstprivate(x, y)
         for ( j = 0; j < A->start[A->n]; ++j )
         {
             sum = ZERO;
@@ -845,7 +857,7 @@ static real ICHOL_PAR( const sparse_matrix * const A, const unsigned int sweeps,
                 /* sanity check */
                 if ( sum < ZERO )
                 {
-                    fprintf( stderr, "Numeric breakdown in ICHOL Terminating.\n");
+                    fprintf( stderr, "Numeric breakdown in ICHOL_PAR. Terminating.\n");
 #if defined(DEBUG_FOCUS)
                     fprintf( stderr, "A(%5d,%5d) = %10.3f\n",
                              k - 1, A->entries[j].j, A->entries[j].val );
@@ -868,7 +880,7 @@ static real ICHOL_PAR( const sparse_matrix * const A, const unsigned int sweeps,
      * since DAD \approx U^{T}U, so
      * D^{-1}DADD^{-1} = A \approx D^{-1}U^{T}UD^{-1} */
     #pragma omp parallel for schedule(guided) \
-        default(none) shared(D_inv) private(i, pj)
+    default(none) shared(D_inv) private(i, pj)
     for ( i = 0; i < A->n; ++i )
     {
         for ( pj = A->start[i]; pj < A->start[i + 1]; ++pj )
@@ -908,7 +920,7 @@ static real ICHOL_PAR( const sparse_matrix * const A, const unsigned int sweeps,
  * sweeps: number of loops over non-zeros for computation
  * L / U: factorized triangular matrices (A \approx LU), CSR format */
 static real ILU_PAR( const sparse_matrix * const A, const unsigned int sweeps,
-                     sparse_matrix * const L, sparse_matrix * const U )
+        sparse_matrix * const L, sparse_matrix * const U )
 {
     unsigned int i, j, k, pj, x, y, ei_x, ei_y;
     real *D, *D_inv, sum, start;
@@ -920,23 +932,24 @@ static real ILU_PAR( const sparse_matrix * const A, const unsigned int sweeps,
             ( D = (real*) malloc(A->n * sizeof(real)) ) == NULL ||
             ( D_inv = (real*) malloc(A->n * sizeof(real)) ) == NULL )
     {
-        fprintf( stderr, "not enough memory for ILU_PAR preconditioning matrices. terminating.\n" );
+        fprintf( stderr, "[ILU_PAR] Not enough memory for preconditioning matrices. Terminating.\n" );
         exit( INSUFFICIENT_MEMORY );
     }
 
     #pragma omp parallel for schedule(static) \
-        default(none) shared(D, D_inv) private(i)
+    default(none) shared(D, D_inv) private(i)
     for ( i = 0; i < A->n; ++i )
     {
-        D_inv[i] = SQRT( A->val[A->start[i + 1] - 1] );
+        D_inv[i] = SQRT( FABS( A->val[A->start[i + 1] - 1] ) );
         D[i] = 1.0 / D_inv[i];
+//        printf( "A->val[%8d] = %f, D[%4d] = %f, D_inv[%4d] = %f\n", A->start[i + 1] - 1, A->val[A->start[i + 1] - 1], i, D[i], i, D_inv[i] );
     }
 
     /* to get convergence, A must have unit diagonal, so apply
-     * transformation DAD, where D = D(1./sqrt(D(A))) */
+     * transformation DAD, where D = D(1./sqrt(abs(D(A)))) */
     memcpy( DAD->start, A->start, sizeof(int) * (A->n + 1) );
     #pragma omp parallel for schedule(static) \
-        default(none) shared(DAD, D) private(i, pj)
+    default(none) shared(DAD, D) private(i, pj)
     for ( i = 0; i < A->n; ++i )
     {
         /* non-diagonals */
@@ -971,7 +984,7 @@ static real ILU_PAR( const sparse_matrix * const A, const unsigned int sweeps,
     {
         /* for each nonzero in L */
         #pragma omp parallel for schedule(static) \
-            default(none) shared(DAD) private(j, k, x, y, ei_x, ei_y, sum)
+        default(none) shared(DAD) private(j, k, x, y, ei_x, ei_y, sum)
         for ( j = 0; j < DAD->start[DAD->n]; ++j )
         {
             sum = ZERO;
@@ -1021,7 +1034,7 @@ static real ILU_PAR( const sparse_matrix * const A, const unsigned int sweeps,
         }
 
         #pragma omp parallel for schedule(static) \
-            default(none) shared(DAD) private(j, k, x, y, ei_x, ei_y, sum)
+        default(none) shared(DAD) private(j, k, x, y, ei_x, ei_y, sum)
         for ( j = 0; j < DAD->start[DAD->n]; ++j )
         {
             sum = ZERO;
@@ -1072,7 +1085,7 @@ static real ILU_PAR( const sparse_matrix * const A, const unsigned int sweeps,
      * since DAD \approx LU, then
      * D^{-1}DADD^{-1} = A \approx D^{-1}LUD^{-1} */
     #pragma omp parallel for schedule(static) \
-        default(none) shared(DAD, D_inv) private(i, pj)
+    default(none) shared(DAD, D_inv) private(i, pj)
     for ( i = 0; i < DAD->n; ++i )
     {
         for ( pj = DAD->start[i]; pj < DAD->start[i + 1]; ++pj )
@@ -1110,7 +1123,7 @@ static real ILU_PAR( const sparse_matrix * const A, const unsigned int sweeps,
  * sweeps: number of loops over non-zeros for computation
  * L / U: factorized triangular matrices (A \approx LU), CSR format */
 static real ILUT_PAR( const sparse_matrix * const A, const real * droptol,
-        const unsigned int sweeps, sparse_matrix * const L, sparse_matrix * const U )
+                      const unsigned int sweeps, sparse_matrix * const L, sparse_matrix * const U )
 {
     unsigned int i, j, k, pj, x, y, ei_x, ei_y, Ltop, Utop;
     real *D, *D_inv, sum, start;
@@ -1134,10 +1147,10 @@ static real ILUT_PAR( const sparse_matrix * const A, const real * droptol,
     }
 
     #pragma omp parallel for schedule(static) \
-        default(none) shared(D, D_inv) private(i)
+    default(none) shared(D, D_inv) private(i)
     for ( i = 0; i < A->n; ++i )
     {
-        D_inv[i] = SQRT( A->val[A->start[i + 1] - 1] );
+        D_inv[i] = SQRT( FABS( A->val[A->start[i + 1] - 1] ) );
         D[i] = 1.0 / D_inv[i];
     }
 
@@ -1145,7 +1158,7 @@ static real ILUT_PAR( const sparse_matrix * const A, const real * droptol,
      * transformation DAD, where D = D(1./sqrt(D(A))) */
     memcpy( DAD->start, A->start, sizeof(int) * (A->n + 1) );
     #pragma omp parallel for schedule(static) \
-        default(none) shared(DAD, D) private(i, pj)
+    default(none) shared(DAD, D) private(i, pj)
     for ( i = 0; i < A->n; ++i )
     {
         /* non-diagonals */
@@ -1171,7 +1184,7 @@ static real ILUT_PAR( const sparse_matrix * const A, const real * droptol,
 
     /* L has unit diagonal, by convention */
     #pragma omp parallel for schedule(static) \
-        default(none) private(i) shared(L_temp)
+    default(none) private(i) shared(L_temp)
     for ( i = 0; i < A->n; ++i )
     {
         L_temp->val[L_temp->start[i + 1] - 1] = 1.0;
@@ -1231,7 +1244,7 @@ static real ILUT_PAR( const sparse_matrix * const A, const real * droptol,
         }
 
         #pragma omp parallel for schedule(static) \
-            default(none) shared(DAD, L_temp, U_temp) private(j, k, x, y, ei_x, ei_y, sum)
+        default(none) shared(DAD, L_temp, U_temp) private(j, k, x, y, ei_x, ei_y, sum)
         for ( j = 0; j < DAD->start[DAD->n]; ++j )
         {
             sum = ZERO;
@@ -1352,191 +1365,18 @@ static real ILUT_PAR( const sparse_matrix * const A, const real * droptol,
 }
 
 
-/* Setup routine which performs the following:
- *  1) init storage for QEq matrices and other dependent routines
- *  2) compute preconditioner (if sim. step matches refactor step)
- *  3) extrapolate ficticious charges s and t
- */
-static void Init_MatVec( const reax_system * const system, const control_params * const control,
-        simulation_data * const data, static_storage * const workspace, const list * const far_nbrs )
+static void Extrapolate_Charges_QEq( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace )
 {
-    int i, fillin;
-    real s_tmp, t_tmp, time;
-    sparse_matrix *Hptr;
-//    char fname[100];
-
-    if (control->qeq_domain_sparsify_enabled)
-    {
-        Hptr = workspace->H_sp;
-    }
-    else
-    {
-        Hptr = workspace->H;
-    }
-
-#if defined(TEST_MAT)
-    Hptr = create_test_mat( );
-#endif
-
-    if (control->pre_comp_refactor > 0 &&
-            ((data->step - data->prev_steps) % control->pre_comp_refactor == 0 || workspace->L == NULL))
-    {
-        //Print_Linear_System( system, control, workspace, data->step );
-
-        time = Get_Time( );
-        if ( control->pre_comp_type != DIAG_PC )
-        {
-            Sort_Matrix_Rows( workspace->H );
-            if ( control->qeq_domain_sparsify_enabled == TRUE )
-            {
-                Sort_Matrix_Rows( workspace->H_sp );
-            }
-
-            if ( control->pre_app_type == TRI_SOLVE_GC_PA )
-            {
-                if ( control->qeq_domain_sparsify_enabled == TRUE )
-                {
-                    Hptr = setup_graph_coloring( workspace->H_sp );
-                }
-                else
-                {
-                    Hptr = setup_graph_coloring( workspace->H );
-                }
-
-                Sort_Matrix_Rows( Hptr );
-            }
-        }
-        data->timing.QEq_sort_mat_rows += Get_Timing_Info( time );
-
-#if defined(DEBUG)
-        fprintf( stderr, "H matrix sorted\n" );
-#endif
-
-        switch ( control->pre_comp_type )
-        {
-        case DIAG_PC:
-            if ( workspace->Hdia_inv == NULL )
-            {
-                if ( ( workspace->Hdia_inv = (real *) calloc( system->N, sizeof( real ) ) ) == NULL )
-                {
-                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
-                    exit( INSUFFICIENT_MEMORY );
-                }
-            }
-            data->timing.pre_comp += diag_pre_comp( system, workspace->Hdia_inv );
-            break;
-
-        case ICHOLT_PC:
-            Calculate_Droptol( Hptr, workspace->droptol, control->pre_comp_droptol );
-
-#if defined(DEBUG_FOCUS)
-            fprintf( stderr, "drop tolerances calculated\n" );
-#endif
-
-            if ( workspace->L == NULL )
-            {
-                fillin = Estimate_LU_Fill( Hptr, workspace->droptol );
-                if ( Allocate_Matrix( &(workspace->L), far_nbrs->n, fillin ) == FAILURE ||
-                        Allocate_Matrix( &(workspace->U), far_nbrs->n, fillin ) == FAILURE )
-                {
-                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
-                    exit( INSUFFICIENT_MEMORY );
-                }
-
-#if defined(DEBUG)
-                fprintf( stderr, "fillin = %d\n", fillin );
-                fprintf( stderr, "allocated memory: L = U = %ldMB\n",
-                         fillin * sizeof(sparse_matrix_entry) / (1024 * 1024) );
-#endif
-            }
-
-            data->timing.pre_comp += ICHOLT( Hptr, workspace->droptol, workspace->L, workspace->U );
-            break;
-
-        case ILU_PAR_PC:
-            if ( workspace->L == NULL )
-            {
-                /* factors have sparsity pattern as H */
-                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
-                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
-                {
-                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
-                    exit( INSUFFICIENT_MEMORY );
-                }
-            }
-
-            data->timing.pre_comp += ILU_PAR( Hptr, control->pre_comp_sweeps, workspace->L, workspace->U );
-            break;
-
-        case ILUT_PAR_PC:
-            Calculate_Droptol( Hptr, workspace->droptol, control->pre_comp_droptol );
-#if defined(DEBUG_FOCUS)
-            fprintf( stderr, "drop tolerances calculated\n" );
-#endif
-
-            if ( workspace->L == NULL )
-            {
-                /* TODO: safest storage estimate is ILU(0) (same as lower triangular portion of H), could improve later */
-                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
-                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
-                {
-                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
-                    exit( INSUFFICIENT_MEMORY );
-                }
-            }
-
-            data->timing.pre_comp += ILUT_PAR( Hptr, workspace->droptol, control->pre_comp_sweeps,
-                    workspace->L, workspace->U );
-            break;
-
-        case ILU_SUPERLU_MT_PC:
-            if ( workspace->L == NULL )
-            {
-                /* factors have sparsity pattern as H */
-                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
-                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
-                {
-                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
-                    exit( INSUFFICIENT_MEMORY );
-                }
-            }
-
-#if defined(HAVE_SUPERLU_MT)
-            data->timing.pre_comp += SuperLU_Factorize( Hptr, workspace->L, workspace->U );
-#else
-            fprintf( stderr, "SuperLU MT support disabled. Re-compile before enabling. Terminating...\n" );
-            exit( INVALID_INPUT );
-#endif
-            break;
-
-        default:
-            fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
-            exit( INVALID_INPUT );
-            break;
-        }
-
-#if defined(DEBUG)
-        fprintf( stderr, "condest = %f\n", condest(workspace->L, workspace->U) );
-#endif
-
-#if defined(DEBUG_FOCUS)
-        sprintf( fname, "%s.L%d.out", control->sim_name, data->step );
-        Print_Sparse_Matrix2( workspace->L, fname );
-        sprintf( fname, "%s.U%d.out", control->sim_name, data->step );
-        Print_Sparse_Matrix2( workspace->U, fname );
-
-        fprintf( stderr, "icholt-" );
-        //sprintf( fname, "%s.L%d.out", control->sim_name, data->step );
-        //Print_Sparse_Matrix2( workspace->L, fname );
-        //Print_Sparse_Matrix( U );
-#endif
-    }
+    int i;
+    real s_tmp, t_tmp;
 
     /* extrapolation for s & t */
     //TODO: good candidate for vectorization, avoid moving data with head pointer and circular buffer
     #pragma omp parallel for schedule(static) \
-        default(none) private(i, s_tmp, t_tmp)
-    for ( i = 0; i < system->N; ++i )
+    default(none) private(i, s_tmp, t_tmp)
+    for ( i = 0; i < system->N_cm; ++i )
     {
         // no extrapolation
         //s_tmp = workspace->s[0][i];
@@ -1577,106 +1417,1371 @@ static void Init_MatVec( const reax_system * const system, const control_params
 }
 
 
-/* Combine ficticious charges s and t to get atomic charge q
- */
-static void Calculate_Charges( const reax_system * const system, static_storage * const workspace )
+static void Extrapolate_Charges_EE( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace )
 {
     int i;
-    real u, s_sum, t_sum;
+    real s_tmp;
 
-    s_sum = t_sum = 0.;
-    for ( i = 0; i < system->N; ++i )
+    /* extrapolation for s */
+    //TODO: good candidate for vectorization, avoid moving data with head pointer and circular buffer
+    #pragma omp parallel for schedule(static) \
+        default(none) private(i, s_tmp)
+    for ( i = 0; i < system->N_cm; ++i )
     {
-        s_sum += workspace->s[0][i];
-        t_sum += workspace->t[0][i];
-    }
+        // no extrapolation
+        //s_tmp = workspace->s[0][i];
 
-    u = s_sum / t_sum;
-    for ( i = 0; i < system->N; ++i )
-    {
-        system->atoms[i].q = workspace->s[0][i] - u * workspace->t[0][i];
+        // linear
+        //s_tmp = 2 * workspace->s[0][i] - workspace->s[1][i];
+
+        // quadratic
+        //s_tmp = workspace->s[2][i] + 3 * (workspace->s[0][i]-workspace->s[1][i]);
+
+        // cubic
+        s_tmp = 4 * (workspace->s[0][i] + workspace->s[2][i]) -
+                (6 * workspace->s[1][i] + workspace->s[3][i] );
+
+        // 4th order
+        //s_tmp = 5 * (workspace->s[0][i] - workspace->s[3][i]) +
+        //  10 * (-workspace->s[1][i] + workspace->s[2][i] ) + workspace->s[4][i];
+
+        workspace->s[4][i] = workspace->s[3][i];
+        workspace->s[3][i] = workspace->s[2][i];
+        workspace->s[2][i] = workspace->s[1][i];
+        workspace->s[1][i] = workspace->s[0][i];
+        workspace->s[0][i] = s_tmp;
     }
 }
 
 
-/* Main driver method for QEq kernel
- *
- * Rough outline:
- *  1) init / setup routines
- *  2) perform 2 linear solves
- *  3) compute atomic charges based on output of 2)
+/* Compute preconditioner for QEq
  */
-void QEq( reax_system * const system, control_params * const control, simulation_data * const data,
-          static_storage * const workspace, const list * const far_nbrs,
-          const output_controls * const out_control )
+static void Compute_Preconditioner_QEq( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs )
 {
-    int iters;
-
-    Init_MatVec( system, control, data, workspace, far_nbrs );
-
-//    if( data->step == 0 || data->step == 100 )
-//    {
-//      Print_Linear_System( system, control, workspace, data->step );
-//    }
+    real time;
+    sparse_matrix *Hptr;
 
-    switch ( control->qeq_solver_type )
+    if ( control->cm_domain_sparsify_enabled == TRUE )
     {
-    case GMRES_S:
-        iters = GMRES( workspace, control, data, workspace->H, workspace->b_s, control->qeq_solver_q_err,
-                       workspace->s[0], out_control->log,
-                       ((data->step - data->prev_steps) % control->pre_comp_refactor == 0) ? TRUE : FALSE );
-        iters += GMRES( workspace, control, data, workspace->H, workspace->b_t, control->qeq_solver_q_err,
-                        workspace->t[0], out_control->log, FALSE );
-        break;
-    case GMRES_H_S:
-        iters = GMRES_HouseHolder( workspace, control, data, workspace->H, workspace->b_s, control->qeq_solver_q_err,
-                                   workspace->s[0], out_control->log, (data->step - data->prev_steps) % control->pre_comp_refactor == 0 );
-        iters += GMRES_HouseHolder( workspace, control, data, workspace->H, workspace->b_t, control->qeq_solver_q_err,
-                                    workspace->t[0], out_control->log, 0 );
-        break;
-    case CG_S:
-        iters = CG( workspace, workspace->H, workspace->b_s, control->qeq_solver_q_err,
-                    workspace->s[0], out_control->log ) + 1;
-        iters += CG( workspace, workspace->H, workspace->b_t, control->qeq_solver_q_err,
-                     workspace->t[0], out_control->log ) + 1;
-//            iters = CG( workspace, workspace->H, workspace->b_s, control->qeq_solver_q_err,
-//                    workspace->L, workspace->U, workspace->s[0], control->pre_app_type,
-//                    control->pre_app_jacobi_iters, out_control->log ) + 1;
-//            iters += CG( workspace, workspace->H, workspace->b_t, control->qeq_solver_q_err,
-//                    workspace->L, workspace->U, workspace->t[0], control->pre_app_type,
-//                    control->pre_app_jacobi_iters, out_control->log ) + 1;
-        break;
-    case SDM_S:
-        iters = SDM( workspace, workspace->H, workspace->b_s, control->qeq_solver_q_err,
-                     workspace->s[0], out_control->log ) + 1;
-        iters += SDM( workspace, workspace->H, workspace->b_t, control->qeq_solver_q_err,
-                      workspace->t[0], out_control->log ) + 1;
-//            iters = SDM( workspace, workspace->H, workspace->b_s, control->qeq_solver_q_err,
-//                    workspace->L, workspace->U, workspace->s[0], control->pre_app_type,
-//                    control->pre_app_jacobi_iters, out_control->log ) + 1;
-//            iters += SDM( workspace, workspace->H, workspace->b_t, control->qeq_solver_q_err,
-//                    workspace->L, workspace->U, workspace->t[0], control->pre_app_type,
-//                    control->pre_app_jacobi_iters, out_control->log ) + 1;
-        break;
-    default:
-        fprintf( stderr, "Unrecognized QEq solver selection. Terminating...\n" );
-        exit( INVALID_INPUT );
-        break;
+        Hptr = workspace->H_sp;
+    }
+    else
+    {
+        Hptr = workspace->H;
     }
 
-    data->timing.solver_iters += iters;
+    time = Get_Time( );
+    if ( control->cm_solver_pre_app_type == TRI_SOLVE_GC_PA )
+    {
+        if ( control->cm_domain_sparsify_enabled == TRUE )
+        {
+            Hptr = setup_graph_coloring( workspace->H_sp );
+        }
+        else
+        {
+            Hptr = setup_graph_coloring( workspace->H );
+        }
 
-#if defined(DEBUG_FOCUS)
-    fprintf( stderr, "linsolve-" );
+        Sort_Matrix_Rows( Hptr );
+    }
+    data->timing.cm_sort_mat_rows += Get_Timing_Info( time );
+
+#if defined(TEST_MAT)
+    Hptr = create_test_mat( );
 #endif
 
-    Calculate_Charges( system, workspace );
+    switch ( control->cm_solver_pre_comp_type )
+    {
+        case NONE_PC:
+            break;
 
-    //fprintf( stderr, "%d %.9f %.9f %.9f %.9f %.9f %.9f\n",
-    //   data->step,
-    //   workspace->s[0][0], workspace->t[0][0],
-    //   workspace->s[0][1], workspace->t[0][1],
-    //   workspace->s[0][2], workspace->t[0][2] );
-    // if( data->step == control->nsteps )
-    //Print_Charges( system, control, workspace, data->step );
+        case DIAG_PC:
+            data->timing.cm_solver_pre_comp +=
+                diag_pre_comp( Hptr, workspace->Hdia_inv );
+            break;
+
+        case ICHOLT_PC:
+            data->timing.cm_solver_pre_comp +=
+                ICHOLT( Hptr, workspace->droptol, workspace->L, workspace->U );
+            break;
+
+        case ILU_PAR_PC:
+            data->timing.cm_solver_pre_comp +=
+                ILU_PAR( Hptr, control->cm_solver_pre_comp_sweeps, workspace->L, workspace->U );
+            break;
+
+        case ILUT_PAR_PC:
+            data->timing.cm_solver_pre_comp +=
+                ILUT_PAR( Hptr, workspace->droptol, control->cm_solver_pre_comp_sweeps,
+                        workspace->L, workspace->U );
+            break;
+
+        case ILU_SUPERLU_MT_PC:
+#if defined(HAVE_SUPERLU_MT)
+            data->timing.cm_solver_pre_comp +=
+                SuperLU_Factorize( Hptr, workspace->L, workspace->U );
+#else
+            fprintf( stderr, "SuperLU MT support disabled. Re-compile before enabling. Terminating...\n" );
+            exit( INVALID_INPUT );
+#endif
+            break;
+
+        default:
+            fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
+    }
+
+#if defined(DEBUG)
+    if ( control->cm_solver_pre_comp_type != NONE_PC && 
+            control->cm_solver_pre_comp_type != DIAG_PC )
+    {
+        fprintf( stderr, "condest = %f\n", condest(workspace->L, workspace->U) );
+
+#if defined(DEBUG_FOCUS)
+        sprintf( fname, "%s.L%d.out", control->sim_name, data->step );
+        Print_Sparse_Matrix2( workspace->L, fname, NULL );
+        sprintf( fname, "%s.U%d.out", control->sim_name, data->step );
+        Print_Sparse_Matrix2( workspace->U, fname, NULL );
+#endif
+    }
+#endif
+}
+
+
+/* Compute preconditioner for EE
+ */
+//static void Compute_Preconditioner_EE( const reax_system * const system,
+//        const control_params * const control,
+//        simulation_data * const data, static_storage * const workspace,
+//        const list * const far_nbrs )
+//{
+//    int i, top;
+//    static real * ones = NULL, * x = NULL, * y = NULL;
+//    sparse_matrix *Hptr;
+//
+//    Hptr = workspace->H_EE;
+//
+//#if defined(TEST_MAT)
+//    Hptr = create_test_mat( );
+//#endif
+//
+//    if ( ones == NULL )
+//    {
+//        if ( ( ones = (real*) malloc( system->N * sizeof(real)) ) == NULL ||
+//            ( x = (real*) malloc( system->N * sizeof(real)) ) == NULL ||
+//            ( y = (real*) malloc( system->N * sizeof(real)) ) == NULL )
+//        {
+//            fprintf( stderr, "Not enough space for preconditioner computation. Terminating...\n" );
+//            exit( INSUFFICIENT_MEMORY );
+//        }
+//
+//        for ( i = 0; i < system->N; ++i )
+//        {
+//            ones[i] = 1.0;
+//        }
+//    }
+//
+//    switch ( control->cm_solver_pre_comp_type )
+//    {
+//    case DIAG_PC:
+//        data->timing.cm_solver_pre_comp +=
+//            diag_pre_comp( Hptr, workspace->Hdia_inv );
+//        break;
+//
+//    case ICHOLT_PC:
+//        data->timing.cm_solver_pre_comp +=
+//            ICHOLT( Hptr, workspace->droptol, workspace->L_EE, workspace->U_EE );
+//        break;
+//
+//    case ILU_PAR_PC:
+//        data->timing.cm_solver_pre_comp +=
+//            ILU_PAR( Hptr, control->cm_solver_pre_comp_sweeps, workspace->L_EE, workspace->U_EE );
+//        break;
+//
+//    case ILUT_PAR_PC:
+//        data->timing.cm_solver_pre_comp +=
+//            ILUT_PAR( Hptr, workspace->droptol, control->cm_solver_pre_comp_sweeps,
+//                    workspace->L_EE, workspace->U_EE );
+//        break;
+//
+//    case ILU_SUPERLU_MT_PC:
+//#if defined(HAVE_SUPERLU_MT)
+//        data->timing.cm_solver_pre_comp +=
+//            SuperLU_Factorize( Hptr, workspace->L_EE, workspace->U_EE );
+//#else
+//        fprintf( stderr, "SuperLU MT support disabled. Re-compile before enabling. Terminating...\n" );
+//        exit( INVALID_INPUT );
+//#endif
+//        break;
+//
+//    default:
+//        fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
+//        exit( INVALID_INPUT );
+//        break;
+//    }
+//
+//    if ( control->cm_solver_pre_comp_type != DIAG_PC )
+//    {
+//        switch ( control->cm_solver_pre_app_type )
+//        {
+//            case TRI_SOLVE_PA:
+//                tri_solve( workspace->L_EE, ones, x, workspace->L_EE->n, LOWER );
+//                Transpose_I( workspace->U_EE );
+//                tri_solve( workspace->U_EE, ones, y, workspace->U_EE->n, LOWER );
+//                Transpose_I( workspace->U_EE );
+//
+//                memcpy( workspace->L->start, workspace->L_EE->start, sizeof(unsigned int) * (system->N + 1) );
+//                memcpy( workspace->L->j, workspace->L_EE->j, sizeof(unsigned int) * workspace->L_EE->start[workspace->L_EE->n] );
+//                memcpy( workspace->L->val, workspace->L_EE->val, sizeof(real) * workspace->L_EE->start[workspace->L_EE->n] );
+//
+//                top = workspace->L->start[system->N];
+//                for ( i = 0; i < system->N; ++i )
+//                {
+//                    workspace->L->j[top] = i;
+//                    workspace->L->val[top] = x[i];
+//                    ++top;
+//                }
+//
+//                workspace->L->j[top] = system->N_cm - 1;
+//                workspace->L->val[top] = 1.0;
+//                ++top;
+//
+//                workspace->L->start[system->N_cm] = top;
+//
+//                top = 0;
+//                for ( i = 0; i < system->N; ++i )
+//                {
+//                    workspace->U->start[i] = top;
+//                    memcpy( workspace->U->j + top, workspace->U_EE->j + workspace->U_EE->start[i],
+//                            sizeof(unsigned int) * (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]) );
+//                    memcpy( workspace->U->val + top, workspace->U_EE->val + workspace->U_EE->start[i],
+//                            sizeof(real) * (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]) );
+//                    top += (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]);
+//
+//                    workspace->U->j[top] = system->N_cm - 1;
+//                    workspace->U->val[top] = y[i];
+//                    ++top;
+//                }
+//
+//                workspace->U->start[system->N_cm - 1] = top;
+//
+//                workspace->U->j[top] = system->N_cm - 1;
+//                workspace->U->val[top] = -Dot( x, y, system->N );
+//                ++top;
+//
+//                workspace->U->start[system->N_cm] = top;
+//                break;
+//
+//            case TRI_SOLVE_LEVEL_SCHED_PA:
+//                tri_solve_level_sched( workspace->L_EE, ones, x, workspace->L_EE->n, LOWER, TRUE );
+//                Transpose_I( workspace->U_EE );
+//                tri_solve_level_sched( workspace->U_EE, ones, y, workspace->U_EE->n, LOWER, TRUE );
+//                Transpose_I( workspace->U_EE );
+//
+//                memcpy( workspace->L->start, workspace->L_EE->start, sizeof(unsigned int) * (system->N + 1) );
+//                memcpy( workspace->L->j, workspace->L_EE->j, sizeof(unsigned int) * workspace->L_EE->start[workspace->L_EE->n] );
+//                memcpy( workspace->L->val, workspace->L_EE->val, sizeof(real) * workspace->L_EE->start[workspace->L_EE->n] );
+//
+//                top = workspace->L->start[system->N];
+//                for ( i = 0; i < system->N; ++i )
+//                {
+//                    workspace->L->j[top] = i;
+//                    workspace->L->val[top] = x[i];
+//                    ++top;
+//                }
+//
+//                workspace->L->j[top] = system->N_cm - 1;
+//                workspace->L->val[top] = 1.0;
+//                ++top;
+//
+//                workspace->L->start[system->N_cm] = top;
+//
+//                top = 0;
+//                for ( i = 0; i < system->N; ++i )
+//                {
+//                    workspace->U->start[i] = top;
+//                    memcpy( workspace->U->j + top, workspace->U_EE->j + workspace->U_EE->start[i],
+//                            sizeof(unsigned int) * (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]) );
+//                    memcpy( workspace->U->val + top, workspace->U_EE->val + workspace->U_EE->start[i],
+//                            sizeof(real) * (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]) );
+//                    top += (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]);
+//
+//                    workspace->U->j[top] = system->N_cm - 1;
+//                    workspace->U->val[top] = y[i];
+//                    ++top;
+//                }
+//
+//                workspace->U->start[system->N_cm - 1] = top;
+//
+//                workspace->U->j[top] = system->N_cm - 1;
+//                workspace->U->val[top] = -Dot( x, y, system->N );
+//                ++top;
+//
+//                workspace->U->start[system->N_cm] = top;
+//                break;
+//
+//            //TODO: add Jacobi iter, etc.?
+//            default:
+//                tri_solve( workspace->L_EE, ones, x, workspace->L_EE->n, LOWER );
+//                Transpose_I( workspace->U_EE );
+//                tri_solve( workspace->U_EE, ones, y, workspace->U_EE->n, LOWER );
+//                Transpose_I( workspace->U_EE );
+//
+//                memcpy( workspace->L->start, workspace->L_EE->start, sizeof(unsigned int) * (system->N + 1) );
+//                memcpy( workspace->L->j, workspace->L_EE->j, sizeof(unsigned int) * workspace->L_EE->start[workspace->L_EE->n] );
+//                memcpy( workspace->L->val, workspace->L_EE->val, sizeof(real) * workspace->L_EE->start[workspace->L_EE->n] );
+//
+//                top = workspace->L->start[system->N];
+//                for ( i = 0; i < system->N; ++i )
+//                {
+//                    workspace->L->j[top] = i;
+//                    workspace->L->val[top] = x[i];
+//                    ++top;
+//                }
+//
+//                workspace->L->j[top] = system->N_cm - 1;
+//                workspace->L->val[top] = 1.0;
+//                ++top;
+//
+//                workspace->L->start[system->N_cm] = top;
+//
+//                top = 0;
+//                for ( i = 0; i < system->N; ++i )
+//                {
+//                    workspace->U->start[i] = top;
+//                    memcpy( workspace->U->j + top, workspace->U_EE->j + workspace->U_EE->start[i],
+//                            sizeof(unsigned int) * (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]) );
+//                    memcpy( workspace->U->val + top, workspace->U_EE->val + workspace->U_EE->start[i],
+//                            sizeof(real) * (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]) );
+//                    top += (workspace->U_EE->start[i + 1] - workspace->U_EE->start[i]);
+//
+//                    workspace->U->j[top] = system->N_cm - 1;
+//                    workspace->U->val[top] = y[i];
+//                    ++top;
+//                }
+//
+//                workspace->U->start[system->N_cm - 1] = top;
+//
+//                workspace->U->j[top] = system->N_cm - 1;
+//                workspace->U->val[top] = -Dot( x, y, system->N );
+//                ++top;
+//
+//                workspace->U->start[system->N_cm] = top;
+//                break;
+//        }
+//    }
+//
+//#if defined(DEBUG)
+//    if ( control->cm_solver_pre_comp_type != DIAG_PC )
+//    {
+//        fprintf( stderr, "condest = %f\n", condest(workspace->L) );
+//
+//#if defined(DEBUG_FOCUS)
+//        sprintf( fname, "%s.L%d.out", control->sim_name, data->step );
+//        Print_Sparse_Matrix2( workspace->L, fname, NULL );
+//        sprintf( fname, "%s.U%d.out", control->sim_name, data->step );
+//        Print_Sparse_Matrix2( workspace->U, fname, NULL );
+//
+//        fprintf( stderr, "icholt-" );
+//        sprintf( fname, "%s.L%d.out", control->sim_name, data->step );
+//        Print_Sparse_Matrix2( workspace->L, fname, NULL );
+//        Print_Sparse_Matrix( U );
+//#endif
+//    }
+//#endif
+//}
+
+
+/* Compute preconditioner for EE
+ */
+static void Compute_Preconditioner_EE( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs )
+{
+    real time;
+    sparse_matrix *Hptr;
+
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Hptr = workspace->H_sp;
+    }
+    else
+    {
+        Hptr = workspace->H;
+    }
+
+    time = Get_Time( );
+    if ( control->cm_solver_pre_app_type == TRI_SOLVE_GC_PA )
+    {
+        if ( control->cm_domain_sparsify_enabled == TRUE )
+        {
+            Hptr = setup_graph_coloring( workspace->H_sp );
+        }
+        else
+        {
+            Hptr = setup_graph_coloring( workspace->H );
+        }
+
+        Sort_Matrix_Rows( Hptr );
+    }
+    data->timing.cm_sort_mat_rows += Get_Timing_Info( time );
+
+#if defined(TEST_MAT)
+    Hptr = create_test_mat( );
+#endif
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 1.0;
+    
+    switch ( control->cm_solver_pre_comp_type )
+    {
+        case NONE_PC:
+            break;
+
+        case DIAG_PC:
+            data->timing.cm_solver_pre_comp +=
+                diag_pre_comp( Hptr, workspace->Hdia_inv );
+            break;
+
+        case ICHOLT_PC:
+            data->timing.cm_solver_pre_comp +=
+                ICHOLT( Hptr, workspace->droptol, workspace->L, workspace->U );
+            break;
+
+        case ILU_PAR_PC:
+            data->timing.cm_solver_pre_comp +=
+                ILU_PAR( Hptr, control->cm_solver_pre_comp_sweeps, workspace->L, workspace->U );
+            break;
+
+        case ILUT_PAR_PC:
+            data->timing.cm_solver_pre_comp +=
+                ILUT_PAR( Hptr, workspace->droptol, control->cm_solver_pre_comp_sweeps,
+                        workspace->L, workspace->U );
+            break;
+
+        case ILU_SUPERLU_MT_PC:
+#if defined(HAVE_SUPERLU_MT)
+            data->timing.cm_solver_pre_comp +=
+                SuperLU_Factorize( Hptr, workspace->L, workspace->U );
+#else
+            fprintf( stderr, "SuperLU MT support disabled. Re-compile before enabling. Terminating...\n" );
+            exit( INVALID_INPUT );
+#endif
+            break;
+
+        default:
+            fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
+    }
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 0.0;
+
+#if defined(DEBUG)
+    if ( control->cm_solver_pre_comp_type != NONE_PC && 
+            control->cm_solver_pre_comp_type != DIAG_PC )
+    {
+        fprintf( stderr, "condest = %f\n", condest(workspace->L, workspace->U) );
+
+#if defined(DEBUG_FOCUS)
+        sprintf( fname, "%s.L%d.out", control->sim_name, data->step );
+        Print_Sparse_Matrix2( workspace->L, fname, NULL );
+        sprintf( fname, "%s.U%d.out", control->sim_name, data->step );
+        Print_Sparse_Matrix2( workspace->U, fname, NULL );
+#endif
+    }
+#endif
+}
+
+
+/* Compute preconditioner for ACKS2
+ */
+static void Compute_Preconditioner_ACKS2( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs )
+{
+    real time;
+    sparse_matrix *Hptr;
+
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Hptr = workspace->H_sp;
+    }
+    else
+    {
+        Hptr = workspace->H;
+    }
+
+    time = Get_Time( );
+    if ( control->cm_solver_pre_app_type == TRI_SOLVE_GC_PA )
+    {
+        if ( control->cm_domain_sparsify_enabled == TRUE )
+        {
+            Hptr = setup_graph_coloring( workspace->H_sp );
+        }
+        else
+        {
+            Hptr = setup_graph_coloring( workspace->H );
+        }
+
+        Sort_Matrix_Rows( Hptr );
+    }
+    data->timing.cm_sort_mat_rows += Get_Timing_Info( time );
+
+#if defined(TEST_MAT)
+    Hptr = create_test_mat( );
+#endif
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 1.0;
+    Hptr->val[Hptr->start[system->N_cm] - 1] = 1.0;
+    
+    switch ( control->cm_solver_pre_comp_type )
+    {
+        case NONE_PC:
+            break;
+
+        case DIAG_PC:
+            data->timing.cm_solver_pre_comp +=
+                diag_pre_comp( Hptr, workspace->Hdia_inv );
+            break;
+
+        case ICHOLT_PC:
+            data->timing.cm_solver_pre_comp +=
+                ICHOLT( Hptr, workspace->droptol, workspace->L, workspace->U );
+            break;
+
+        case ILU_PAR_PC:
+            data->timing.cm_solver_pre_comp +=
+                ILU_PAR( Hptr, control->cm_solver_pre_comp_sweeps, workspace->L, workspace->U );
+            break;
+
+        case ILUT_PAR_PC:
+            data->timing.cm_solver_pre_comp +=
+                ILUT_PAR( Hptr, workspace->droptol, control->cm_solver_pre_comp_sweeps,
+                        workspace->L, workspace->U );
+            break;
+
+        case ILU_SUPERLU_MT_PC:
+#if defined(HAVE_SUPERLU_MT)
+            data->timing.cm_solver_pre_comp +=
+                SuperLU_Factorize( Hptr, workspace->L, workspace->U );
+#else
+            fprintf( stderr, "SuperLU MT support disabled. Re-compile before enabling. Terminating...\n" );
+            exit( INVALID_INPUT );
+#endif
+            break;
+
+        default:
+            fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
+    }
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 0.0;
+    Hptr->val[Hptr->start[system->N_cm] - 1] = 0.0;
+
+#if defined(DEBUG)
+    if ( control->cm_solver_pre_comp_type != NONE_PC || 
+            control->cm_solver_pre_comp_type != DIAG_PC )
+    {
+        fprintf( stderr, "condest = %f\n", condest(workspace->L, workspace->U) );
+
+#if defined(DEBUG_FOCUS)
+        sprintf( fname, "%s.L%d.out", control->sim_name, data->step );
+        Print_Sparse_Matrix2( workspace->L, fname, NULL );
+        sprintf( fname, "%s.U%d.out", control->sim_name, data->step );
+        Print_Sparse_Matrix2( workspace->U, fname, NULL );
+#endif
+    }
+#endif
+}
+
+
+/* Setup routines before computing the preconditioner for QEq
+ */
+static void Setup_Preconditioner_QEq( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs )
+{
+    int fillin;
+    real time;
+    sparse_matrix *Hptr;
+
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Hptr = workspace->H_sp;
+    }
+    else
+    {
+        Hptr = workspace->H;
+    }
+
+    /* sort H needed for SpMV's in linear solver, H or H_sp needed for preconditioning */
+    time = Get_Time( );
+    Sort_Matrix_Rows( workspace->H );
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Sort_Matrix_Rows( workspace->H_sp );
+    }
+    data->timing.cm_sort_mat_rows += Get_Timing_Info( time );
+
+#if defined(DEBUG)
+    fprintf( stderr, "H matrix sorted\n" );
+#endif
+
+    switch ( control->cm_solver_pre_comp_type )
+    {
+        case NONE_PC:
+            break;
+
+        case DIAG_PC:
+            if ( workspace->Hdia_inv == NULL )
+            {
+                if ( ( workspace->Hdia_inv = (real *) calloc( Hptr->n, sizeof( real ) ) ) == NULL )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            break;
+
+        case ICHOLT_PC:
+            Calculate_Droptol( Hptr, workspace->droptol, control->cm_solver_pre_comp_droptol );
+
+#if defined(DEBUG_FOCUS)
+            fprintf( stderr, "drop tolerances calculated\n" );
+#endif
+
+            fillin = Estimate_LU_Fill( Hptr, workspace->droptol );
+
+#if defined(DEBUG)
+            fprintf( stderr, "fillin = %d\n", fillin );
+            fprintf( stderr, "allocated memory: L = U = %ldMB\n",
+                     fillin * (sizeof(real) + sizeof(unsigned int)) / (1024 * 1024) );
+#endif
+
+            if ( workspace->L == NULL )
+            {
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, fillin ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, fillin ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILU_PAR_PC:
+            if ( workspace->L == NULL )
+            {
+                /* factors have sparsity pattern as H */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILUT_PAR_PC:
+            Calculate_Droptol( Hptr, workspace->droptol, control->cm_solver_pre_comp_droptol );
+
+#if defined(DEBUG_FOCUS)
+            fprintf( stderr, "drop tolerances calculated\n" );
+#endif
+
+            if ( workspace->L == NULL )
+            {
+                /* TODO: safest storage estimate is ILU(0) (same as lower triangular portion of H), could improve later */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILU_SUPERLU_MT_PC:
+            if ( workspace->L == NULL )
+            {
+                /* factors have sparsity pattern as H */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        default:
+            fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
+    }
+}
+
+
+/* Setup routines before computing the preconditioner for EE
+ */
+static void Setup_Preconditioner_EE( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs )
+{
+    int fillin;
+    real time;
+    sparse_matrix *Hptr;
+
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Hptr = workspace->H_sp;
+    }
+    else
+    {
+        Hptr = workspace->H;
+    }
+
+    /* sorted H needed for SpMV's in linear solver, H or H_sp needed for preconditioning */
+    time = Get_Time( );
+    Sort_Matrix_Rows( workspace->H );
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Sort_Matrix_Rows( workspace->H_sp );
+    }
+    data->timing.cm_sort_mat_rows += Get_Timing_Info( time );
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 1.0;
+
+#if defined(DEBUG)
+    fprintf( stderr, "H matrix sorted\n" );
+#endif
+
+    switch ( control->cm_solver_pre_comp_type )
+    {
+        case NONE_PC:
+            break;
+
+        case DIAG_PC:
+            if ( workspace->Hdia_inv == NULL )
+            {
+                if ( ( workspace->Hdia_inv = (real *) calloc( system->N_cm, sizeof( real ) ) ) == NULL )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            break;
+
+        case ICHOLT_PC:
+            Calculate_Droptol( Hptr, workspace->droptol, control->cm_solver_pre_comp_droptol );
+
+#if defined(DEBUG_FOCUS)
+            fprintf( stderr, "drop tolerances calculated\n" );
+#endif
+
+            fillin = Estimate_LU_Fill( Hptr, workspace->droptol );
+
+#if defined(DEBUG)
+            fprintf( stderr, "fillin = %d\n", fillin );
+            fprintf( stderr, "allocated memory: L = U = %ldMB\n",
+                     fillin * (sizeof(real) + sizeof(unsigned int)) / (1024 * 1024) );
+#endif
+
+            if ( workspace->L == NULL )
+            {
+                if ( Allocate_Matrix( &(workspace->L), system->N_cm, fillin + system->N_cm ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), system->N_cm, fillin + system->N_cm ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILU_PAR_PC:
+            if ( workspace->L == NULL )
+            {
+                /* factors have sparsity pattern as H */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILUT_PAR_PC:
+            Calculate_Droptol( Hptr, workspace->droptol, control->cm_solver_pre_comp_droptol );
+
+#if defined(DEBUG_FOCUS)
+            fprintf( stderr, "drop tolerances calculated\n" );
+#endif
+
+            if ( workspace->L == NULL )
+            {
+                /* TODO: safest storage estimate is ILU(0) (same as lower triangular portion of H), could improve later */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILU_SUPERLU_MT_PC:
+            if ( workspace->L == NULL )
+            {
+                /* factors have sparsity pattern as H */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        default:
+            fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
+    }
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 0.0;
+}
+
+
+/* Setup routines before computing the preconditioner for ACKS2
+ */
+static void Setup_Preconditioner_ACKS2( const reax_system * const system,
+        const control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs )
+{
+    int fillin;
+    real time;
+    sparse_matrix *Hptr;
+
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Hptr = workspace->H_sp;
+    }
+    else
+    {
+        Hptr = workspace->H;
+    }
+
+    /* sort H needed for SpMV's in linear solver, H or H_sp needed for preconditioning */
+    time = Get_Time( );
+    Sort_Matrix_Rows( workspace->H );
+    if ( control->cm_domain_sparsify_enabled == TRUE )
+    {
+        Sort_Matrix_Rows( workspace->H_sp );
+    }
+    data->timing.cm_sort_mat_rows += Get_Timing_Info( time );
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 1.0;
+    Hptr->val[Hptr->start[system->N_cm] - 1] = 1.0;
+
+#if defined(DEBUG)
+    fprintf( stderr, "H matrix sorted\n" );
+#endif
+
+    switch ( control->cm_solver_pre_comp_type )
+    {
+        case NONE_PC:
+            break;
+
+        case DIAG_PC:
+            if ( workspace->Hdia_inv == NULL )
+            {
+                if ( ( workspace->Hdia_inv = (real *) calloc( Hptr->n, sizeof( real ) ) ) == NULL )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            break;
+
+        case ICHOLT_PC:
+            Calculate_Droptol( Hptr, workspace->droptol, control->cm_solver_pre_comp_droptol );
+
+#if defined(DEBUG_FOCUS)
+            fprintf( stderr, "drop tolerances calculated\n" );
+#endif
+
+            fillin = Estimate_LU_Fill( Hptr, workspace->droptol );
+
+#if defined(DEBUG)
+            fprintf( stderr, "fillin = %d\n", fillin );
+            fprintf( stderr, "allocated memory: L = U = %ldMB\n",
+                     fillin * (sizeof(real) + sizeof(unsigned int)) / (1024 * 1024) );
+#endif
+
+            if ( workspace->L == NULL )
+            {
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, fillin ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, fillin ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILU_PAR_PC:
+            if ( workspace->L == NULL )
+            {
+                /* factors have sparsity pattern as H */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILUT_PAR_PC:
+            Calculate_Droptol( Hptr, workspace->droptol, control->cm_solver_pre_comp_droptol );
+
+#if defined(DEBUG_FOCUS)
+            fprintf( stderr, "drop tolerances calculated\n" );
+#endif
+
+            if ( workspace->L == NULL )
+            {
+                /* TODO: safest storage estimate is ILU(0) (same as lower triangular portion of H), could improve later */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        case ILU_SUPERLU_MT_PC:
+            if ( workspace->L == NULL )
+            {
+                /* factors have sparsity pattern as H */
+                if ( Allocate_Matrix( &(workspace->L), Hptr->n, Hptr->m ) == FAILURE ||
+                        Allocate_Matrix( &(workspace->U), Hptr->n, Hptr->m ) == FAILURE )
+                {
+                    fprintf( stderr, "not enough memory for preconditioning matrices. terminating.\n" );
+                    exit( INSUFFICIENT_MEMORY );
+                }
+            }
+            else
+            {
+                //TODO: reallocate
+            }
+            break;
+
+        default:
+            fprintf( stderr, "Unrecognized preconditioner computation method. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
+    }
+
+    Hptr->val[Hptr->start[system->N + 1] - 1] = 0.0;
+    Hptr->val[Hptr->start[system->N_cm] - 1] = 0.0;
+}
+
+
+/* Combine ficticious charges s and t to get atomic charge q for QEq method
+ */
+static void Calculate_Charges_QEq( const reax_system * const system,
+        static_storage * const workspace )
+{
+    int i;
+    real u, s_sum, t_sum;
+
+    s_sum = t_sum = 0.;
+    for ( i = 0; i < system->N_cm; ++i )
+    {
+        s_sum += workspace->s[0][i];
+        t_sum += workspace->t[0][i];
+    }
+
+    u = s_sum / t_sum;
+    for ( i = 0; i < system->N_cm; ++i )
+    {
+        system->atoms[i].q = workspace->s[0][i] - u * workspace->t[0][i];
+
+#if defined(DEBUG_FOCUS)
+        printf("atom %4d: %f\n", i, system->atoms[i].q);
+        printf("  x[0]: %10.5f, x[1]: %10.5f, x[2]:  %10.5f\n",
+                system->atoms[i].x[0], system->atoms[i].x[1], system->atoms[i].x[2]);
+#endif
+    }
+}
+
+
+/* Get atomic charge q for EE method
+ */
+static void Calculate_Charges_EE( const reax_system * const system,
+        static_storage * const workspace )
+{
+    int i;
+
+    for ( i = 0; i < system->N; ++i )
+    {
+        system->atoms[i].q = workspace->s[0][i];
+    }
+}
+
+
+/* Main driver method for QEq kernel
+ *
+ * Rough outline:
+ *  1) init / setup routines for preconditioning of linear solver
+ *  2) compute preconditioner
+ *  3) extrapolate charges
+ *  4) perform 2 linear solves
+ *  5) compute atomic charges based on output of (4)
+ */
+static void QEq( reax_system * const system, control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs, const output_controls * const out_control )
+{
+    int iters;
+
+    if ( control->cm_solver_pre_comp_refactor > 0 &&
+            ((data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) )
+        
+    {
+        Setup_Preconditioner_QEq( system, control, data, workspace, far_nbrs );
+
+        Compute_Preconditioner_QEq( system, control, data, workspace, far_nbrs );
+    }
+
+    Extrapolate_Charges_QEq( system, control, data, workspace );
+
+    switch ( control->cm_solver_type )
+    {
+    case GMRES_S:
+        iters = GMRES( workspace, control, data, workspace->H,
+                workspace->b_s, control->cm_solver_q_err, workspace->s[0],
+                (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE );
+        iters += GMRES( workspace, control, data, workspace->H,
+                workspace->b_t, control->cm_solver_q_err, workspace->t[0], FALSE );
+        break;
+
+    case GMRES_H_S:
+        iters = GMRES_HouseHolder( workspace, control, data, workspace->H,
+                workspace->b_s, control->cm_solver_q_err, workspace->s[0],
+                (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE );
+        iters += GMRES_HouseHolder( workspace, control, data, workspace->H,
+                workspace->b_t, control->cm_solver_q_err, workspace->t[0], 0 );
+        break;
+
+    case CG_S:
+        iters = CG( workspace, control, workspace->H, workspace->b_s, control->cm_solver_q_err,
+                workspace->s[0], (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE ) + 1;
+        iters += CG( workspace, control, workspace->H, workspace->b_t, control->cm_solver_q_err,
+                workspace->t[0], FALSE ) + 1;
+        break;
+
+    case SDM_S:
+        iters = SDM( workspace, control, workspace->H, workspace->b_s, control->cm_solver_q_err,
+                workspace->s[0], (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE ) + 1;
+        iters += SDM( workspace,control,  workspace->H, workspace->b_t, control->cm_solver_q_err,
+                      workspace->t[0], FALSE ) + 1;
+        break;
+
+    default:
+        fprintf( stderr, "Unrecognized QEq solver selection. Terminating...\n" );
+        exit( INVALID_INPUT );
+        break;
+    }
+
+    data->timing.cm_solver_iters += iters;
+
+#if defined(DEBUG_FOCUS)
+    fprintf( stderr, "linsolve-" );
+#endif
+
+    Calculate_Charges_QEq( system, workspace );
+
+#if defined(DEBUG_FOCUS)
+    fprintf( stderr, "%d %.9f %.9f %.9f %.9f %.9f %.9f\n", data->step,
+       workspace->s[0][0], workspace->t[0][0],
+       workspace->s[0][1], workspace->t[0][1],
+       workspace->s[0][2], workspace->t[0][2] );
+    if( data->step == control->nsteps )
+    {
+        Print_Charges( system, control, workspace, data->step );
+    }
+#endif
+}
+
+
+/* Main driver method for EE kernel
+ *
+ * Rough outline:
+ *  1) init / setup routines for preconditioning of linear solver
+ *  2) compute preconditioner
+ *  3) extrapolate charges
+ *  4) perform 1 linear solve
+ *  5) compute atomic charges based on output of (4)
+ */
+static void EE( reax_system * const system, control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs, const output_controls * const out_control )
+{
+    int iters;
+
+    if ( control->cm_solver_pre_comp_refactor > 0 &&
+            ((data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) )
+    {
+        Setup_Preconditioner_EE( system, control, data, workspace, far_nbrs );
+
+        Compute_Preconditioner_EE( system, control, data, workspace, far_nbrs );
+    }
+
+    Extrapolate_Charges_EE( system, control, data, workspace );
+
+    switch ( control->cm_solver_type )
+    {
+    case GMRES_S:
+        iters = GMRES( workspace, control, data, workspace->H,
+                workspace->b_s, control->cm_solver_q_err, workspace->s[0],
+                (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE );
+        break;
+
+    case GMRES_H_S:
+        iters = GMRES_HouseHolder( workspace, control, data,workspace->H,
+                workspace->b_s, control->cm_solver_q_err, workspace->s[0],
+                control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0 );
+        break;
+
+    case CG_S:
+        iters = CG( workspace, control, workspace->H, workspace->b_s, control->cm_solver_q_err,
+                workspace->s[0], (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE ) + 1;
+        break;
+
+    case SDM_S:
+        iters = SDM( workspace, control, workspace->H, workspace->b_s, control->cm_solver_q_err,
+                workspace->s[0], (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE ) + 1;
+        break;
+
+    default:
+        fprintf( stderr, "Unrecognized EE solver selection. Terminating...\n" );
+        exit( INVALID_INPUT );
+        break;
+    }
+
+    data->timing.cm_solver_iters += iters;
+
+#if defined(DEBUG_FOCUS)
+    fprintf( stderr, "linsolve-" );
+#endif
+
+    Calculate_Charges_EE( system, workspace );
+
+    // if( data->step == control->nsteps )
+    //Print_Charges( system, control, workspace, data->step );
+}
+
+
+/* Main driver method for ACKS2 kernel
+ *
+ * Rough outline:
+ *  1) init / setup routines for preconditioning of linear solver
+ *  2) compute preconditioner
+ *  3) extrapolate charges
+ *  4) perform 1 linear solve
+ *  5) compute atomic charges based on output of (4)
+ */
+static void ACKS2( reax_system * const system, control_params * const control,
+        simulation_data * const data, static_storage * const workspace,
+        const list * const far_nbrs, const output_controls * const out_control )
+{
+    int iters;
+
+    if ( control->cm_solver_pre_comp_refactor > 0 &&
+            ((data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) )
+    {
+        Setup_Preconditioner_ACKS2( system, control, data, workspace, far_nbrs );
+
+        Compute_Preconditioner_ACKS2( system, control, data, workspace, far_nbrs );
+    }
+
+//   Print_Linear_System( system, control, workspace, data->step );
+
+    Extrapolate_Charges_EE( system, control, data, workspace );
+
+    switch ( control->cm_solver_type )
+    {
+    case GMRES_S:
+        iters = GMRES( workspace, control, data, workspace->H,
+                workspace->b_s, control->cm_solver_q_err, workspace->s[0],
+                (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE );
+        break;
+
+    case GMRES_H_S:
+        iters = GMRES_HouseHolder( workspace, control, data,workspace->H,
+                workspace->b_s, control->cm_solver_q_err, workspace->s[0],
+                control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0 );
+        break;
+
+    case CG_S:
+        iters = CG( workspace, control, workspace->H, workspace->b_s, control->cm_solver_q_err,
+                workspace->s[0], (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE ) + 1;
+        break;
+
+    case SDM_S:
+        iters = SDM( workspace, control, workspace->H, workspace->b_s, control->cm_solver_q_err,
+                workspace->s[0], (control->cm_solver_pre_comp_refactor > 0 &&
+                 (data->step - data->prev_steps) % control->cm_solver_pre_comp_refactor == 0) ? TRUE : FALSE ) + 1;
+        break;
+
+    default:
+        fprintf( stderr, "Unrecognized ACKS2 solver selection. Terminating...\n" );
+        exit( INVALID_INPUT );
+        break;
+    }
+
+    data->timing.cm_solver_iters += iters;
+
+#if defined(DEBUG_FOCUS)
+    fprintf( stderr, "linsolve-" );
+#endif
+
+    Calculate_Charges_EE( system, workspace );
+}
+
+
+void Compute_Charges( reax_system * const system, control_params * const control,
+                      simulation_data * const data, static_storage * const workspace,
+                      const list * const far_nbrs, const output_controls * const out_control )
+{
+    int i;
+#if defined(DEBUG_FOCUS)
+    char fname[200];
+    FILE * fp;
+
+    if ( data->step >= 100 )
+    {
+        sprintf( fname, "s_%d_%s.out", data->step, control->sim_name );
+        fp = fopen( fname, "w" );
+        Vector_Print( fp, NULL, workspace->s[0], system->N_cm );
+        fclose( fp );
+
+        sprintf( fname, "t_%d_%s.out", data->step, control->sim_name );
+        fp = fopen( fname, "w" );
+        Vector_Print( fp, NULL, workspace->t[0], system->N_cm );
+        fclose( fp );
+    }
+#endif
+
+    switch ( control->charge_method )
+    {
+    case QEQ_CM:
+        QEq( system, control, data, workspace, far_nbrs, out_control );
+        break;
+
+    case EE_CM:
+        EE( system, control, data, workspace, far_nbrs, out_control );
+        break;
+
+    case ACKS2_CM:
+        ACKS2( system, control, data, workspace, far_nbrs, out_control );
+        break;
+
+    default:
+        fprintf( stderr, "Invalid charge method. Terminating...\n" );
+        exit( INVALID_INPUT );
+        break;
+    }
+
+#if defined(DEBUG_FOCUS)
+    if ( data->step >= 100 )
+    {
+        sprintf( fname, "H_%d_%s.out", data->step, control->sim_name );
+        Print_Sparse_Matrix2( workspace->H, fname, NULL );
+//        Print_Sparse_Matrix_Binary( workspace->H, fname );
+
+        sprintf( fname, "b_s_%d_%s.out", data->step, control->sim_name );
+        fp = fopen( fname, "w" );
+        Vector_Print( fp, NULL, workspace->b_s, system->N_cm );
+        fclose( fp );
+
+        sprintf( fname, "b_t_%d_%s.out", data->step, control->sim_name );
+        fp = fopen( fname, "w" );
+        Vector_Print( fp, NULL, workspace->b_t, system->N_cm );
+        fclose( fp );
+    }
+#endif
 }
diff --git a/sPuReMD/src/qeq.h b/sPuReMD/src/charges.h
similarity index 88%
rename from sPuReMD/src/qeq.h
rename to sPuReMD/src/charges.h
index c7186aaee64b35ab67a6fe590de525d99db08c32..50f563c3e94fc5e8a5c324d2d3467572c6ea930d 100644
--- a/sPuReMD/src/qeq.h
+++ b/sPuReMD/src/charges.h
@@ -19,12 +19,12 @@
   <http://www.gnu.org/licenses/>.
   ----------------------------------------------------------------------*/
 
-#ifndef __QEq_H_
-#define __QEq_H_
+#ifndef __CHARGES_H_
+#define __CHARGES_H_
 
 #include "mytypes.h"
 
-void QEq( reax_system* const, control_params* const, simulation_data* const,
+void Compute_Charges( reax_system* const, control_params* const, simulation_data* const,
           static_storage* const, const list* const,
           const output_controls* const );
 
diff --git a/sPuReMD/src/control.c b/sPuReMD/src/control.c
index 41f744969f1615ba621d85db852d998e92719b86..16083739cd050f02ac465d5cefceba0bc0fbdca3 100644
--- a/sPuReMD/src/control.c
+++ b/sPuReMD/src/control.c
@@ -66,20 +66,24 @@ char Read_Control_File( FILE* fp, reax_system *system, control_params* control,
     control->max_far_nbrs = 1000;
     control->bo_cut = 0.01;
     control->thb_cut = 0.001;
-    control->hb_cut = 7.50;
+    control->hb_cut = 0.0;
 
     control->tabulate = 0;
 
-    control->qeq_solver_type = GMRES_S;
-    control->qeq_solver_q_err = 0.000001;
-    control->qeq_domain_sparsify_enabled = FALSE;
-    control->qeq_domain_sparsity = 1.0;
-    control->pre_comp_type = ICHOLT_PC;
-    control->pre_comp_sweeps = 3;
-    control->pre_comp_refactor = 100;
-    control->pre_comp_droptol = 0.01;
-    control->pre_app_type = TRI_SOLVE_PA;
-    control->pre_app_jacobi_iters = 50;
+    control->charge_method = QEQ_CM;
+    control->cm_q_net = 0.0;
+    control->cm_solver_type = GMRES_S;
+    control->cm_solver_max_iters = 100;
+    control->cm_solver_restart = 50;
+    control->cm_solver_q_err = 0.000001;
+    control->cm_domain_sparsify_enabled = FALSE;
+    control->cm_domain_sparsity = 1.0;
+    control->cm_solver_pre_comp_type = ICHOLT_PC;
+    control->cm_solver_pre_comp_sweeps = 3;
+    control->cm_solver_pre_comp_refactor = 100;
+    control->cm_solver_pre_comp_droptol = 0.01;
+    control->cm_solver_pre_app_type = TRI_SOLVE_PA;
+    control->cm_solver_pre_app_jacobi_iters = 50;
 
     control->T_init = 0.;
     control->T_final = 300.;
@@ -101,9 +105,9 @@ char Read_Control_File( FILE* fp, reax_system *system, control_params* control,
     control->remove_CoM_vel = 25;
 
     out_control->debug_level = 0;
-    out_control->energy_update_freq = 10;
+    out_control->energy_update_freq = 0;
 
-    out_control->write_steps = 100;
+    out_control->write_steps = 0;
     out_control->traj_compress = 0;
     out_control->write = fprintf;
     out_control->traj_format = 0;
@@ -240,51 +244,74 @@ char Read_Control_File( FILE* fp, reax_system *system, control_params* control,
             val = atof( tmp[1] );
             control->hb_cut = val;
         }
-        else if ( strcmp(tmp[0], "qeq_solver_type") == 0 )
+        else if ( strcmp(tmp[0], "charge_method") == 0 )
         {
             ival = atoi( tmp[1] );
-            control->qeq_solver_type = ival;
+            control->charge_method = ival;
         }
-        else if ( strcmp(tmp[0], "qeq_solver_q_err") == 0 )
+        else if ( strcmp(tmp[0], "cm_q_net") == 0 )
         {
             val = atof( tmp[1] );
-            control->qeq_solver_q_err = val;
+            control->cm_q_net = val;
         }
-        else if ( strcmp(tmp[0], "qeq_domain_sparsity") == 0 )
+        else if ( strcmp(tmp[0], "cm_solver_type") == 0 )
+        {
+            ival = atoi( tmp[1] );
+            control->cm_solver_type = ival;
+        }
+        else if ( strcmp(tmp[0], "cm_solver_max_iters") == 0 )
+        {
+            ival = atoi( tmp[1] );
+            control->cm_solver_max_iters = ival;
+        }
+        else if ( strcmp(tmp[0], "cm_solver_restart") == 0 )
+        {
+            ival = atoi( tmp[1] );
+            control->cm_solver_restart = ival;
+        }
+        else if ( strcmp(tmp[0], "cm_solver_q_err") == 0 )
         {
             val = atof( tmp[1] );
-            control->qeq_domain_sparsity = val;
-            control->qeq_domain_sparsify_enabled = TRUE;
+            control->cm_solver_q_err = val;
+        }
+        else if ( strcmp(tmp[0], "cm_domain_sparsity") == 0 )
+        {
+            val = atof( tmp[1] );
+            control->cm_domain_sparsity = val;
+            if ( val < 1.0 )
+            {
+                control->cm_domain_sparsify_enabled = TRUE;
+            }
         }
-        else if ( strcmp(tmp[0], "pre_comp_type") == 0 )
+        else if ( strcmp(tmp[0], "cm_solver_pre_comp_type") == 0 )
         {
             ival = atoi( tmp[1] );
-            control->pre_comp_type = ival;
+            control->cm_solver_pre_comp_type = ival;
         }
-        else if ( strcmp(tmp[0], "pre_comp_refactor") == 0 )
+        else if ( strcmp(tmp[0], "cm_solver_pre_comp_refactor") == 0 )
         {
             ival = atoi( tmp[1] );
-            control->pre_comp_refactor = ival;
+            control->cm_solver_pre_comp_refactor = ival;
         }
-        else if ( strcmp(tmp[0], "pre_comp_droptol") == 0 )
+        else if ( strcmp(tmp[0], "cm_solver_pre_comp_droptol") == 0 )
         {
             val = atof( tmp[1] );
-            control->pre_comp_droptol = val;
+            control->cm_solver_pre_comp_droptol = val;
         }
-        else if ( strcmp(tmp[0], "pre_comp_sweeps") == 0 )
+        else if ( strcmp(tmp[0], "cm_solver_pre_comp_sweeps") == 0 )
         {
             ival = atoi( tmp[1] );
-            control->pre_comp_sweeps = ival;
+            control->cm_solver_pre_comp_sweeps = ival;
         }
-        else if ( strcmp(tmp[0], "pre_app_type") == 0 )
+        else if ( strcmp(tmp[0], "cm_solver_pre_app_type") == 0 )
         {
             ival = atoi( tmp[1] );
-            control->pre_app_type = ival;
+            control->cm_solver_pre_app_type = ival;
         }
-        else if ( strcmp(tmp[0], "pre_app_jacobi_iters") == 0 )
+        else if ( strcmp(tmp[0], "cm_solver_pre_app_jacobi_iters") == 0 )
         {
             ival = atoi( tmp[1] );
-            control->pre_app_jacobi_iters = ival;
+            control->cm_solver_pre_app_jacobi_iters = ival;
         }
         else if ( strcmp(tmp[0], "temp_init") == 0 )
         {
@@ -530,7 +557,7 @@ char Read_Control_File( FILE* fp, reax_system *system, control_params* control,
     control->bo_cut = 0.01 * system->reaxprm.gp.l[29];
     control->r_low  = system->reaxprm.gp.l[11];
     control->r_cut  = system->reaxprm.gp.l[12];
-    control->r_sp_cut  = control->r_cut * control->qeq_domain_sparsity;
+    control->r_sp_cut  = control->r_cut * control->cm_domain_sparsity;
     control->vlist_cut += control->r_cut;
 
     system->g.cell_size = control->vlist_cut / 2.;
diff --git a/sPuReMD/src/ffield.c b/sPuReMD/src/ffield.c
index 088e1acbe2aa7588cb6e40b19626038d4257e56e..0fa59d4e07e34113d39f1a0f84b101dd63d8574a 100644
--- a/sPuReMD/src/ffield.c
+++ b/sPuReMD/src/ffield.c
@@ -206,6 +206,7 @@ char Read_Force_Field( FILE* fp, reax_interaction* reax )
         val = atof(tmp[5]);
         reax->sbp[i].b_o_133    = val;
         val = atof(tmp[6]);
+        reax->sbp[i].b_s_acks2  = val;
         val = atof(tmp[7]);
 
         /* line 4  */
diff --git a/sPuReMD/src/forces.c b/sPuReMD/src/forces.c
index 5a0585685b7af523c9b129d6ec57cd3589675edc..2b894c232f00a2b8764ba9bf6211cf5226f54f8d 100644
--- a/sPuReMD/src/forces.c
+++ b/sPuReMD/src/forces.c
@@ -30,10 +30,17 @@
 #include "list.h"
 #include "print_utils.h"
 #include "system_props.h"
-#include "qeq.h"
+#include "charges.h"
 #include "vector.h"
 
 
+typedef enum
+{
+    DIAGONAL = 0,
+    OFF_DIAGONAL = 1,
+} MATRIX_ENTRY_POSITION;
+
+
 void Dummy_Interaction( reax_system *system, control_params *control,
                         simulation_data *data, static_storage *workspace,
                         list **lists, output_controls *out_control )
@@ -126,9 +133,10 @@ void Compute_NonBonded_Forces( reax_system *system, control_params *control,
 #endif
 
     t_start = Get_Time( );
-    QEq( system, control, data, workspace, lists[FAR_NBRS], out_control );
+    Compute_Charges( system, control, data, workspace, lists[FAR_NBRS], out_control );
     t_elapsed = Get_Timing_Info( t_start );
-    data->timing.QEq += t_elapsed;
+    data->timing.cm += t_elapsed;
+
 #if defined(DEBUG_FOCUS)
     fprintf( stderr, "qeq - " );
 #endif
@@ -264,6 +272,374 @@ void Validate_Lists( static_storage *workspace, list **lists, int step, int n,
 }
 
 
+static inline real Init_Charge_Matrix_Entry_Tab( reax_system *system,
+        control_params *control, int i, int j,
+        real r_ij, MATRIX_ENTRY_POSITION pos )
+{
+    int r;
+    real base, dif, val, ret = 0.0;
+    LR_lookup_table *t;
+
+    switch ( control->charge_method )
+    {
+    case QEQ_CM:
+        switch ( pos )
+        {
+            case OFF_DIAGONAL:
+                t = &( LR
+                        [MIN( system->atoms[i].type, system->atoms[j].type )]
+                        [MAX( system->atoms[i].type, system->atoms[j].type )] );
+
+                /* cubic spline interpolation */
+                r = (int)(r_ij * t->inv_dx);
+                if ( r == 0 )  ++r;
+                base = (real)(r + 1) * t->dx;
+                dif = r_ij - base;
+                val = ((t->ele[r].d * dif + t->ele[r].c) * dif + t->ele[r].b) * dif +
+                      t->ele[r].a;
+                val *= EV_to_KCALpMOL / C_ele;
+
+                ret = ((i == j) ? 0.5 : 1.0) * val;
+            break;
+            case DIAGONAL:
+                ret = system->reaxprm.sbp[system->atoms[i].type].eta;
+            break;
+            default:
+                fprintf( stderr, "[Init_forces] Invalid matrix position. Terminating...\n" );
+                exit( INVALID_INPUT );
+            break;
+        }
+        break;
+
+    case EE_CM:
+        //TODO
+        switch ( pos )
+        {
+            case OFF_DIAGONAL:
+            break;
+            case DIAGONAL:
+            break;
+            default:
+                fprintf( stderr, "[Init_forces] Invalid matrix position. Terminating...\n" );
+                exit( INVALID_INPUT );
+            break;
+        }
+        break;
+
+    case ACKS2_CM:
+        //TODO
+        switch ( pos )
+        {
+            case OFF_DIAGONAL:
+            break;
+            case DIAGONAL:
+            break;
+            default:
+                fprintf( stderr, "[Init_forces] Invalid matrix position. Terminating...\n" );
+                exit( INVALID_INPUT );
+            break;
+        }
+        break;
+
+    default:
+        fprintf( stderr, "Invalid charge method. Terminating...\n" );
+        exit( INVALID_INPUT );
+        break;
+    }
+
+    return ret;
+}
+
+
+static inline real Init_Charge_Matrix_Entry( reax_system *system,
+        control_params *control, int i, int j,
+        real r_ij, MATRIX_ENTRY_POSITION pos )
+{
+    real Tap, gamij, dr3gamij_1, dr3gamij_3, ret = 0.0;
+
+    switch ( control->charge_method )
+    {
+    case QEQ_CM:
+        switch ( pos )
+        {
+            case OFF_DIAGONAL:
+                Tap = control->Tap7 * r_ij + control->Tap6;
+                Tap = Tap * r_ij + control->Tap5;
+                Tap = Tap * r_ij + control->Tap4;
+                Tap = Tap * r_ij + control->Tap3;
+                Tap = Tap * r_ij + control->Tap2;
+                Tap = Tap * r_ij + control->Tap1;
+                Tap = Tap * r_ij + control->Tap0;
+
+                /* shielding */
+                dr3gamij_1 = ( r_ij * r_ij * r_ij +
+                        system->reaxprm.tbp[system->atoms[i].type][system->atoms[j].type].gamma );
+                dr3gamij_3 = POW( dr3gamij_1 , 1.0 / 3.0 );
+
+                ret = ((i == j) ? 0.5 : 1.0) * Tap * EV_to_KCALpMOL / dr3gamij_3;
+            break;
+
+            case DIAGONAL:
+                ret = system->reaxprm.sbp[system->atoms[i].type].eta;
+            break;
+
+            default:
+                fprintf( stderr, "[Init_forces] Invalid matrix position. Terminating...\n" );
+                exit( INVALID_INPUT );
+            break;
+        }
+        break;
+
+    case EE_CM:
+        switch ( pos )
+        {
+            case OFF_DIAGONAL:
+                if ( r_ij < control->r_cut && r_ij > 0.001 )
+                {
+                    Tap = control->Tap7 * r_ij + control->Tap6;
+                    Tap = Tap * r_ij + control->Tap5;
+                    Tap = Tap * r_ij + control->Tap4;
+                    Tap = Tap * r_ij + control->Tap3;
+                    Tap = Tap * r_ij + control->Tap2;
+                    Tap = Tap * r_ij + control->Tap1;
+                    Tap = Tap * r_ij + control->Tap0;
+
+                    gamij = SQRT( system->reaxprm.sbp[system->atoms[i].type].gamma
+                            * system->reaxprm.sbp[system->atoms[j].type].gamma );
+                    /* shielding */
+                    dr3gamij_1 = POW( r_ij, 3.0 ) + 1.0 / POW( gamij, 3.0 );
+                    dr3gamij_3 = POW( dr3gamij_1 , 1.0 / 3.0 );
+
+                    ret = Tap * EV_to_KCALpMOL / dr3gamij_3;
+                }
+            break;
+
+            case DIAGONAL:
+                ret = system->reaxprm.sbp[system->atoms[i].type].eta;
+            break;
+
+            default:
+                fprintf( stderr, "[Init_forces] Invalid matrix position. Terminating...\n" );
+                exit( INVALID_INPUT );
+            break;
+        }
+        break;
+
+    case ACKS2_CM:
+        switch ( pos )
+        {
+            case OFF_DIAGONAL:
+                if ( r_ij < control->r_cut && r_ij > 0.001 )
+                {
+                    Tap = control->Tap7 * r_ij + control->Tap6;
+                    Tap = Tap * r_ij + control->Tap5;
+                    Tap = Tap * r_ij + control->Tap4;
+                    Tap = Tap * r_ij + control->Tap3;
+                    Tap = Tap * r_ij + control->Tap2;
+                    Tap = Tap * r_ij + control->Tap1;
+                    Tap = Tap * r_ij + control->Tap0;
+
+                    gamij = SQRT( system->reaxprm.sbp[system->atoms[i].type].gamma
+                            * system->reaxprm.sbp[system->atoms[j].type].gamma );
+                    /* shielding */
+                    dr3gamij_1 = POW( r_ij, 3.0 ) + 1.0 / POW( gamij, 3.0 );
+                    dr3gamij_3 = POW( dr3gamij_1 , 1.0 / 3.0 );
+
+                    ret = Tap * EV_to_KCALpMOL / dr3gamij_3;
+                }
+            break;
+
+            case DIAGONAL:
+                ret = system->reaxprm.sbp[system->atoms[i].type].eta;
+            break;
+
+            default:
+                fprintf( stderr, "[Init_forces] Invalid matrix position. Terminating...\n" );
+                exit( INVALID_INPUT );
+            break;
+        }
+        break;
+
+    default:
+        fprintf( stderr, "Invalid charge method. Terminating...\n" );
+        exit( INVALID_INPUT );
+        break;
+    }
+
+    return ret;
+}
+
+
+static void Init_Charge_Matrix_Remaining_Entries( reax_system *system,
+        control_params *control, list *far_nbrs,
+        sparse_matrix * H, sparse_matrix * H_sp,
+        int * Htop, int * H_sp_top )
+{
+    int i, j, pj;
+    real d, xcut, bond_softness, * X_diag;
+
+    switch ( control->charge_method )
+    {
+        case QEQ_CM:
+            break;
+
+        case EE_CM:
+            H->start[system->N_cm - 1] = *Htop;
+            H_sp->start[system->N_cm - 1] = *H_sp_top;
+
+            for ( i = 0; i < system->N_cm - 1; ++i )
+            {
+                H->j[*Htop] = i;
+                H->val[*Htop] = 1.0;
+                *Htop = *Htop + 1;
+
+                H_sp->j[*H_sp_top] = i;
+                H_sp->val[*H_sp_top] = 1.0;
+                *H_sp_top = *H_sp_top + 1;
+            }
+
+            H->j[*Htop] = system->N_cm - 1;
+            H->val[*Htop] = 0.0;
+            *Htop = *Htop + 1;
+
+            H_sp->j[*H_sp_top] = system->N_cm - 1;
+            H_sp->val[*H_sp_top] = 0.0;
+            *H_sp_top = *H_sp_top + 1;
+            break;
+
+        case ACKS2_CM:
+            if ( (X_diag = (real*) calloc(system->N, sizeof(real))) == NULL )
+            {
+                fprintf( stderr, "not enough memory for charge matrix. terminating.\n" );
+                exit( INSUFFICIENT_MEMORY );
+            }
+
+            H->start[system->N] = *Htop;
+            H_sp->start[system->N] = *H_sp_top;
+
+            for ( i = 0; i < system->N; ++i )
+            {
+                H->j[*Htop] = i;
+                H->val[*Htop] = 1.0;
+                *Htop = *Htop + 1;
+
+                H_sp->j[*H_sp_top] = i;
+                H_sp->val[*H_sp_top] = 1.0;
+                *H_sp_top = *H_sp_top + 1;
+            }
+
+            H->j[*Htop] = system->N;
+            H->val[*Htop] = 0.0;
+            *Htop = *Htop + 1;
+
+            H_sp->j[*H_sp_top] = system->N;
+            H_sp->val[*H_sp_top] = 0.0;
+            *H_sp_top = *H_sp_top + 1;
+
+            for ( i = 0; i < system->N; ++i )
+            {
+                H->start[system->N + i + 1] = *Htop;
+                H_sp->start[system->N + i + 1] = *H_sp_top;
+
+                H->j[*Htop] = i;
+                H->val[*Htop] = 1.0;
+                *Htop = *Htop + 1;
+
+                H_sp->j[*H_sp_top] = i;
+                H_sp->val[*H_sp_top] = 1.0;
+                *H_sp_top = *H_sp_top + 1;
+
+                for ( pj = Start_Index(i, far_nbrs); pj < End_Index(i, far_nbrs); ++pj )
+                {
+                    if ( far_nbrs->select.far_nbr_list[pj].d <= control->r_cut )
+                    {
+                        j = far_nbrs->select.far_nbr_list[pj].nbr;
+
+                        xcut = ( system->reaxprm.sbp[ system->atoms[i].type ].b_s_acks2
+                                + system->reaxprm.sbp[ system->atoms[j].type ].b_s_acks2 )
+                            / 2.0;
+
+                        if ( far_nbrs->select.far_nbr_list[pj].d < xcut &&
+                                far_nbrs->select.far_nbr_list[pj].d > 0.001 )
+                        {
+                            d = far_nbrs->select.far_nbr_list[pj].d / xcut;
+                            bond_softness = system->reaxprm.gp.l[34] * POW( d, 3.0 ) * POW( 1.0 - d, 6.0 );
+
+                            H->j[*Htop] = system->N + j + 1;
+                            H->val[*Htop] = MAX( 0.0, bond_softness );
+                            *Htop = *Htop + 1;
+
+                            H_sp->j[*H_sp_top] = system->N + j + 1;
+                            H_sp->val[*H_sp_top] = MAX( 0.0, bond_softness );
+                            *H_sp_top = *H_sp_top + 1;
+
+                            X_diag[i] -= bond_softness;
+                            X_diag[j] -= bond_softness;
+                        }
+                    }
+                }
+
+                H->j[*Htop] = system->N + i + 1;
+                H->val[*Htop] = 0.0;
+                *Htop = *Htop + 1;
+
+                H_sp->j[*H_sp_top] = system->N + i + 1;
+                H_sp->val[*H_sp_top] = 0.0;
+                *H_sp_top = *H_sp_top + 1;
+            }
+
+            H->start[system->N_cm - 1] = *Htop;
+            H_sp->start[system->N_cm - 1] = *H_sp_top;
+
+            for ( i = system->N + 1; i < system->N_cm - 1; ++i )
+            {
+                for ( pj = H->start[i]; pj < H->start[i + 1]; ++pj )
+                {
+                    if ( H->j[pj] == i )
+                    {
+                        H->val[pj] = X_diag[i - system->N - 1];
+                        break;
+                    }
+                }
+
+                for ( pj = H_sp->start[i]; pj < H_sp->start[i + 1]; ++pj )
+                {
+                    if ( H_sp->j[pj] == i )
+                    {
+                        H_sp->val[pj] = X_diag[i - system->N - 1];
+                        break;
+                    }
+                }
+            }
+
+            for ( i = system->N + 1; i < system->N_cm - 1; ++i )
+            {
+                H->j[*Htop] = i;
+                H->val[*Htop] = 1.0;
+                *Htop = *Htop + 1;
+
+                H_sp->j[*H_sp_top] = i;
+                H_sp->val[*H_sp_top] = 1.0;
+                *H_sp_top = *H_sp_top + 1;
+            }
+
+            H->j[*Htop] = system->N_cm - 1;
+            H->val[*Htop] = 0.0;
+            *Htop = *Htop + 1;
+
+            H_sp->j[*H_sp_top] = system->N_cm - 1;
+            H_sp->val[*H_sp_top] = 0.0;
+            *H_sp_top = *H_sp_top + 1;
+
+            free( X_diag );
+            break;
+
+        default:
+            break;
+    }
+}
+
+
 void Init_Forces( reax_system *system, control_params *control,
                   simulation_data *data, static_storage *workspace,
                   list **lists, output_controls *out_control )
@@ -274,9 +650,7 @@ void Init_Forces( reax_system *system, control_params *control,
     int Htop, H_sp_top, btop_i, btop_j, num_bonds, num_hbonds;
     int ihb, jhb, ihb_top, jhb_top;
     int flag, flag_sp;
-    real r_ij, r2, self_coef;
-    real dr3gamij_1, dr3gamij_3, Tap;
-    //real val, dif, base;
+    real r_ij, r2;
     real C12, C34, C56;
     real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2;
     real BO, BO_s, BO_pi, BO_pi2;
@@ -286,7 +660,6 @@ void Init_Forces( reax_system *system, control_params *control,
     single_body_parameters *sbp_i, *sbp_j;
     two_body_parameters *twbp;
     far_neighbor_data *nbr_pj;
-    //LR_lookup_table *t;
     reax_atom *atom_i, *atom_j;
     bond_data *ibond, *jbond;
     bond_order_data *bo_ij, *bo_ji;
@@ -316,8 +689,11 @@ void Init_Forces( reax_system *system, control_params *control,
         btop_i = End_Index( i, bonds );
         sbp_i = &(system->reaxprm.sbp[type_i]);
         ihb = ihb_top = -1;
+
         if ( control->hb_cut > 0 && (ihb = sbp_i->p_hbond) == 1 )
+        {
             ihb_top = End_Index( workspace->hbond_index[i], hbonds );
+        }
 
         for ( pj = start_i; pj < end_i; ++pj )
         {
@@ -360,22 +736,10 @@ void Init_Forces( reax_system *system, control_params *control,
                 r_ij = nbr_pj->d;
                 sbp_j = &(system->reaxprm.sbp[type_j]);
                 twbp = &(system->reaxprm.tbp[type_i][type_j]);
-                self_coef = (i == j) ? 0.5 : 1.0;
-
-                /* H matrix entry */
-                Tap = control->Tap7 * r_ij + control->Tap6;
-                Tap = Tap * r_ij + control->Tap5;
-                Tap = Tap * r_ij + control->Tap4;
-                Tap = Tap * r_ij + control->Tap3;
-                Tap = Tap * r_ij + control->Tap2;
-                Tap = Tap * r_ij + control->Tap1;
-                Tap = Tap * r_ij + control->Tap0;
-
-                dr3gamij_1 = ( r_ij * r_ij * r_ij + twbp->gamma );
-                dr3gamij_3 = POW( dr3gamij_1 , 0.33333333333333 );
 
                 H->j[Htop] = j;
-                H->val[Htop] = self_coef * Tap * EV_to_KCALpMOL / dr3gamij_3;
+                H->val[Htop] = Init_Charge_Matrix_Entry( system, control, i, j, 
+                        r_ij, OFF_DIAGONAL );
                 ++Htop;
 
                 /* H_sp matrix entry */
@@ -542,27 +906,33 @@ void Init_Forces( reax_system *system, control_params *control,
 
         /* diagonal entry */
         H->j[Htop] = i;
-        H->val[Htop] = system->reaxprm.sbp[type_i].eta;
+        H->val[Htop] = Init_Charge_Matrix_Entry( system, control, i, j,
+                r_ij, DIAGONAL );
         ++Htop;
 
-        /* diagonal entry */
         H_sp->j[H_sp_top] = i;
         H_sp->val[H_sp_top] = H->val[Htop - 1];
         ++H_sp_top;
 
         Set_End_Index( i, btop_i, bonds );
         if ( ihb == 1 )
+        {
             Set_End_Index( workspace->hbond_index[i], ihb_top, hbonds );
+        }
         //fprintf( stderr, "%d bonds start: %d, end: %d\n",
         //     i, Start_Index( i, bonds ), End_Index( i, bonds ) );
     }
 
+    Init_Charge_Matrix_Remaining_Entries( system, control, far_nbrs,
+            H, H_sp, &Htop, &H_sp_top );
+
+    // mark the end of j list
+    H->start[system->N_cm] = Htop;
+    H_sp->start[system->N_cm] = H_sp_top;
+
 //    printf("Htop = %d\n", Htop);
 //    printf("H_sp_top = %d\n", H_sp_top);
 
-    // mark the end of j list
-    H->start[i] = Htop;
-    H_sp->start[i] = H_sp_top;
     /* validate lists - decide if reallocation is required! */
     Validate_Lists( workspace, lists,
                     data->step, system->N, H->m, Htop, num_bonds, num_hbonds );
@@ -583,11 +953,9 @@ void Init_Forces_Tab( reax_system *system, control_params *control,
     int start_i, end_i;
     int type_i, type_j;
     int Htop, H_sp_top, btop_i, btop_j, num_bonds, num_hbonds;
-    int tmin, tmax, r;
     int ihb, jhb, ihb_top, jhb_top;
     int flag, flag_sp;
-    real r_ij, r2, self_coef;
-    real val, dif, base;
+    real r_ij, r2;
     real C12, C34, C56;
     real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2;
     real BO, BO_s, BO_pi, BO_pi2;
@@ -597,7 +965,6 @@ void Init_Forces_Tab( reax_system *system, control_params *control,
     single_body_parameters *sbp_i, *sbp_j;
     two_body_parameters *twbp;
     far_neighbor_data *nbr_pj;
-    LR_lookup_table *t;
     reax_atom *atom_i, *atom_j;
     bond_data *ibond, *jbond;
     bond_order_data *bo_ij, *bo_ji;
@@ -671,22 +1038,10 @@ void Init_Forces_Tab( reax_system *system, control_params *control,
                 r_ij = nbr_pj->d;
                 sbp_j = &(system->reaxprm.sbp[type_j]);
                 twbp = &(system->reaxprm.tbp[type_i][type_j]);
-                self_coef = (i == j) ? 0.5 : 1.0;
-                tmin  = MIN( type_i, type_j );
-                tmax  = MAX( type_i, type_j );
-                t = &( LR[tmin][tmax] );
-
-                /* cubic spline interpolation */
-                r = (int)(r_ij * t->inv_dx);
-                if ( r == 0 )  ++r;
-                base = (real)(r + 1) * t->dx;
-                dif = r_ij - base;
-                val = ((t->ele[r].d * dif + t->ele[r].c) * dif + t->ele[r].b) * dif +
-                      t->ele[r].a;
-                val *= EV_to_KCALpMOL / C_ele;
 
                 H->j[Htop] = j;
-                H->val[Htop] = self_coef * val;
+                H->val[Htop] = Init_Charge_Matrix_Entry_Tab( system, control, i, j, 
+                        r_ij, OFF_DIAGONAL );
                 ++Htop;
 
                 /* H_sp matrix entry */
@@ -825,10 +1180,10 @@ void Init_Forces_Tab( reax_system *system, control_params *control,
 
         /* diagonal entry */
         H->j[Htop] = i;
-        H->val[Htop] = system->reaxprm.sbp[type_i].eta;
+        H->val[Htop] = Init_Charge_Matrix_Entry_Tab( system, control, i, j,
+                r_ij, DIAGONAL );
         ++Htop;
 
-        /* diagonal entry */
         H_sp->j[H_sp_top] = i;
         H_sp->val[H_sp_top] = H->val[Htop - 1];
         ++H_sp_top;
@@ -850,14 +1205,13 @@ void Init_Forces_Tab( reax_system *system, control_params *control,
              data->step, Htop, num_bonds, num_hbonds );
     //Print_Bonds( system, bonds, "sbonds.out" );
     //Print_Bond_List2( system, bonds, "sbonds.out" );
-    //Print_Sparse_Matrix2( H, "H.out" );
+    //Print_Sparse_Matrix2( H, "H.out", NULL );
 #endif
 }
 
 
 void Estimate_Storage_Sizes( reax_system *system, control_params *control,
-                             list **lists, int *Htop, int *hb_top,
-                             int *bond_top, int *num_3body )
+        list **lists, int *Htop, int *hb_top, int *bond_top, int *num_3body )
 {
     int i, j, pj;
     int start_i, end_i;
@@ -979,6 +1333,7 @@ void Compute_Forces( reax_system *system, control_params *control,
     }
     t_elapsed = Get_Timing_Info( t_start );
     data->timing.init_forces += t_elapsed;
+
 #if defined(DEBUG_FOCUS)
     fprintf( stderr, "init_forces - ");
 #endif
diff --git a/sPuReMD/src/geo_tools.c b/sPuReMD/src/geo_tools.c
index 01f404b4f6d51e73722b9f450f9ca8873dc3c9c9..f996af5e3dc3d3ff770afa8cbc6fd4530d0b46cb 100644
--- a/sPuReMD/src/geo_tools.c
+++ b/sPuReMD/src/geo_tools.c
@@ -381,9 +381,9 @@ char Read_PDB( char* pdb_file, reax_system* system, control_params *control,
             //       system->my_atoms[top].q, occupancy, temp_factor,
             //       seg_id, element );
 
-            //fprintf( stderr, "atom( %8.3f %8.3f %8.3f ) --> p%d\n",
-            // system->my_atoms[top].x[0], system->my_atoms[top].x[1],
-            // system->my_atoms[top].x[2], system->my_rank );
+//            fprintf( stderr, "atom( %8.3f %8.3f %8.3f )\n",
+//                    atom->x[0], atom->x[1],
+//                    atom->x[2] );
 
             c++;
         }
@@ -503,7 +503,11 @@ char Write_PDB( reax_system* system, list* bonds, simulation_data *data,
                  "ATOM  ", workspace->orig_id[i], p_atom->name, ' ', "REX", ' ', 1, ' ',
                  p_atom->x[0], p_atom->x[1], p_atom->x[2],
                  1.0, 0.0, "0", name, "  " );
+
+#if defined(DEBUG)
         fprintf( stderr, "PDB NAME <%s>\n", p_atom->name );
+#endif
+
         strncpy( buffer + i * PDB_ATOM_FORMAT_O_LENGTH, line,
                  PDB_ATOM_FORMAT_O_LENGTH );
     }
diff --git a/sPuReMD/src/grid.c b/sPuReMD/src/grid.c
index c45c1a2214d7589b3e4c1a647ebde1b9d3c7e56d..c422a48ae746f336cb0c3398c3990678d93ec35e 100644
--- a/sPuReMD/src/grid.c
+++ b/sPuReMD/src/grid.c
@@ -494,13 +494,12 @@ static inline void reax_atom_Copy( reax_atom *dest, reax_atom *src )
 
 
 void Copy_Storage( reax_system *system, static_storage *workspace,
-                   int top, int old_id, int old_type,
-                   int *num_H, real **v, real **s, real **t,
-                   int *orig_id, rvec *f_old )
+        control_params *control, int top, int old_id, int old_type, int *num_H,
+        real **v, real **s, real **t, int *orig_id, rvec *f_old )
 {
     int i;
 
-    for ( i = 0; i < RESTART + 1; ++i )
+    for ( i = 0; i < control->cm_solver_restart + 1; ++i )
     {
         v[i][top] = workspace->v[i][old_id];
     }
@@ -529,11 +528,11 @@ void Copy_Storage( reax_system *system, static_storage *workspace,
 }
 
 
-void Free_Storage( static_storage *workspace )
+void Free_Storage( static_storage *workspace, control_params * control )
 {
     int i;
 
-    for ( i = 0; i < RESTART + 1; ++i )
+    for ( i = 0; i < control->cm_solver_restart + 1; ++i )
     {
         free( workspace->v[i] );
     }
@@ -566,7 +565,8 @@ void Assign_New_Storage( static_storage *workspace,
 }
 
 
-void Cluster_Atoms( reax_system *system, static_storage *workspace )
+void Cluster_Atoms( reax_system *system, static_storage *workspace,
+        control_params *control )
 {
     int         i, j, k, l, top, old_id, num_H;
     reax_atom  *old_atom;
@@ -591,8 +591,8 @@ void Cluster_Atoms( reax_system *system, static_storage *workspace )
         t[i] = (real *) calloc( system->N, sizeof( real ) );
     }
 
-    v = (real**) calloc( RESTART + 1, sizeof( real* ) );
-    for ( i = 0; i < RESTART + 1; ++i )
+    v = (real**) calloc( control->cm_solver_restart + 1, sizeof( real* ) );
+    for ( i = 0; i < control->cm_solver_restart + 1; ++i )
     {
         v[i] = (real *) calloc( system->N, sizeof( real ) );
     }
@@ -614,8 +614,8 @@ void Cluster_Atoms( reax_system *system, static_storage *workspace )
                     // fprintf( stderr, "%d <-- %d\n", top, old_id );
 
                     reax_atom_Copy( &(new_atoms[top]), old_atom );
-                    Copy_Storage( system, workspace, top, old_id, old_atom->type,
-                                  &num_H, v, s, t, orig_id, f_old );
+                    Copy_Storage( system, workspace, control, top, old_id, old_atom->type,
+                            &num_H, v, s, t, orig_id, f_old );
                     ++top;
                 }
 
@@ -626,7 +626,7 @@ void Cluster_Atoms( reax_system *system, static_storage *workspace )
 
 
     free( system->atoms );
-    Free_Storage( workspace );
+    Free_Storage( workspace, control );
 
     system->atoms = new_atoms;
     Assign_New_Storage( workspace, v, s, t, orig_id, f_old );
diff --git a/sPuReMD/src/grid.h b/sPuReMD/src/grid.h
index 41d7b57edb2ba271bd41f71c6a77d5f179370910..cab825018606dd56e9f2b057c89a7d43287ed1f7 100644
--- a/sPuReMD/src/grid.h
+++ b/sPuReMD/src/grid.h
@@ -30,7 +30,7 @@ void Update_Grid( reax_system* );
 
 int  Shift( int, int, int, grid* );
 
-void Cluster_Atoms( reax_system*, static_storage* );
+void Cluster_Atoms( reax_system *, static_storage *, control_params * );
 
 void Bin_Atoms( reax_system*, static_storage* );
 
diff --git a/sPuReMD/src/init_md.c b/sPuReMD/src/init_md.c
index af3e234b65c8cd763399646ba014a3bfcf0113f9..3cbf575fc3215c45e6c4bde578036e0f243abb20 100644
--- a/sPuReMD/src/init_md.c
+++ b/sPuReMD/src/init_md.c
@@ -209,15 +209,15 @@ void Init_Simulation_Data( reax_system *system, control_params *control,
     data->timing.init_forces = 0;
     data->timing.bonded = 0;
     data->timing.nonb = 0;
-    data->timing.QEq = ZERO;
-    data->timing.QEq_sort_mat_rows = ZERO;
-    data->timing.pre_comp = ZERO;
-    data->timing.pre_app = ZERO;
-    data->timing.solver_iters = 0;
-    data->timing.solver_spmv = ZERO;
-    data->timing.solver_vector_ops = ZERO;
-    data->timing.solver_orthog = ZERO;
-    data->timing.solver_tri_solve = ZERO;
+    data->timing.cm = ZERO;
+    data->timing.cm_sort_mat_rows = ZERO;
+    data->timing.cm_solver_pre_comp = ZERO;
+    data->timing.cm_solver_pre_app = ZERO;
+    data->timing.cm_solver_iters = 0;
+    data->timing.cm_solver_spmv = ZERO;
+    data->timing.cm_solver_vector_ops = ZERO;
+    data->timing.cm_solver_orthog = ZERO;
+    data->timing.cm_solver_tri_solve = ZERO;
 }
 
 
@@ -231,17 +231,20 @@ void Init_Taper( control_params *control )
     swa = control->r_low;
     swb = control->r_cut;
 
-    if ( fabs( swa ) > 0.01 )
+    if ( FABS( swa ) > 0.01 )
+    {
         fprintf( stderr, "Warning: non-zero value for lower Taper-radius cutoff\n" );
+    }
 
-    if ( swb < 0 )
+    if ( swb < 0.0 )
     {
         fprintf( stderr, "Negative value for upper Taper-radius cutoff\n" );
         exit( INVALID_INPUT );
     }
-    else if ( swb < 5 )
-        fprintf( stderr, "Warning: low value for upper Taper-radius cutoff:%f\n",
-                 swb );
+    else if ( swb < 5.0 )
+    {
+        fprintf( stderr, "Warning: low value for upper Taper-radius cutoff:%f\n", swb );
+    }
 
     d1 = swb - swa;
     d7 = POW( d1, 7.0 );
@@ -258,12 +261,12 @@ void Init_Taper( control_params *control )
     control->Tap2 = -210.0 * (swa3 * swb2 + swa2 * swb3) / d7;
     control->Tap1 = 140.0 * swa3 * swb3 / d7;
     control->Tap0 = (-35.0 * swa3 * swb2 * swb2 + 21.0 * swa2 * swb3 * swb2 +
-                     7.0 * swa * swb3 * swb3 + swb3 * swb3 * swb ) / d7;
+            7.0 * swa * swb3 * swb3 + swb3 * swb3 * swb ) / d7;
 }
 
 
 void Init_Workspace( reax_system *system, control_params *control,
-                     static_storage *workspace )
+        static_storage *workspace )
 {
     int i;
 
@@ -289,71 +292,158 @@ void Init_Workspace( reax_system *system, control_params *control,
     workspace->CdDelta          = (real *) malloc( system->N * sizeof( real ) );
     workspace->vlpex        = (real *) malloc( system->N * sizeof( real ) );
 
-    /* QEq storage */
-    workspace->H        = NULL;
-    workspace->H_sp     = NULL;
-    workspace->L        = NULL;
-    workspace->U        = NULL;
+    /* charge method storage */
+    switch ( control->charge_method )
+    {
+        case QEQ_CM:
+            system->N_cm = system->N;
+            break;
+        case EE_CM:
+            system->N_cm = system->N + 1;
+            break;
+        case ACKS2_CM:
+            system->N_cm = 2 * system->N + 2;
+            break;
+        default:
+            fprintf( stderr, "Unknown charge method type. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
+    }
+
+    workspace->H = NULL;
+    workspace->H_sp = NULL;
+    workspace->L = NULL;
+    workspace->U = NULL;
     workspace->Hdia_inv = NULL;
-    workspace->droptol  = (real *) calloc( system->N, sizeof( real ) );
-    workspace->w        = (real *) calloc( system->N, sizeof( real ) );
-    workspace->b        = (real *) calloc( system->N * 2, sizeof( real ) );
-    workspace->b_s      = (real *) calloc( system->N, sizeof( real ) );
-    workspace->b_t      = (real *) calloc( system->N, sizeof( real ) );
-    workspace->b_prc    = (real *) calloc( system->N * 2, sizeof( real ) );
-    workspace->b_prm    = (real *) calloc( system->N * 2, sizeof( real ) );
-    workspace->s_t      = (real *) calloc( system->N * 2, sizeof( real ) );
+    if ( control->cm_solver_pre_comp_type == ICHOLT_PC ||
+            control->cm_solver_pre_comp_type == ILUT_PAR_PC )
+    {
+        workspace->droptol  = (real *) calloc( system->N_cm, sizeof( real ) );
+    }
+    //TODO: check if unused
+    //workspace->w        = (real *) calloc( cm_lin_sys_size, sizeof( real ) );
+    //TODO: check if unused
+    workspace->b        = (real *) calloc( system->N_cm * 2, sizeof( real ) );
+    workspace->b_s      = (real *) calloc( system->N_cm, sizeof( real ) );
+    workspace->b_t      = (real *) calloc( system->N_cm, sizeof( real ) );
+    workspace->b_prc    = (real *) calloc( system->N_cm * 2, sizeof( real ) );
+    workspace->b_prm    = (real *) calloc( system->N_cm * 2, sizeof( real ) );
+    //TODO: check if unused
+    //workspace->s_t      = (real *) calloc( cm_lin_sys_size * 2, sizeof( real ) );
     workspace->s        = (real**) calloc( 5, sizeof( real* ) );
     workspace->t        = (real**) calloc( 5, sizeof( real* ) );
     for ( i = 0; i < 5; ++i )
     {
-        workspace->s[i] = (real *) calloc( system->N, sizeof( real ) );
-        workspace->t[i] = (real *) calloc( system->N, sizeof( real ) );
+        workspace->s[i] = (real *) calloc( system->N_cm, sizeof( real ) );
+        workspace->t[i] = (real *) calloc( system->N_cm, sizeof( real ) );
     }
-    // workspace->s_old    = (real *) calloc( system->N, sizeof( real ) );
-    // workspace->t_old    = (real *) calloc( system->N, sizeof( real ) );
-    // workspace->s_oldest = (real *) calloc( system->N, sizeof( real ) );
-    // workspace->t_oldest = (real *) calloc( system->N, sizeof( real ) );
 
-    for ( i = 0; i < system->N; ++i )
+    switch ( control->charge_method )
     {
-        workspace->b_s[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
-        workspace->b_t[i] = -1.0;
-
-        workspace->b[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
-        workspace->b[i + system->N] = -1.0;
+        case QEQ_CM:
+            for ( i = 0; i < system->N; ++i )
+            {
+                workspace->b_s[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
+                workspace->b_t[i] = -1.0;
+
+                //TODO: check if unused (redundant)
+                workspace->b[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
+                workspace->b[i + system->N] = -1.0;
+            }
+            break;
+
+        case EE_CM:
+            for ( i = 0; i < system->N; ++i )
+            {
+                workspace->b_s[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
+
+                //TODO: check if unused (redundant)
+                workspace->b[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
+            }
+
+            workspace->b_s[system->N] = control->cm_q_net;
+            workspace->b[system->N] = control->cm_q_net;
+            break;
+
+        case ACKS2_CM:
+            for ( i = 0; i < system->N; ++i )
+            {
+                workspace->b_s[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
+
+                //TODO: check if unused (redundant)
+                workspace->b[i] = -system->reaxprm.sbp[ system->atoms[i].type ].chi;
+            }
+
+            workspace->b_s[system->N] = control->cm_q_net;
+            workspace->b[system->N] = control->cm_q_net;
+
+            for ( i = system->N + 1; i < system->N_cm; ++i )
+            {
+                workspace->b_s[i] = 0.0;
+
+                //TODO: check if unused (redundant)
+                workspace->b[i] = 0.0;
+            }
+            break;
+
+        default:
+            fprintf( stderr, "Unknown charge method type. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
     }
 
-    /* GMRES storage */
-    workspace->y  = (real *)  calloc( RESTART + 1, sizeof( real ) );
-    workspace->z  = (real *)  calloc( RESTART + 1, sizeof( real ) );
-    workspace->g  = (real *)  calloc( RESTART + 1, sizeof( real ) );
-    workspace->h  = (real **) calloc( RESTART + 1, sizeof( real*) );
-    workspace->hs = (real *)  calloc( RESTART + 1, sizeof( real ) );
-    workspace->hc = (real *)  calloc( RESTART + 1, sizeof( real ) );
-    workspace->rn = (real **) calloc( RESTART + 1, sizeof( real*) );
-    workspace->v  = (real **) calloc( RESTART + 1, sizeof( real*) );
-
-    for ( i = 0; i < RESTART + 1; ++i )
+    switch ( control->cm_solver_type )
     {
-        workspace->h[i]  = (real *) calloc( RESTART + 1, sizeof( real ) );
-        workspace->rn[i] = (real *) calloc( system->N * 2, sizeof( real ) );
-        workspace->v[i]  = (real *) calloc( system->N, sizeof( real ) );
+        /* GMRES storage */
+        case GMRES_S:
+        case GMRES_H_S:
+            workspace->y  = (real *)  calloc( control->cm_solver_restart + 1, sizeof( real ) );
+            workspace->z  = (real *)  calloc( control->cm_solver_restart + 1, sizeof( real ) );
+            workspace->g  = (real *)  calloc( control->cm_solver_restart + 1, sizeof( real ) );
+            workspace->h  = (real **) calloc( control->cm_solver_restart + 1, sizeof( real*) );
+            workspace->hs = (real *)  calloc( control->cm_solver_restart + 1, sizeof( real ) );
+            workspace->hc = (real *)  calloc( control->cm_solver_restart + 1, sizeof( real ) );
+            workspace->rn = (real **) calloc( control->cm_solver_restart + 1, sizeof( real*) );
+            workspace->v  = (real **) calloc( control->cm_solver_restart + 1, sizeof( real*) );
+
+            for ( i = 0; i < control->cm_solver_restart + 1; ++i )
+            {
+                workspace->h[i]  = (real *) calloc( control->cm_solver_restart + 1, sizeof( real ) );
+                workspace->rn[i] = (real *) calloc( system->N_cm * 2, sizeof( real ) );
+                workspace->v[i]  = (real *) calloc( system->N_cm, sizeof( real ) );
+            }
+
+            workspace->r = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->d = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->q = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->p = (real *) calloc( system->N_cm, sizeof( real ) );
+            break;
+
+        /* CG storage */
+        case CG_S:
+            workspace->r = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->d = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->q = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->p = (real *) calloc( system->N_cm, sizeof( real ) );
+            break;
+
+        case SDM_S:
+            workspace->r = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->d = (real *) calloc( system->N_cm, sizeof( real ) );
+            workspace->q = (real *) calloc( system->N_cm, sizeof( real ) );
+            break;
+
+        default:
+            fprintf( stderr, "Unknown charge method linear solver type. Terminating...\n" );
+            exit( INVALID_INPUT );
+            break;
     }
 
-    /* CG storage */
-    workspace->r = (real *) calloc( system->N, sizeof( real ) );
-    workspace->d = (real *) calloc( system->N, sizeof( real ) );
-    workspace->q = (real *) calloc( system->N, sizeof( real ) );
-    workspace->p = (real *) calloc( system->N, sizeof( real ) );
-
-
     /* integrator storage */
     workspace->a = (rvec *) malloc( system->N * sizeof( rvec ) );
     workspace->f_old = (rvec *) malloc( system->N * sizeof( rvec ) );
     workspace->v_const = (rvec *) malloc( system->N * sizeof( rvec ) );
 
-
     /* storage for analysis */
     if ( control->molec_anal || control->diffusion_coef )
     {
@@ -361,12 +451,18 @@ void Init_Workspace( reax_system *system, control_params *control,
         workspace->old_mark = (int *) calloc( system->N, sizeof(int) );
     }
     else
+    {
         workspace->mark = workspace->old_mark = NULL;
+    }
 
     if ( control->diffusion_coef )
+    {
         workspace->x_old = (rvec *) calloc( system->N, sizeof( rvec ) );
-    else workspace->x_old = NULL;
-
+    }
+    else
+    {
+        workspace->x_old = NULL;
+    }
 
 #ifdef TEST_FORCES
     workspace->dDelta = (rvec *) malloc( system->N * sizeof( rvec ) );
@@ -403,15 +499,17 @@ void Init_Lists( reax_system *system, control_params *control,
                  simulation_data *data, static_storage *workspace,
                  list **lists, output_controls *out_control )
 {
-    int i, num_nbrs, num_hbonds, num_bonds, num_3body, Htop;
+    int i, num_nbrs, num_hbonds, num_bonds, num_3body, Htop, max_nnz;
     int *hb_top, *bond_top;
 
     num_nbrs = Estimate_NumNeighbors( system, control, workspace, lists );
+
     if ( !Make_List(system->N, num_nbrs, TYP_FAR_NEIGHBOR, (*lists) + FAR_NBRS) )
     {
         fprintf(stderr, "Problem in initializing far nbrs list. Terminating!\n");
         exit( CANNOT_INITIALIZE );
     }
+
 #if defined(DEBUG_FOCUS)
     fprintf( stderr, "memory allocated: far_nbrs = %ldMB\n",
              num_nbrs * sizeof(far_neighbor_data) / (1024 * 1024) );
@@ -422,10 +520,26 @@ void Init_Lists( reax_system *system, control_params *control,
     hb_top = (int*) calloc( system->N, sizeof(int) );
     bond_top = (int*) calloc( system->N, sizeof(int) );
     num_3body = 0;
-    Estimate_Storage_Sizes( system, control, lists,
-                            &Htop, hb_top, bond_top, &num_3body );
+    Estimate_Storage_Sizes( system, control, lists, &Htop,
+            hb_top, bond_top, &num_3body );
 
-    if ( Allocate_Matrix( &(workspace->H), system->N, Htop ) == FAILURE )
+    switch ( control->charge_method )
+    {
+        case QEQ_CM:
+            max_nnz = Htop;
+            break;
+        case EE_CM:
+            max_nnz = Htop + system->N_cm;
+            break;
+        case ACKS2_CM:
+            max_nnz = 2 * Htop + 3 * system->N + 2;
+            break;
+        default:
+            max_nnz = Htop;
+            break;
+    }
+
+    if ( Allocate_Matrix( &(workspace->H), system->N_cm, max_nnz ) == FAILURE )
     {
         fprintf( stderr, "Not enough space for init matrices. Terminating...\n" );
         exit( INSUFFICIENT_MEMORY );
@@ -434,15 +548,16 @@ void Init_Lists( reax_system *system, control_params *control,
      *   If so, need to refactor Estimate_Storage_Sizes
      *   to use various cut-off distances as parameters
      *   (non-bonded, hydrogen, 3body, etc.) */
-    if ( Allocate_Matrix( &(workspace->H_sp), system->N, Htop ) == FAILURE )
+    if ( Allocate_Matrix( &(workspace->H_sp), system->N_cm, max_nnz ) == FAILURE )
     {
         fprintf( stderr, "Not enough space for init matrices. Terminating...\n" );
         exit( INSUFFICIENT_MEMORY );
     }
+
 #if defined(DEBUG_FOCUS)
     fprintf( stderr, "estimated storage - Htop: %d\n", Htop );
     fprintf( stderr, "memory allocated: H = %ldMB\n",
-             Htop * sizeof(sparse_matrix_entry) / (1024 * 1024) );
+            Htop * sizeof(sparse_matrix_entry) / (1024 * 1024) );
 #endif
 
     workspace->num_H = 0;
@@ -450,13 +565,22 @@ void Init_Lists( reax_system *system, control_params *control,
     {
         /* init H indexes */
         for ( i = 0; i < system->N; ++i )
-            if ( system->reaxprm.sbp[ system->atoms[i].type ].p_hbond == 1 ) // H atom
+        {
+            // H atom
+            if ( system->reaxprm.sbp[ system->atoms[i].type ].p_hbond == 1 )
+            {
                 workspace->hbond_index[i] = workspace->num_H++;
-            else workspace->hbond_index[i] = -1;
+            }
+            else
+            {
+                workspace->hbond_index[i] = -1;
+            }
+        }
 
         Allocate_HBond_List( system->N, workspace->num_H, workspace->hbond_index,
-                             hb_top, (*lists) + HBONDS );
+                hb_top, (*lists) + HBONDS );
         num_hbonds = hb_top[system->N - 1];
+
 #if defined(DEBUG_FOCUS)
         fprintf( stderr, "estimated storage - num_hbonds: %d\n", num_hbonds );
         fprintf( stderr, "memory allocated: hbonds = %ldMB\n",
@@ -467,6 +591,7 @@ void Init_Lists( reax_system *system, control_params *control,
     /* bonds list */
     Allocate_Bond_List( system->N, bond_top, (*lists) + BONDS );
     num_bonds = bond_top[system->N - 1];
+
 #if defined(DEBUG_FOCUS)
     fprintf( stderr, "estimated storage - num_bonds: %d\n", num_bonds );
     fprintf( stderr, "memory allocated: bonds = %ldMB\n",
@@ -483,11 +608,13 @@ void Init_Lists( reax_system *system, control_params *control,
         fprintf( stderr, "Problem in initializing angles list. Terminating!\n" );
         exit( CANNOT_INITIALIZE );
     }
+
 #if defined(DEBUG_FOCUS)
     fprintf( stderr, "estimated storage - num_3body: %d\n", num_3body );
     fprintf( stderr, "memory allocated: 3-body = %ldMB\n",
              num_3body * sizeof(three_body_interaction_data) / (1024 * 1024) );
 #endif
+
 #ifdef TEST_FORCES
     if (!Make_List( system->N, num_bonds * 8, TYP_DDELTA, (*lists) + DDELTA ))
     {
@@ -548,7 +675,7 @@ void Init_Out_Controls(reax_system *system, control_params *control,
         out_control->log = fopen( temp, "w" );
         fprintf( out_control->log, "%-6s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s\n",
                  "step", "total", "neighbors", "init", "bonded",
-                 "nonbonded", "QEq", "QEq Sort", "S iters", "Pre Comp", "Pre App",
+                 "nonbonded", "CM", "CM Sort", "S iters", "Pre Comp", "Pre App",
                  "S spmv", "S vec ops", "S orthog", "S tsolve" );
     }
 
diff --git a/sPuReMD/src/integrate.c b/sPuReMD/src/integrate.c
index f9768c49bc89915346645f6134e9e346c845c2d6..4e573d388b481e006fcf821333c8b43b38816018 100644
--- a/sPuReMD/src/integrate.c
+++ b/sPuReMD/src/integrate.c
@@ -27,7 +27,7 @@
 #include "grid.h"
 #include "neighbors.h"
 #include "print_utils.h"
-#include "qeq.h"
+#include "charges.h"
 #include "reset_utils.h"
 #include "restart.h"
 #include "system_props.h"
@@ -483,7 +483,7 @@ void Velocity_Verlet_Nose_Hoover_NVT(reax_system* system,
     fprintf(out_control->log, "nbrs-");
     fflush( out_control->log );
 
-    /* QEq( system, control, workspace, lists[FAR_NBRS], out_control );
+    /* Compute_Charges( system, control, workspace, lists[FAR_NBRS], out_control );
        fprintf(out_control->log,"qeq-"); fflush( out_control->log ); */
 
     Compute_Forces( system, control, data, workspace, lists, out_control );
@@ -589,7 +589,7 @@ void Velocity_Verlet_Isotropic_NPT( reax_system* system,
     fprintf(out_control->log, "nbrs-");
     fflush( out_control->log );
 
-    /* QEq( system, control, workspace, lists[FAR_NBRS], out_control );
+    /* Compute_Charges( system, control, workspace, lists[FAR_NBRS], out_control );
        fprintf(out_control->log,"qeq-"); fflush( out_control->log ); */
 
     Compute_Forces( system, control, data, workspace, lists, out_control );
diff --git a/sPuReMD/src/lin_alg.c b/sPuReMD/src/lin_alg.c
index 1759b41c76969a8ec64047d60c744f6a5771abbb..28b7c9560d4ab5f11e8161f8a9ff867ab5f3dc1a 100644
--- a/sPuReMD/src/lin_alg.c
+++ b/sPuReMD/src/lin_alg.c
@@ -28,13 +28,6 @@
 #include "vector.h"
 
 
-typedef enum
-{
-    LOWER = 0,
-    UPPER = 1,
-} TRIANGULARITY;
-
-
 /* global to make OpenMP shared (Sparse_MatVec) */
 #ifdef _OPENMP
 real *b_local = NULL;
@@ -75,7 +68,7 @@ real *Dinv_b = NULL, *rp = NULL, *rp2 = NULL, *rp3 = NULL;
  *   x: vector
  *   b: vector (result) */
 static void Sparse_MatVec( const sparse_matrix * const A,
-                           const real * const x, real * const b )
+        const real * const x, real * const b )
 {
     int i, j, k, n, si, ei;
     real H;
@@ -153,7 +146,7 @@ static void Sparse_MatVec( const sparse_matrix * const A,
  * A: stored in CSR
  * A_t: stored in CSR
  */
-void Transpose( const sparse_matrix const *A, sparse_matrix const *A_t )
+void Transpose( const sparse_matrix * const A, sparse_matrix const *A_t )
 {
     unsigned int i, j, pj, *A_t_top;
 
@@ -225,10 +218,10 @@ void Transpose_I( sparse_matrix * const A )
  * Hdia_inv: diagonal inverse preconditioner (constructed using H)
  * y: current residual
  * x: preconditioned residual
- * N: length of preconditioner and vectors (# rows in H)
+ * N: dimensions of preconditioner and vectors (# rows in H)
  */
 static void diag_pre_app( const real * const Hdia_inv, const real * const y,
-                          real * const x, const int N )
+        real * const x, const int N )
 {
     unsigned int i;
 
@@ -245,13 +238,14 @@ static void diag_pre_app( const real * const Hdia_inv, const real * const y,
  * LU: lower/upper triangular, stored in CSR
  * y: constants in linear system (RHS)
  * x: solution
+ * N: dimensions of matrix and vectors
  * tri: triangularity of LU (lower/upper)
  *
  * Assumptions:
  *   LU has non-zero diagonals
  *   Each row of LU has at least one non-zero (i.e., no rows with all zeros) */
-static void tri_solve( const sparse_matrix * const LU, const real * const y,
-                       real * const x, const TRIANGULARITY tri )
+void tri_solve( const sparse_matrix * const LU, const real * const y,
+        real * const x, const int N, const TRIANGULARITY tri )
 {
     int i, pj, j, si, ei;
     real val;
@@ -260,7 +254,7 @@ static void tri_solve( const sparse_matrix * const LU, const real * const y,
     {
         if ( tri == LOWER )
         {
-            for ( i = 0; i < LU->n; ++i )
+            for ( i = 0; i < N; ++i )
             {
                 x[i] = y[i];
                 si = LU->start[i];
@@ -276,7 +270,7 @@ static void tri_solve( const sparse_matrix * const LU, const real * const y,
         }
         else
         {
-            for ( i = LU->n - 1; i >= 0; --i )
+            for ( i = N - 1; i >= 0; --i )
             {
                 x[i] = y[i];
                 si = LU->start[i];
@@ -299,14 +293,16 @@ static void tri_solve( const sparse_matrix * const LU, const real * const y,
  * LU: lower/upper triangular, stored in CSR
  * y: constants in linear system (RHS)
  * x: solution
+ * N: dimensions of matrix and vectors
  * tri: triangularity of LU (lower/upper)
  * find_levels: perform level search if positive, otherwise reuse existing levels
  *
  * Assumptions:
  *   LU has non-zero diagonals
  *   Each row of LU has at least one non-zero (i.e., no rows with all zeros) */
-static void tri_solve_level_sched( const sparse_matrix * const LU, const real * const y,
-                                   real * const x, const TRIANGULARITY tri, int find_levels )
+void tri_solve_level_sched( const sparse_matrix * const LU,
+        const real * const y, real * const x, const int N,
+        const TRIANGULARITY tri, int find_levels )
 {
     int i, j, pj, local_row, local_level;
 
@@ -329,9 +325,9 @@ static void tri_solve_level_sched( const sparse_matrix * const LU, const real *
 
         if ( row_levels == NULL || level_rows == NULL || level_rows_cnt == NULL )
         {
-            if ( (row_levels = (unsigned int*) malloc((size_t)LU->n * sizeof(unsigned int))) == NULL
-                    || (level_rows = (unsigned int*) malloc((size_t)LU->n * sizeof(unsigned int))) == NULL
-                    || (level_rows_cnt = (unsigned int*) malloc((size_t)(LU->n + 1) * sizeof(unsigned int))) == NULL )
+            if ( (row_levels = (unsigned int*) malloc((size_t)N * sizeof(unsigned int))) == NULL
+                    || (level_rows = (unsigned int*) malloc((size_t)N * sizeof(unsigned int))) == NULL
+                    || (level_rows_cnt = (unsigned int*) malloc((size_t)(N + 1) * sizeof(unsigned int))) == NULL )
             {
                 fprintf( stderr, "Not enough space for triangular solve via level scheduling. Terminating...\n" );
                 exit( INSUFFICIENT_MEMORY );
@@ -340,7 +336,7 @@ static void tri_solve_level_sched( const sparse_matrix * const LU, const real *
 
         if ( top == NULL )
         {
-            if ( (top = (unsigned int*) malloc((size_t)(LU->n + 1) * sizeof(unsigned int))) == NULL )
+            if ( (top = (unsigned int*) malloc((size_t)(N + 1) * sizeof(unsigned int))) == NULL )
             {
                 fprintf( stderr, "Not enough space for triangular solve via level scheduling. Terminating...\n" );
                 exit( INSUFFICIENT_MEMORY );
@@ -350,14 +346,14 @@ static void tri_solve_level_sched( const sparse_matrix * const LU, const real *
         /* find levels (row dependencies in substitutions) */
         if ( find_levels == TRUE )
         {
-            memset( row_levels, 0, LU->n * sizeof(unsigned int) );
-            memset( level_rows_cnt, 0, LU->n * sizeof(unsigned int) );
-            memset( top, 0, LU->n * sizeof(unsigned int) );
+            memset( row_levels, 0, N * sizeof(unsigned int) );
+            memset( level_rows_cnt, 0, N * sizeof(unsigned int) );
+            memset( top, 0, N * sizeof(unsigned int) );
             levels = 1;
 
             if ( tri == LOWER )
             {
-                for ( i = 0; i < LU->n; ++i )
+                for ( i = 0; i < N; ++i )
                 {
                     local_level = 1;
                     for ( pj = LU->start[i]; pj < LU->start[i + 1] - 1; ++pj )
@@ -372,12 +368,12 @@ static void tri_solve_level_sched( const sparse_matrix * const LU, const real *
 
 //#if defined(DEBUG)
                 fprintf(stderr, "levels(L): %d\n", levels);
-                fprintf(stderr, "NNZ(L): %d\n", LU->start[LU->n]);
+                fprintf(stderr, "NNZ(L): %d\n", LU->start[N]);
 //#endif
             }
             else
             {
-                for ( i = LU->n - 1; i >= 0; --i )
+                for ( i = N - 1; i >= 0; --i )
                 {
                     local_level = 1;
                     for ( pj = LU->start[i] + 1; pj < LU->start[i + 1]; ++pj )
@@ -392,7 +388,7 @@ static void tri_solve_level_sched( const sparse_matrix * const LU, const real *
 
 //#if defined(DEBUG)
                 fprintf(stderr, "levels(U): %d\n", levels);
-                fprintf(stderr, "NNZ(U): %d\n", LU->start[LU->n]);
+                fprintf(stderr, "NNZ(U): %d\n", LU->start[N]);
 //#endif
             }
 
@@ -402,7 +398,7 @@ static void tri_solve_level_sched( const sparse_matrix * const LU, const real *
                 top[i] = level_rows_cnt[i];
             }
 
-            for ( i = 0; i < LU->n; ++i )
+            for ( i = 0; i < N; ++i )
             {
                 level_rows[top[row_levels[i] - 1]] = i;
                 ++top[row_levels[i] - 1];
@@ -921,7 +917,7 @@ sparse_matrix * setup_graph_coloring( sparse_matrix * const H )
  *
  * Note: Newmann series arises from series expansion of the inverse of
  * the coefficient matrix in the triangular system */
-static void jacobi_iter( const sparse_matrix * const R, const real * const Dinv,
+void jacobi_iter( const sparse_matrix * const R, const real * const Dinv,
         const real * const b, real * const x, const TRIANGULARITY tri, const
         unsigned int maxiter )
 {
@@ -1026,164 +1022,167 @@ static void jacobi_iter( const sparse_matrix * const R, const real * const Dinv,
  *   Matrices have non-zero diagonals
  *   Each row of a matrix has at least one non-zero (i.e., no rows with all zeros) */
 static void apply_preconditioner( const static_storage * const workspace, const control_params * const control,
-                                  const real * const y, real * const x, const int fresh_pre )
+        const real * const y, real * const x, const int fresh_pre )
 {
     int i, si;
 
-    switch ( control->pre_app_type )
+    /* no preconditioning */
+    if ( control->cm_solver_pre_comp_type == NONE_PC )
     {
-    case NONE_PA:
-        break;
-    case TRI_SOLVE_PA:
-        switch ( control->pre_comp_type )
-        {
-        case DIAG_PC:
-            diag_pre_app( workspace->Hdia_inv, y, x, workspace->H->n );
-            break;
-        case ICHOLT_PC:
-        case ILU_PAR_PC:
-        case ILUT_PAR_PC:
-            tri_solve( workspace->L, y, x, LOWER );
-            tri_solve( workspace->U, x, x, UPPER );
-            break;
-        default:
-            fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
-            exit( INVALID_INPUT );
-            break;
-        }
-        break;
-    case TRI_SOLVE_LEVEL_SCHED_PA:
-        switch ( control->pre_comp_type )
-        {
-        case DIAG_PC:
-            diag_pre_app( workspace->Hdia_inv, y, x, workspace->H->n );
-            break;
-        case ICHOLT_PC:
-        case ILU_PAR_PC:
-        case ILUT_PAR_PC:
-            tri_solve_level_sched( workspace->L, y, x, LOWER, fresh_pre );
-            tri_solve_level_sched( workspace->U, x, x, UPPER, fresh_pre );
-            break;
-        default:
-            fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
-            exit( INVALID_INPUT );
-            break;
-        }
-        break;
-    case TRI_SOLVE_GC_PA:
-        switch ( control->pre_comp_type )
+        Vector_Copy( x, y, workspace->H->n );
+    }
+    else
+    {
+        switch ( control->cm_solver_pre_app_type )
         {
-        case DIAG_PC:
-            fprintf( stderr, "Unsupported preconditioner computation/application method combination. Terminating...\n" );
-            exit( INVALID_INPUT );
+        case TRI_SOLVE_PA:
+            switch ( control->cm_solver_pre_comp_type )
+            {
+            case DIAG_PC:
+                diag_pre_app( workspace->Hdia_inv, y, x, workspace->H->n );
+                break;
+            case ICHOLT_PC:
+            case ILU_PAR_PC:
+            case ILUT_PAR_PC:
+                tri_solve( workspace->L, y, x, workspace->L->n, LOWER );
+                tri_solve( workspace->U, x, x, workspace->U->n, UPPER );
+                break;
+            default:
+                fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
+                exit( INVALID_INPUT );
+                break;
+            }
             break;
-        case ICHOLT_PC:
-        case ILU_PAR_PC:
-        case ILUT_PAR_PC:
-            #pragma omp master
+        case TRI_SOLVE_LEVEL_SCHED_PA:
+            switch ( control->cm_solver_pre_comp_type )
             {
-                memcpy( y_p, y, sizeof(real) * workspace->H->n );
+            case DIAG_PC:
+                diag_pre_app( workspace->Hdia_inv, y, x, workspace->H->n );
+                break;
+            case ICHOLT_PC:
+            case ILU_PAR_PC:
+            case ILUT_PAR_PC:
+                tri_solve_level_sched( workspace->L, y, x, workspace->L->n, LOWER, fresh_pre );
+                tri_solve_level_sched( workspace->U, x, x, workspace->U->n, UPPER, fresh_pre );
+                break;
+            default:
+                fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
+                exit( INVALID_INPUT );
+                break;
             }
+            break;
+        case TRI_SOLVE_GC_PA:
+            switch ( control->cm_solver_pre_comp_type )
+            {
+            case DIAG_PC:
+                fprintf( stderr, "Unsupported preconditioner computation/application method combination. Terminating...\n" );
+                exit( INVALID_INPUT );
+                break;
+            case ICHOLT_PC:
+            case ILU_PAR_PC:
+            case ILUT_PAR_PC:
+                #pragma omp master
+                {
+                    memcpy( y_p, y, sizeof(real) * workspace->H->n );
+                }
 
-            #pragma omp barrier
+                #pragma omp barrier
 
-            permute_vector( y_p, workspace->H->n, FALSE, LOWER );
-            tri_solve_level_sched( workspace->L, y_p, x, LOWER, fresh_pre );
-            tri_solve_level_sched( workspace->U, x, x, UPPER, fresh_pre );
-            permute_vector( x, workspace->H->n, TRUE, UPPER );
-        break;
-        default:
-            fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
-            exit( INVALID_INPUT );
+                permute_vector( y_p, workspace->H->n, FALSE, LOWER );
+                tri_solve_level_sched( workspace->L, y_p, x, workspace->L->n, LOWER, fresh_pre );
+                tri_solve_level_sched( workspace->U, x, x, workspace->U->n, UPPER, fresh_pre );
+                permute_vector( x, workspace->H->n, TRUE, UPPER );
             break;
-        }
-        break;
-    case JACOBI_ITER_PA:
-        switch ( control->pre_comp_type )
-        {
-        case DIAG_PC:
-            fprintf( stderr, "Unsupported preconditioner computation/application method combination. Terminating...\n" );
-            exit( INVALID_INPUT );
+            default:
+                fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
+                exit( INVALID_INPUT );
+                break;
+            }
             break;
-        case ICHOLT_PC:
-        case ILU_PAR_PC:
-        case ILUT_PAR_PC:
-            #pragma omp master
+        case JACOBI_ITER_PA:
+            switch ( control->cm_solver_pre_comp_type )
             {
-                if ( Dinv_L == NULL )
+            case DIAG_PC:
+                fprintf( stderr, "Unsupported preconditioner computation/application method combination. Terminating...\n" );
+                exit( INVALID_INPUT );
+                break;
+            case ICHOLT_PC:
+            case ILU_PAR_PC:
+            case ILUT_PAR_PC:
+                #pragma omp master
                 {
-                    if ( (Dinv_L = (real*) malloc(sizeof(real) * workspace->L->n)) == NULL )
+                    if ( Dinv_L == NULL )
                     {
-                        fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" );
-                        exit( INSUFFICIENT_MEMORY );
+                        if ( (Dinv_L = (real*) malloc(sizeof(real) * workspace->L->n)) == NULL )
+                        {
+                            fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" );
+                            exit( INSUFFICIENT_MEMORY );
+                        }
                     }
                 }
-            }
 
-            #pragma omp barrier
+                #pragma omp barrier
 
-            /* construct D^{-1}_L */
-            if ( fresh_pre == TRUE )
-            {
-                #pragma omp for schedule(static)
-                for ( i = 0; i < workspace->L->n; ++i )
+                /* construct D^{-1}_L */
+                if ( fresh_pre == TRUE )
                 {
-                    si = workspace->L->start[i + 1] - 1;
-                    Dinv_L[i] = 1. / workspace->L->val[si];
+                    #pragma omp for schedule(static)
+                    for ( i = 0; i < workspace->L->n; ++i )
+                    {
+                        si = workspace->L->start[i + 1] - 1;
+                        Dinv_L[i] = 1. / workspace->L->val[si];
+                    }
                 }
-            }
 
-            jacobi_iter( workspace->L, Dinv_L, y, x, LOWER, control->pre_app_jacobi_iters );
+                jacobi_iter( workspace->L, Dinv_L, y, x, LOWER, control->cm_solver_pre_app_jacobi_iters );
 
-            #pragma omp master
-            {
-                if ( Dinv_U == NULL )
+                #pragma omp master
                 {
-                    if ( (Dinv_U = (real*) malloc(sizeof(real) * workspace->U->n)) == NULL )
+                    if ( Dinv_U == NULL )
                     {
-                        fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" );
-                        exit( INSUFFICIENT_MEMORY );
+                        if ( (Dinv_U = (real*) malloc(sizeof(real) * workspace->U->n)) == NULL )
+                        {
+                            fprintf( stderr, "not enough memory for Jacobi iteration matrices. terminating.\n" );
+                            exit( INSUFFICIENT_MEMORY );
+                        }
                     }
                 }
-            }
 
-            #pragma omp barrier
+                #pragma omp barrier
 
-            /* construct D^{-1}_U */
-            if ( fresh_pre == TRUE )
-            {
-                #pragma omp for schedule(static)
-                for ( i = 0; i < workspace->U->n; ++i )
+                /* construct D^{-1}_U */
+                if ( fresh_pre == TRUE )
                 {
-                    si = workspace->U->start[i];
-                    Dinv_U[i] = 1. / workspace->U->val[si];
+                    #pragma omp for schedule(static)
+                    for ( i = 0; i < workspace->U->n; ++i )
+                    {
+                        si = workspace->U->start[i];
+                        Dinv_U[i] = 1. / workspace->U->val[si];
+                    }
                 }
-            }
 
-            jacobi_iter( workspace->U, Dinv_U, y, x, UPPER, control->pre_app_jacobi_iters );
+                jacobi_iter( workspace->U, Dinv_U, y, x, UPPER, control->cm_solver_pre_app_jacobi_iters );
+                break;
+            default:
+                fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
+                exit( INVALID_INPUT );
+                break;
+            }
             break;
         default:
             fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
             exit( INVALID_INPUT );
             break;
-        }
-        break;
-    default:
-        fprintf( stderr, "Unrecognized preconditioner application method. Terminating...\n" );
-        exit( INVALID_INPUT );
-        break;
 
+        }
     }
-
-    return;
 }
 
 
 /* generalized minimual residual iterative solver for sparse linear systems */
 int GMRES( const static_storage * const workspace, const control_params * const control,
-           simulation_data * const data, const sparse_matrix * const H,
-           const real * const b, const real tol, real * const x,
-           const FILE * const fout, const int fresh_pre )
+        simulation_data * const data, const sparse_matrix * const H, const real * const b,
+        const real tol, real * const x, const int fresh_pre )
 {
     int i, j, k, itr, N, g_j, g_itr;
     real cc, tmp1, tmp2, temp, ret_temp, bnorm, time_start;
@@ -1200,10 +1199,10 @@ int GMRES( const static_storage * const workspace, const control_params * const
         bnorm = Norm( b, N );
         #pragma omp master
         {
-            data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+            data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
         }
 
-        if ( control->pre_comp_type == DIAG_PC )
+        if ( control->cm_solver_pre_comp_type == DIAG_PC )
         {
             /* apply preconditioner to RHS */
             #pragma omp master
@@ -1213,12 +1212,12 @@ int GMRES( const static_storage * const workspace, const control_params * const
             apply_preconditioner( workspace, control, b, workspace->b_prc, fresh_pre );
             #pragma omp master
             {
-                data->timing.pre_app += Get_Timing_Info( time_start );
+                data->timing.cm_solver_pre_app += Get_Timing_Info( time_start );
             }
         }
 
         /* GMRES outer-loop */
-        for ( itr = 0; itr < MAX_ITR; ++itr )
+        for ( itr = 0; itr < control->cm_solver_max_iters; ++itr )
         {
             /* calculate r0 */
             #pragma omp master
@@ -1228,10 +1227,10 @@ int GMRES( const static_storage * const workspace, const control_params * const
             Sparse_MatVec( H, x, workspace->b_prm );
             #pragma omp master
             {
-                data->timing.solver_spmv += Get_Timing_Info( time_start );
+                data->timing.cm_solver_spmv += Get_Timing_Info( time_start );
             }
 
-            if ( control->pre_comp_type == DIAG_PC )
+            if ( control->cm_solver_pre_comp_type == DIAG_PC )
             {
                 #pragma omp master
                 {
@@ -1240,11 +1239,11 @@ int GMRES( const static_storage * const workspace, const control_params * const
                 apply_preconditioner( workspace, control, workspace->b_prm, workspace->b_prm, FALSE );
                 #pragma omp master
                 {
-                    data->timing.pre_app += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_pre_app += Get_Timing_Info( time_start );
                 }
             }
 
-            if ( control->pre_comp_type == DIAG_PC )
+            if ( control->cm_solver_pre_comp_type == DIAG_PC )
             {
                 #pragma omp master
                 {
@@ -1253,7 +1252,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
                 Vector_Sum( workspace->v[0], 1., workspace->b_prc, -1., workspace->b_prm, N );
                 #pragma omp master
                 {
-                    data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
                 }
             }
             else
@@ -1265,11 +1264,11 @@ int GMRES( const static_storage * const workspace, const control_params * const
                 Vector_Sum( workspace->v[0], 1., b, -1., workspace->b_prm, N );
                 #pragma omp master
                 {
-                    data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
                 }
             }
 
-            if ( control->pre_comp_type != DIAG_PC )
+            if ( control->cm_solver_pre_comp_type != DIAG_PC )
             {
                 #pragma omp master
                 {
@@ -1279,7 +1278,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
                         itr == 0 ? fresh_pre : FALSE );
                 #pragma omp master
                 {
-                    data->timing.pre_app += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_pre_app += Get_Timing_Info( time_start );
                 }
             }
 
@@ -1295,11 +1294,11 @@ int GMRES( const static_storage * const workspace, const control_params * const
             Vector_Scale( workspace->v[0], 1. / workspace->g[0], workspace->v[0], N );
             #pragma omp master
             {
-                data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+                data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
             }
 
             /* GMRES inner-loop */
-            for ( j = 0; j < RESTART && FABS(workspace->g[j]) / bnorm > tol; j++ )
+            for ( j = 0; j < control->cm_solver_restart && FABS(workspace->g[j]) / bnorm > tol; j++ )
             {
                 /* matvec */
                 #pragma omp master
@@ -1309,7 +1308,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
                 Sparse_MatVec( H, workspace->v[j], workspace->v[j + 1] );
                 #pragma omp master
                 {
-                    data->timing.solver_spmv += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_spmv += Get_Timing_Info( time_start );
                 }
 
                 #pragma omp master
@@ -1319,10 +1318,10 @@ int GMRES( const static_storage * const workspace, const control_params * const
                 apply_preconditioner( workspace, control, workspace->v[j + 1], workspace->v[j + 1], FALSE );
                 #pragma omp master
                 {
-                    data->timing.pre_app += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_pre_app += Get_Timing_Info( time_start );
                 }
 
-                if ( control->pre_comp_type == DIAG_PC )
+                if ( control->cm_solver_pre_comp_type == DIAG_PC )
                 {
                     /* apply modified Gram-Schmidt to orthogonalize the new residual */
                     #pragma omp master
@@ -1336,7 +1335,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
                     }
                     #pragma omp master
                     {
-                        data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+                        data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
                     }
                 }
                 else
@@ -1363,7 +1362,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
                     }
                     #pragma omp master
                     {
-                        data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+                        data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
                     }
                 }
 
@@ -1380,7 +1379,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
                               1. / workspace->h[j + 1][j], workspace->v[j + 1], N );
                 #pragma omp master
                 {
-                    data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
                 }
 #if defined(DEBUG)
                 fprintf( stderr, "%d-%d: orthogonalization completed.\n", itr, j );
@@ -1389,7 +1388,8 @@ int GMRES( const static_storage * const workspace, const control_params * const
                 #pragma omp master
                 {
                     time_start = Get_Time( );
-                    if ( control->pre_comp_type == DIAG_PC )
+                    if ( control->cm_solver_pre_comp_type == NONE_PC ||
+                            control->cm_solver_pre_comp_type == DIAG_PC )
                     {
                         /* Givens rotations on the upper-Hessenberg matrix to make it U */
                         for ( i = 0; i <= j; i++ )
@@ -1438,7 +1438,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
                     tmp2 = -workspace->hs[j] * workspace->g[j];
                     workspace->g[j] = tmp1;
                     workspace->g[j + 1] = tmp2;
-                    data->timing.solver_orthog += Get_Timing_Info( time_start );
+                    data->timing.cm_solver_orthog += Get_Timing_Info( time_start );
                 }
 
                 #pragma omp barrier
@@ -1464,7 +1464,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
 
                     workspace->y[i] = temp / workspace->h[i][i];
                 }
-                data->timing.solver_tri_solve += Get_Timing_Info( time_start );
+                data->timing.cm_solver_tri_solve += Get_Timing_Info( time_start );
 
                 /* update x = x_0 + Vy */
                 time_start = Get_Time( );
@@ -1478,7 +1478,7 @@ int GMRES( const static_storage * const workspace, const control_params * const
             Vector_Add( x, 1., workspace->p, N );
             #pragma omp master
             {
-                data->timing.solver_vector_ops += Get_Timing_Info( time_start );
+                data->timing.cm_solver_vector_ops += Get_Timing_Info( time_start );
             }
 
             /* stopping condition */
@@ -1495,38 +1495,25 @@ int GMRES( const static_storage * const workspace, const control_params * const
         }
     }
 
-    // Sparse_MatVec( H, x, workspace->b_prm );
-    // for( i = 0; i < N; ++i )
-    // workspace->b_prm[i] *= workspace->Hdia_inv[i];
-    // fprintf( fout, "\n%10s%15s%15s\n", "b_prc", "b_prm", "x" );
-    // for( i = 0; i < N; ++i )
-    // fprintf( fout, "%10.5f%15.12f%15.12f\n",
-    // workspace->b_prc[i], workspace->b_prm[i], x[i] );*/
-
-    // fprintf(fout,"GMRES outer:%d, inner:%d iters - residual norm: %25.20f\n",
-    //          itr, j, fabs( workspace->g[j] ) / bnorm );
-    // data->timing.solver_iters += itr * RESTART + j;
-
-    if ( g_itr >= MAX_ITR )
+    if ( g_itr >= control->cm_solver_max_iters )
     {
         fprintf( stderr, "GMRES convergence failed\n" );
-        // return -1;
-        return g_itr * (RESTART + 1) + g_j + 1;
+        return g_itr * (control->cm_solver_restart + 1) + g_j + 1;
     }
 
-    return g_itr * (RESTART + 1) + g_j + 1;
+    return g_itr * (control->cm_solver_restart + 1) + g_j + 1;
 }
 
 
-int GMRES_HouseHolder( const static_storage * const workspace, const control_params * const control,
-                       simulation_data * const data, const sparse_matrix * const H,
-                       const real * const b, real tol, real * const x,
-                       const FILE * const fout, const int fresh_pre )
+int GMRES_HouseHolder( const static_storage * const workspace,
+        const control_params * const control, simulation_data * const data,
+        const sparse_matrix * const H, const real * const b, real tol,
+        real * const x, const int fresh_pre )
 {
     int  i, j, k, itr, N;
     real cc, tmp1, tmp2, temp, bnorm;
-    real v[10000], z[RESTART + 2][10000], w[RESTART + 2];
-    real u[RESTART + 2][10000];
+    real v[10000], z[control->cm_solver_restart + 2][10000], w[control->cm_solver_restart + 2];
+    real u[control->cm_solver_restart + 2][10000];
 
     N = H->n;
     bnorm = Norm( b, N );
@@ -1540,7 +1527,7 @@ int GMRES_HouseHolder( const static_storage * const workspace, const control_par
     // memset( x, 0, sizeof(real) * N );
 
     /* GMRES outer-loop */
-    for ( itr = 0; itr < MAX_ITR; ++itr )
+    for ( itr = 0; itr < control->cm_solver_max_iters; ++itr )
     {
         /* compute z = r0 */
         Sparse_MatVec( H, x, workspace->b_prm );
@@ -1550,7 +1537,7 @@ int GMRES_HouseHolder( const static_storage * const workspace, const control_par
         }
         Vector_Sum( z[0], 1.,  workspace->b_prc, -1., workspace->b_prm, N );
 
-        Vector_MakeZero( w, RESTART + 1 );
+        Vector_MakeZero( w, control->cm_solver_restart + 1 );
         w[0] = Norm( z[0], N );
 
         Vector_Copy( u[0], z[0], N );
@@ -1561,7 +1548,7 @@ int GMRES_HouseHolder( const static_storage * const workspace, const control_par
         // fprintf( stderr, "\n\n%12.6f\n", w[0] );
 
         /* GMRES inner-loop */
-        for ( j = 0; j < RESTART && fabs( w[j] ) / bnorm > tol; j++ )
+        for ( j = 0; j < control->cm_solver_restart && fabs( w[j] ) / bnorm > tol; j++ )
         {
             /* compute v_j */
             Vector_Scale( z[j], -2 * u[j][j], u[j], N );
@@ -1665,7 +1652,7 @@ int GMRES_HouseHolder( const static_storage * const workspace, const control_par
         }
 
         // fprintf( stderr, "y: " );
-        // for( i = 0; i < RESTART+1; ++i )
+        // for( i = 0; i < control->cm_solver_restart+1; ++i )
         //   fprintf( stderr, "%8.3f ", workspace->y[i] );
 
 
@@ -1693,10 +1680,6 @@ int GMRES_HouseHolder( const static_storage * const workspace, const control_par
             Vector_Add( x, workspace->y[i], z[i], N );
         }
 
-        // fprintf( stderr, "\nx_aft: " );
-        // for( i = 0; i < N; ++i )
-        //   fprintf( stderr, "%6.2f ", x[i] );
-
         /* stopping condition */
         if ( fabs( w[j] ) / bnorm <= tol )
         {
@@ -1704,197 +1687,135 @@ int GMRES_HouseHolder( const static_storage * const workspace, const control_par
         }
     }
 
-    // Sparse_MatVec( H, x, workspace->b_prm );
-    // for( i = 0; i < N; ++i )
-    // workspace->b_prm[i] *= workspace->Hdia_inv[i];
-
-    // fprintf( fout, "\n%10s%15s%15s\n", "b_prc", "b_prm", "x" );
-    // for( i = 0; i < N; ++i )
-    // fprintf( fout, "%10.5f%15.12f%15.12f\n",
-    // workspace->b_prc[i], workspace->b_prm[i], x[i] );
-
-    //fprintf( fout,"GMRES outer:%d, inner:%d iters - residual norm: %15.10f\n",
-    //         itr, j, fabs( workspace->g[j] ) / bnorm );
-
-    if ( itr >= MAX_ITR )
+    if ( itr >= control->cm_solver_max_iters )
     {
         fprintf( stderr, "GMRES convergence failed\n" );
-        // return -1;
-        return itr * (RESTART + 1) + j + 1;
+        return itr * (control->cm_solver_restart + 1) + j + 1;
     }
 
-    return itr * (RESTART + 1) + j + 1;
+    return itr * (control->cm_solver_restart + 1) + j + 1;
 }
 
 
-/* Preconditioned Conjugate Gradient */
-int PCG( static_storage *workspace, sparse_matrix *A, real *b, real tol,
-         sparse_matrix *L, sparse_matrix *U, real *x, FILE *fout )
+/* Conjugate Gradient */
+int CG( const static_storage * const workspace, const control_params * const control,
+        const sparse_matrix * const H, const real * const b, const real tol,
+        real * const x, const int fresh_pre )
 {
-    int  i, N;
+    int i, itr, N;
     real tmp, alpha, beta, b_norm, r_norm;
-    real sig0, sig_old, sig_new;
-
-    N = A->n;
-    b_norm = Norm( b, N );
-    //fprintf( stderr, "b_norm: %.15e\n", b_norm );
-
-    Sparse_MatVec( A, x, workspace->q );
-    Vector_Sum( workspace->r , 1.,  b, -1., workspace->q, N );
-    r_norm = Norm(workspace->r, N);
-    //Print_Soln( workspace, x, q, b, N );
-    //fprintf( stderr, "res: %.15e\n", r_norm );
+    real *d, *r, *p, *z;
+    real sig_old, sig_new;
 
-    tri_solve( L, workspace->r, workspace->d, LOWER );
-    tri_solve( U, workspace->d, workspace->p, UPPER );
-    sig_new = Dot( workspace->r, workspace->p, N );
-    sig0 = sig_new;
+    N = H->n;
+    d = workspace->d;
+    r = workspace->r;
+    p = workspace->q;
+    z = workspace->p;
 
-    for ( i = 0; i < 200 && r_norm / b_norm > tol; ++i )
+    #pragma omp parallel default(none) private(i, tmp, alpha, beta, b_norm, r_norm, sig_old, sig_new) \
+        shared(itr, N, d, r, p, z)
     {
-        //for( i = 0; i < 200 && sig_new > SQR(tol) * sig0; ++i ) {
-        Sparse_MatVec( A, workspace->p, workspace->q );
-        tmp = Dot( workspace->q, workspace->p, N );
-        alpha = sig_new / tmp;
-        Vector_Add( x, alpha, workspace->p, N );
-        //fprintf( stderr, "iter%d: |p|=%.15e |q|=%.15e tmp=%.15e\n",
-        //     i+1, Norm(workspace->p,N), Norm(workspace->q,N), tmp );
-
-        Vector_Add( workspace->r, -alpha, workspace->q, N );
-        r_norm = Norm(workspace->r, N);
-        //fprintf( stderr, "res: %.15e\n", r_norm );
-
-        tri_solve( L, workspace->r, workspace->d, LOWER );
-        tri_solve( U, workspace->d, workspace->d, UPPER );
-        sig_old = sig_new;
-        sig_new = Dot( workspace->r, workspace->d, N );
-        beta = sig_new / sig_old;
-        Vector_Sum( workspace->p, 1., workspace->d, beta, workspace->p, N );
-    }
+        b_norm = Norm( b, N );
 
-    //fprintf( fout, "CG took %d iterations\n", i );
-    if ( i >= 200 )
-    {
-        fprintf( stderr, "CG convergence failed!\n" );
-        return i;
-    }
+        Sparse_MatVec( H, x, d );
+        Vector_Sum( r, 1.0,  b, -1.0, d, N );
+        r_norm = Norm( r, N );
 
-    return i;
-}
+        apply_preconditioner( workspace, control, r, z, fresh_pre );
+        Vector_Copy( p, z, N );
 
+        sig_new = Dot( r, z, N );
 
-/* Conjugate Gradient */
-int CG( static_storage *workspace, sparse_matrix *H,
-        real *b, real tol, real *x, FILE *fout )
-{
-    int  i, j, N;
-    real tmp, alpha, beta, b_norm;
-    real sig_old, sig_new, sig0;
+        for ( i = 0; i < control->cm_solver_max_iters && r_norm / b_norm > tol; ++i )
+        {
+            Sparse_MatVec( H, p, d );
 
-    N = H->n;
-    b_norm = Norm( b, N );
-    //fprintf( stderr, "b_norm: %10.6f\n", b_norm );
+            tmp = Dot( d, p, N );
+            alpha = sig_new / tmp;
+            Vector_Add( x, alpha, p, N );
 
-    Sparse_MatVec( H, x, workspace->q );
-    Vector_Sum( workspace->r , 1.,  b, -1., workspace->q, N );
-    for ( j = 0; j < N; ++j )
-    {
-        workspace->d[j] = workspace->r[j] * workspace->Hdia_inv[j];
-    }
+            Vector_Add( r, -alpha, d, N );
+            r_norm = Norm( r, N );
 
-    sig_new = Dot( workspace->r, workspace->d, N );
-    sig0 = sig_new;
-    //Print_Soln( workspace, x, q, b, N );
-    //fprintf( stderr, "sig_new: %24.15e, d_norm:%24.15e, q_norm:%24.15e\n",
-    // sqrt(sig_new), Norm(workspace->d,N), Norm(workspace->q,N) );
-    //fprintf( stderr, "sig_new: %f\n", sig_new );
+            apply_preconditioner( workspace, control, r, z, FALSE );
 
-    for ( i = 0; i < 300 && SQRT(sig_new) / b_norm > tol; ++i )
-    {
-        //for( i = 0; i < 300 && sig_new > SQR(tol)*sig0; ++i ) {
-        Sparse_MatVec( H, workspace->d, workspace->q );
-        tmp = Dot( workspace->d, workspace->q, N );
-        //fprintf( stderr, "tmp: %f\n", tmp );
-        alpha = sig_new / tmp;
-        Vector_Add( x, alpha, workspace->d, N );
-        //fprintf( stderr, "d_norm:%24.15e, q_norm:%24.15e, tmp:%24.15e\n",
-        //     Norm(workspace->d,N), Norm(workspace->q,N), tmp );
-
-        Vector_Add( workspace->r, -alpha, workspace->q, N );
-        for ( j = 0; j < N; ++j )
-        {
-            workspace->p[j] = workspace->r[j] * workspace->Hdia_inv[j];
+            sig_old = sig_new;
+            sig_new = Dot( r, z, N );
+
+            beta = sig_new / sig_old;
+            Vector_Sum( p, 1., z, beta, p, N );
         }
 
-        sig_old = sig_new;
-        sig_new = Dot( workspace->r, workspace->p, N );
-        beta = sig_new / sig_old;
-        Vector_Sum( workspace->d, 1., workspace->p, beta, workspace->d, N );
-        //fprintf( stderr, "sig_new: %f\n", sig_new );
+        #pragma omp single
+        itr = i;
     }
 
-    fprintf( stderr, "CG took %d iterations\n", i );
-
-    if ( i >= 300 )
+    if ( itr >= control->cm_solver_max_iters )
     {
-        fprintf( stderr, "CG convergence failed!\n" );
-        return i;
+        fprintf( stderr, "[WARNING] CG convergence failed (%d iters)\n", itr );
+        return itr;
     }
 
-    return i;
+    return itr;
 }
 
 
 /* Steepest Descent */
-int SDM( static_storage *workspace, sparse_matrix *H,
-         real *b, real tol, real *x, FILE *fout )
+int SDM( const static_storage * const workspace, const control_params * const control,
+        const sparse_matrix * const H, const real * const b, const real tol,
+        real * const x, const int fresh_pre )
 {
-    int  i, j, N;
-    real tmp, alpha, beta, b_norm;
-    real sig0, sig;
+    int i, itr, N;
+    real tmp, alpha, b_norm;
+    real sig;
 
     N = H->n;
-    b_norm = Norm( b, N );
-    //fprintf( stderr, "b_norm: %10.6f\n", b_norm );
 
-    Sparse_MatVec( H, x, workspace->q );
-    Vector_Sum( workspace->r , 1.,  b, -1., workspace->q, N );
-    for ( j = 0; j < N; ++j )
+    #pragma omp parallel default(none) private(i, tmp, alpha, b_norm, sig) \
+        shared(itr, N)
     {
-        workspace->d[j] = workspace->r[j] * workspace->Hdia_inv[j];
-    }
+        b_norm = Norm( b, N );
 
-    sig = Dot( workspace->r, workspace->d, N );
-    sig0 = sig;
+        Sparse_MatVec( H, x, workspace->q );
+        Vector_Sum( workspace->r , 1.0,  b, -1.0, workspace->q, N );
 
-    for ( i = 0; i < 300 && SQRT(sig) / b_norm > tol; ++i )
-    {
-        Sparse_MatVec( H, workspace->d, workspace->q );
+        apply_preconditioner( workspace, control, workspace->r, workspace->d, fresh_pre );
 
         sig = Dot( workspace->r, workspace->d, N );
-        tmp = Dot( workspace->d, workspace->q, N );
-        alpha = sig / tmp;
 
-        Vector_Add( x, alpha, workspace->d, N );
-        Vector_Add( workspace->r, -alpha, workspace->q, N );
-        for ( j = 0; j < N; ++j )
+        for ( i = 0; i < control->cm_solver_max_iters && SQRT(sig) / b_norm > tol; ++i )
         {
-            workspace->d[j] = workspace->r[j] * workspace->Hdia_inv[j];
+            Sparse_MatVec( H, workspace->d, workspace->q );
+
+            sig = Dot( workspace->r, workspace->d, N );
+
+            /* ensure each thread gets a local copy of
+             * the function return value
+             * (which is stored as global inside the function)
+             * before proceeding */
+            #pragma omp barrier
+
+            tmp = Dot( workspace->d, workspace->q, N );
+            alpha = sig / tmp;
+
+            Vector_Add( x, alpha, workspace->d, N );
+            Vector_Add( workspace->r, -alpha, workspace->q, N );
+
+            apply_preconditioner( workspace, control, workspace->r, workspace->d, FALSE );
         }
 
-        //fprintf( stderr, "d_norm:%24.15e, q_norm:%24.15e, tmp:%24.15e\n",
-        //     Norm(workspace->d,N), Norm(workspace->q,N), tmp );
+        #pragma omp single
+        itr = i;
     }
 
-    fprintf( stderr, "SDM took %d iterations\n", i );
-
-    if ( i >= 300 )
+    if ( itr >= control->cm_solver_max_iters  )
     {
-        fprintf( stderr, "SDM convergence failed!\n" );
-        return i;
+        fprintf( stderr, "[WARNING] SDM convergence failed (%d iters)\n", itr );
+        return itr;
     }
 
-    return i;
+    return itr;
 }
 
 
@@ -1922,8 +1843,8 @@ real condest( const sparse_matrix * const L, const sparse_matrix * const U )
 
     memset( e, 1., N * sizeof(real) );
 
-    tri_solve( L, e, e, LOWER );
-    tri_solve( U, e, e, UPPER );
+    tri_solve( L, e, e, L->n, LOWER );
+    tri_solve( U, e, e, U->n, UPPER );
 
     /* compute 1-norm of vector e */
     c = FABS(e[0]);
diff --git a/sPuReMD/src/lin_alg.h b/sPuReMD/src/lin_alg.h
index e5a468ffb1669e53e638972b82daad9f7fcc07d0..a3148514449e17fa972c4fee57be8ea518c3c100 100644
--- a/sPuReMD/src/lin_alg.h
+++ b/sPuReMD/src/lin_alg.h
@@ -24,28 +24,49 @@
 
 #include "mytypes.h"
 
+typedef enum
+{
+    LOWER = 0,
+    UPPER = 1,
+} TRIANGULARITY;
+
+
+void Transpose( const sparse_matrix * const, sparse_matrix const * );
 
-void Transpose( const sparse_matrix const *, sparse_matrix const * );
 void Transpose_I( sparse_matrix * const );
 
+void tri_solve( const sparse_matrix * const, const real * const,
+        real * const, const int, const TRIANGULARITY );
+
+void tri_solve_level_sched( const sparse_matrix * const,
+        const real * const, real * const, const int,
+        const TRIANGULARITY, int );
+
+void jacobi_iter( const sparse_matrix * const, const real * const,
+        const real * const, real * const, const TRIANGULARITY,
+        const unsigned int );
+
 sparse_matrix * setup_graph_coloring( sparse_matrix * const );
 
 int GMRES( const static_storage * const, const control_params * const,
         simulation_data * const, const sparse_matrix * const,
         const real * const, const real, real * const,
-        const FILE * const, const int );
+        const int );
 
 int GMRES_HouseHolder( const static_storage * const, const control_params * const,
         simulation_data * const, const sparse_matrix * const,
         const real * const, const real, real * const,
-        const FILE * const, const int );
+        const int );
 
-int CG( static_storage*, sparse_matrix*,
-        real*, real, real*, FILE* );
+int CG( const static_storage * const, const control_params * const,
+        const sparse_matrix * const, const real * const, const real,
+        real * const, const int );
 
-int SDM( static_storage*, sparse_matrix*,
-         real*, real, real*, FILE* );
+int SDM( const static_storage * const, const control_params * const,
+        const sparse_matrix * const, const real * const, const real,
+        real * const, const int );
 
 real condest( const sparse_matrix * const, const sparse_matrix * const );
 
+
 #endif
diff --git a/sPuReMD/src/mytypes.h b/sPuReMD/src/mytypes.h
index fcbc5502da4acabdfe648f752bf8db7b2f8030b1..3833dff83359a5575750d38ec9c4d922f33b3479 100644
--- a/sPuReMD/src/mytypes.h
+++ b/sPuReMD/src/mytypes.h
@@ -116,9 +116,6 @@
 #define MAX_dT              4.00
 #define MIN_dT              0.00
 
-#define MAX_ITR             10
-#define RESTART             50
-
 #define ZERO           0.000000000000000e+00
 #define ALMOST_ZERO    1e-10
 #define NEG_INF       -1e10
@@ -197,6 +194,11 @@ enum geo_formats
     CUSTOM = 0, PDB = 1, BGF = 2, ASCII_RESTART = 3, BINARY_RESTART = 4, GF_N = 5,
 };
 
+enum charge_method
+{
+    QEQ_CM = 0, EE_CM = 1, ACKS2_CM = 2,
+};
+
 enum solver
 {
     GMRES_S = 0, GMRES_H_S = 1, CG_S = 2, SDM_S = 3,
@@ -204,16 +206,16 @@ enum solver
 
 enum pre_comp
 {
-    DIAG_PC = 0, ICHOLT_PC = 1, ILU_PAR_PC = 2, ILUT_PAR_PC = 3, ILU_SUPERLU_MT_PC = 4,
+    NONE_PC = 0, DIAG_PC = 1, ICHOLT_PC = 2, ILU_PAR_PC = 3, ILUT_PAR_PC = 4, ILU_SUPERLU_MT_PC = 5,
 };
 
 enum pre_app
 {
-    NONE_PA = 0, TRI_SOLVE_PA = 1, TRI_SOLVE_LEVEL_SCHED_PA = 2, TRI_SOLVE_GC_PA = 3, JACOBI_ITER_PA = 4,
+    TRI_SOLVE_PA = 0, TRI_SOLVE_LEVEL_SCHED_PA = 1, TRI_SOLVE_GC_PA = 2, JACOBI_ITER_PA = 3,
 };
 
 
-/* Global params mapping */
+/* Force field global params mapping */
 /*
 l[0]  = p_boc1
 l[1]  = p_boc2
@@ -249,7 +251,7 @@ l[30] = p_coa4
 l[31] = p_ovun4
 l[32] = p_ovun3
 l[33] = p_val8
-l[34] = N/A
+l[34] = ACKS2 bond softness
 l[35] = N/A
 l[36] = N/A
 l[37] = version number
@@ -296,6 +298,7 @@ typedef struct
     real b_o_131;
     real b_o_132;
     real b_o_133;
+    real b_s_acks2; /* bond softness for ACKS2 */
 
     /* Line four in the field file */
     real p_ovun2;
@@ -454,10 +457,17 @@ typedef struct
 
 typedef struct
 {
+    /* number of atoms */
     int N;
+    /* dimension of the N x N sparse charge method matrix H */
+    int N_cm;
+    /* atom info */
     reax_atom *atoms;
+    /* atomic interaction parameters */
     reax_interaction reaxprm;
+    /* simulation space (a.k.a. box) parameters */
     simulation_box box;
+    /* grid structure used for binning atoms and tracking neighboring bins */
     grid g;
 } reax_system;
 
@@ -517,16 +527,20 @@ typedef struct
     int freq_diffusion_coef;
     int restrict_type;
 
-    unsigned int qeq_solver_type;
-    real qeq_solver_q_err;
-    real qeq_domain_sparsity;
-    unsigned int qeq_domain_sparsify_enabled;
-    unsigned int pre_comp_type;
-    unsigned int pre_comp_refactor;
-    real pre_comp_droptol;
-    unsigned int pre_comp_sweeps;
-    unsigned int pre_app_type;
-    unsigned int pre_app_jacobi_iters;
+    unsigned int charge_method;
+    unsigned int cm_solver_type;
+    real cm_q_net;
+    unsigned int cm_solver_max_iters;
+    unsigned int cm_solver_restart;
+    real cm_solver_q_err;
+    real cm_domain_sparsity;
+    unsigned int cm_domain_sparsify_enabled;
+    unsigned int cm_solver_pre_comp_type;
+    unsigned int cm_solver_pre_comp_refactor;
+    real cm_solver_pre_comp_droptol;
+    unsigned int cm_solver_pre_comp_sweeps;
+    unsigned int cm_solver_pre_app_type;
+    unsigned int cm_solver_pre_app_jacobi_iters;
 
     int molec_anal;
     int freq_molec_anal;
@@ -586,15 +600,15 @@ typedef struct
     real init_forces;
     real bonded;
     real nonb;
-    real QEq;
-    real QEq_sort_mat_rows;
-    real pre_comp;
-    real pre_app;
-    int solver_iters;
-    real solver_spmv;
-    real solver_vector_ops;
-    real solver_orthog;
-    real solver_tri_solve;
+    real cm;
+    real cm_sort_mat_rows;
+    real cm_solver_pre_comp;
+    real cm_solver_pre_app;
+    int cm_solver_iters;
+    real cm_solver_spmv;
+    real cm_solver_vector_ops;
+    real cm_solver_orthog;
+    real cm_solver_tri_solve;
 } reax_timing;
 
 
@@ -768,7 +782,7 @@ typedef struct
     real *nlp, *nlp_temp, *Clp, *vlpex;
     rvec *dDeltap_self;
 
-    /* QEq storage */
+    /* charge method storage */
     sparse_matrix *H, *H_sp, *L, *U;
     real *droptol;
     real *w;
diff --git a/sPuReMD/src/neighbors.c b/sPuReMD/src/neighbors.c
index fc318ef2d7d7022fc97df29548017299cd1f5e63..1208c826606e61bf912d3623a9d4011eb95f99ee 100644
--- a/sPuReMD/src/neighbors.c
+++ b/sPuReMD/src/neighbors.c
@@ -390,7 +390,7 @@ void Generate_Neighbor_Lists( reax_system *system, control_params *control,
     // fprintf( stderr, "atoms sorted - " );
 
 #ifdef REORDER_ATOMS
-    Cluster_Atoms( system, workspace );
+    Cluster_Atoms( system, workspace, control );
     // fprintf( stderr, "atoms clustered - " );
 #endif
 
diff --git a/sPuReMD/src/print_utils.c b/sPuReMD/src/print_utils.c
index 579ba6290a5c9812cd8b1342f96f959f597d6709..06b7d63dfbf0420a1b062ebc39a6c5bfee0f9234 100644
--- a/sPuReMD/src/print_utils.c
+++ b/sPuReMD/src/print_utils.c
@@ -622,30 +622,30 @@ void Output_Results( reax_system *system, control_params *control,
                  data->timing.init_forces / f_update,
                  data->timing.bonded / f_update,
                  data->timing.nonb / f_update,
-                 data->timing.QEq / f_update,
-                 data->timing.QEq_sort_mat_rows / f_update,
-                 (double)data->timing.solver_iters / f_update,
-                 data->timing.pre_comp / f_update,
-                 data->timing.pre_app / f_update,
-                 data->timing.solver_spmv / f_update,
-                 data->timing.solver_vector_ops / f_update,
-                 data->timing.solver_orthog / f_update,
-                 data->timing.solver_tri_solve / f_update );
+                 data->timing.cm / f_update,
+                 data->timing.cm_sort_mat_rows / f_update,
+                 (double)data->timing.cm_solver_iters / f_update,
+                 data->timing.cm_solver_pre_comp / f_update,
+                 data->timing.cm_solver_pre_app / f_update,
+                 data->timing.cm_solver_spmv / f_update,
+                 data->timing.cm_solver_vector_ops / f_update,
+                 data->timing.cm_solver_orthog / f_update,
+                 data->timing.cm_solver_tri_solve / f_update );
 
         data->timing.total = Get_Time( );
         data->timing.nbrs = 0;
         data->timing.init_forces = 0;
         data->timing.bonded = 0;
         data->timing.nonb = 0;
-        data->timing.QEq = ZERO;
-        data->timing.QEq_sort_mat_rows = ZERO;
-        data->timing.pre_comp = ZERO;
-        data->timing.pre_app = ZERO;
-        data->timing.solver_iters = 0;
-        data->timing.solver_spmv = ZERO;
-        data->timing.solver_vector_ops = ZERO;
-        data->timing.solver_orthog = ZERO;
-        data->timing.solver_tri_solve = ZERO;
+        data->timing.cm = ZERO;
+        data->timing.cm_sort_mat_rows = ZERO;
+        data->timing.cm_solver_pre_comp = ZERO;
+        data->timing.cm_solver_pre_app = ZERO;
+        data->timing.cm_solver_iters = 0;
+        data->timing.cm_solver_spmv = ZERO;
+        data->timing.cm_solver_vector_ops = ZERO;
+        data->timing.cm_solver_orthog = ZERO;
+        data->timing.cm_solver_tri_solve = ZERO;
 
         fflush( out_control->out );
         fflush( out_control->pot );
@@ -694,17 +694,17 @@ void Output_Results( reax_system *system, control_params *control,
 
 
 void Print_Linear_System( reax_system *system, control_params *control,
-                          static_storage *workspace, int step )
+        static_storage *workspace, int step )
 {
-    int   i, j;
-    char  fname[100];
+    int i, j;
+    char fname[100];
     sparse_matrix *H;
     FILE *out;
 
     sprintf( fname, "%s.state%d.out", control->sim_name, step );
     out = fopen( fname, "w" );
 
-    for ( i = 0; i < system->N; i++ )
+    for ( i = 0; i < system->N_cm; i++ )
         fprintf( out, "%6d%2d%24.15e%24.15e%24.15e%24.15e%24.15e%24.15e%24.15e\n",
                  workspace->orig_id[i], system->atoms[i].type,
                  system->atoms[i].x[0], system->atoms[i].x[1],
@@ -719,12 +719,11 @@ void Print_Linear_System( reax_system *system, control_params *control,
     // fprintf( out, "%g\n", workspace->s_t[i+system->N] );
     // fclose( out );
 
-
     sprintf( fname, "%s.H%d.out", control->sim_name, step );
     out = fopen( fname, "w" );
     H = workspace->H;
 
-    for ( i = 0; i < system->N; ++i )
+    for ( i = 0; i < system->N_cm; ++i )
     {
         for ( j = H->start[i]; j < H->start[i + 1] - 1; ++j )
         {
@@ -747,7 +746,7 @@ void Print_Linear_System( reax_system *system, control_params *control,
     out = fopen( fname, "w" );
     H = workspace->H_sp;
 
-    for ( i = 0; i < system->N; ++i )
+    for ( i = 0; i < system->N_cm; ++i )
     {
         for ( j = H->start[i]; j < H->start[i + 1] - 1; ++j )
         {
@@ -828,10 +827,19 @@ void Print_Sparse_Matrix( sparse_matrix *A )
 }
 
 
-void Print_Sparse_Matrix2( sparse_matrix *A, char *fname )
+void Print_Sparse_Matrix2( sparse_matrix *A, char *fname, char *mode )
 {
     int i, j;
-    FILE *f = fopen( fname, "w" );
+    FILE *f;
+   
+    if ( mode == NULL )
+    {
+        f = fopen( fname, "w" );
+    }
+    else
+    {
+        f = fopen( fname, mode );
+    }
 
     for ( i = 0; i < A->n; ++i )
     {
@@ -839,7 +847,44 @@ void Print_Sparse_Matrix2( sparse_matrix *A, char *fname )
         {
             //fprintf( f, "%d%d %.15e\n", A->entries[j].j, i, A->entries[j].val );
             //Convert 0-based to 1-based (for Matlab)
-            fprintf( f, "%6d%6d %24.15e\n", i+1, A->j[j]+1, A->val[j] );
+            fprintf( f, "%6d %6d %24.15e\n", i+1, A->j[j]+1, A->val[j] );
+        }
+    }
+
+    fclose(f);
+}
+
+
+/* Note: watch out for portability issues with endianness
+ * due to serialization of numeric types (integer, IEEE 754) */
+void Print_Sparse_Matrix_Binary( sparse_matrix *A, char *fname )
+{
+    int i, j, temp;
+    FILE *f;
+   
+    f = fopen( fname, "wb" );
+
+    /* header: # rows, # nonzeros */
+    fwrite( &(A->n), sizeof(unsigned int), 1, f );
+    fwrite( &(A->start[A->n]), sizeof(unsigned int), 1, f );
+
+    /* row pointers */
+    for ( i = 0; i <= A->n; ++i )
+    {
+        //Convert 0-based to 1-based (for Matlab)
+        temp = A->start[i] + 1;
+        fwrite( &temp, sizeof(unsigned int), 1, f );
+    }
+
+    /* column indices and non-zeros */
+    for ( i = 0; i <= A->n; ++i )
+    {
+        for ( j = A->start[i]; j < A->start[i + 1]; ++j )
+        {
+            //Convert 0-based to 1-based (for Matlab)
+            temp = A->j[j] + 1;
+            fwrite( &temp, sizeof(unsigned int), 1, f );
+            fwrite( &(A->val[j]), sizeof(real), 1, f );
         }
     }
 
diff --git a/sPuReMD/src/print_utils.h b/sPuReMD/src/print_utils.h
index 8b3b363571ca5b7c50195b4c91bca8951c1caa7b..8c15ebbe81487eabf2a5db13627eef60ee8432d3 100644
--- a/sPuReMD/src/print_utils.h
+++ b/sPuReMD/src/print_utils.h
@@ -55,7 +55,9 @@ void Print_Soln( static_storage*, real*, real*, real*, int );
 
 void Print_Sparse_Matrix( sparse_matrix* );
 
-void Print_Sparse_Matrix2( sparse_matrix*, char* );
+void Print_Sparse_Matrix2( sparse_matrix*, char*, char* );
+
+void Print_Sparse_Matrix_Binary( sparse_matrix*, char* );
 
 void Print_Bonds( reax_system*, list*, char* );
 void Print_Bond_List2( reax_system*, list*, char* );
diff --git a/sPuReMD/src/testmd.c b/sPuReMD/src/testmd.c
index c4c6645375434287bc670b0317ed116254502d46..9ff007a91b77a1844d10d43cf045ca2e3ba91b3a 100644
--- a/sPuReMD/src/testmd.c
+++ b/sPuReMD/src/testmd.c
@@ -47,7 +47,7 @@ static void Post_Evolve( reax_system * const system,
     /* if velocity dependent force then
        {
        Generate_Neighbor_Lists( &system, &control, &lists );
-       QEq(system, control, workspace, lists[FAR_NBRS]);
+       Compute_Charges(system, control, workspace, lists[FAR_NBRS]);
        Introduce compute_force here if we are using velocity dependent forces
        Compute_Forces(system,control,data,workspace,lists);
        } */
@@ -176,8 +176,8 @@ int main(int argc, char* argv[])
     /* compute f_0 */
     //if( control.restart == 0 ) {
     Reset( &system, &control, &data, &workspace, &lists );
-    Generate_Neighbor_Lists( &system, &control, &data, &workspace,
-                             &lists, &out_control );
+    Generate_Neighbor_Lists( &system, &control, &data, &workspace, 
+            &lists, &out_control );
 
     //fprintf( stderr, "total: %.2f secs\n", data.timing.nbrs);
     Compute_Forces(&system, &control, &data, &workspace, &lists, &out_control);
@@ -186,8 +186,7 @@ int main(int argc, char* argv[])
     ++data.step;
     //}
     //
-
-
+    
     for ( ; data.step <= control.nsteps; data.step++ )
     {
         if ( control.T_mode )
diff --git a/sPuReMD/src/tool_box.c b/sPuReMD/src/tool_box.c
index 776bb565f9cb21d7f9ef38259f42bc13fca4fb91..cc1da28a9786923260f9eb9bb75251cd6127629a 100644
--- a/sPuReMD/src/tool_box.c
+++ b/sPuReMD/src/tool_box.c
@@ -290,6 +290,8 @@ void Trim_Spaces( char *element )
 /************ from system_props.c *************/
 real Get_Time( )
 {
+    struct timeval tim;
+
     gettimeofday(&tim, NULL );
     return ( tim.tv_sec + (tim.tv_usec / 1000000.0) );
 }
@@ -297,6 +299,9 @@ real Get_Time( )
 
 real Get_Timing_Info( real t_start )
 {
+    struct timeval tim;
+    real t_end;
+
     gettimeofday(&tim, NULL );
     t_end = tim.tv_sec + (tim.tv_usec / 1000000.0);
     return (t_end - t_start);
@@ -305,6 +310,9 @@ real Get_Timing_Info( real t_start )
 
 void Update_Timing_Info( real *t_start, real *timing )
 {
+    struct timeval tim;
+    real t_end;
+
     gettimeofday(&tim, NULL );
     t_end = tim.tv_sec + (tim.tv_usec / 1000000.0);
     *timing += (t_end - *t_start);
diff --git a/sPuReMD/src/tool_box.h b/sPuReMD/src/tool_box.h
index 5712152d9f399fd2c92152a64a2e82d2aacc70dc..aec68895612e529ccd8175103ee782c7a49ad10d 100644
--- a/sPuReMD/src/tool_box.h
+++ b/sPuReMD/src/tool_box.h
@@ -24,9 +24,6 @@
 
 #include "mytypes.h"
 
-struct timeval tim;
-real t_end;
-
 /* from box.h */
 void Transform( rvec, simulation_box*, char, rvec );
 void Transform_to_UnitBox( rvec, simulation_box*, char, rvec );
diff --git a/sPuReMD/src/traj.c b/sPuReMD/src/traj.c
index 81207a00720ee20143fe066cf939d41e7f244130..f679186d5e543e3e77a5aa9b49de4cb05338c462 100644
--- a/sPuReMD/src/traj.c
+++ b/sPuReMD/src/traj.c
@@ -53,7 +53,7 @@ int Write_Custom_Header(reax_system *system, control_params *control,
              control->bo_cut,
              control->thb_cut,
              control->hb_cut,
-             control->qeq_solver_q_err,
+             control->cm_solver_q_err,
              control->T_init,
              control->T_final,
              control->Tau_T,
diff --git a/sPuReMD/src/vector.c b/sPuReMD/src/vector.c
index ba4a5ea3ce8da6f0b25f1e43a984dc6c8d7e4cb5..5329aea717a6d00b542df5527eb03a6684ec5f18 100644
--- a/sPuReMD/src/vector.c
+++ b/sPuReMD/src/vector.c
@@ -32,13 +32,11 @@ inline int Vector_isZero( const real * const v, const unsigned int k )
 {
     unsigned int i;
 
-    #pragma omp master
+    #pragma omp single
     {
         ret = TRUE;
     }
 
-    #pragma omp barrier
-
     #pragma omp for reduction(&&: ret) schedule(static)
     for ( i = 0; i < k; ++i )
     {
@@ -114,16 +112,19 @@ inline void Vector_Add( real * const dest, const real c, const real * const v, c
 
 
 void Vector_Print( FILE * const fout, const char * const vname, const real * const v,
-                   const unsigned int k )
+        const unsigned int k )
 {
     unsigned int i;
 
-    fprintf( fout, "%s:\n", vname );
+    if ( vname != NULL )
+    {
+        fprintf( fout, "%s:\n", vname );
+    }
+
     for ( i = 0; i < k; ++i )
     {
         fprintf( fout, "%24.15e\n", v[i] );
     }
-    fprintf( fout, "\n" );
 }
 
 
@@ -131,14 +132,11 @@ inline real Dot( const real * const v1, const real * const v2, const unsigned in
 {
     unsigned int i;
 
-    #pragma omp master
+    #pragma omp single
     {
         ret2 = ZERO;
     }
 
-    #pragma omp barrier
-
-
     #pragma omp for reduction(+: ret2) schedule(static)
     for ( i = 0; i < k; ++i )
     {
@@ -153,17 +151,15 @@ inline real Norm( const real * const v1, const unsigned int k )
 {
     unsigned int i;
 
-    #pragma omp master
+    #pragma omp single
     {
         ret2 = ZERO;
     }
 
-    #pragma omp barrier
-
     #pragma omp for reduction(+: ret2) schedule(static)
     for ( i = 0; i < k; ++i )
     {
-        ret2 +=  SQR( v1[i] );
+        ret2 += SQR( v1[i] );
     }
 
     return SQRT( ret2 );
diff --git a/tools/run_sim.py b/tools/run_sim.py
index 3aa4ad5146db95404e6c7a062eac2612fd8c28eb..2ee79c24888d0c54a8a1f5c8da8886824524d549 100644
--- a/tools/run_sim.py
+++ b/tools/run_sim.py
@@ -32,24 +32,32 @@ class TestCase():
                     r'(?P<key>nsteps\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
                 'tabulate_long_range': lambda l, x: sub(
                     r'(?P<key>tabulate_long_range\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'qeq_solver_type': lambda l, x: sub(
-                    r'(?P<key>qeq_solver_type\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'qeq_solver_q_err': lambda l, x: sub(
-                    r'(?P<key>qeq_solver_q_err\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'qeq_domain_sparsity': lambda l, x: sub(
-                    r'(?P<key>qeq_domain_sparsity\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'pre_comp_type': lambda l, x: sub(
-                    r'(?P<key>pre_comp_type\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'pre_comp_droptol': lambda l, x: sub(
-                    r'(?P<key>pre_comp_droptol\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'pre_comp_refactor': lambda l, x: sub(
-                    r'(?P<key>pre_comp_refactor\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'pre_comp_sweeps': lambda l, x: sub(
-                    r'(?P<key>pre_comp_sweeps\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'pre_app_type': lambda l, x: sub(
-                    r'(?P<key>pre_app_type\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
-                'pre_app_jacobi_iters': lambda l, x: sub(
-                    r'(?P<key>pre_app_jacobi_iters\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'charge_method': lambda l, x: sub(
+                    r'(?P<key>charge_method\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_q_net': lambda l, x: sub(
+                    r'(?P<key>cm_q_net\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_type': lambda l, x: sub(
+                    r'(?P<key>cm_solver_type\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_max_iters': lambda l, x: sub(
+                    r'(?P<key>cm_solver_max_iters\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_restart': lambda l, x: sub(
+                    r'(?P<key>cm_solver_restart\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_q_err': lambda l, x: sub(
+                    r'(?P<key>cm_solver_q_err\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_domain_sparsity': lambda l, x: sub(
+                    r'(?P<key>cm_domain_sparsity\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_pre_comp_type': lambda l, x: sub(
+                    r'(?P<key>cm_solver_pre_comp_type\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_pre_comp_droptol': lambda l, x: sub(
+                    r'(?P<key>cm_solver_pre_comp_droptol\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_pre_comp_refactor': lambda l, x: sub(
+                    r'(?P<key>cm_solver_pre_comp_refactor\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_pre_comp_sweeps': lambda l, x: sub(
+                    r'(?P<key>cm_solver_pre_comp_sweeps\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_pre_app_type': lambda l, x: sub(
+                    r'(?P<key>cm_solver_pre_app_type\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
+                'cm_solver_pre_app_jacobi_iters': lambda l, x: sub(
+                    r'(?P<key>cm_solver_pre_app_jacobi_iters\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
                 'geo_format': lambda l, x: sub(
                     r'(?P<key>geo_format\s+)\S+(?P<comment>.*)', r'\g<key>%s\g<comment>' % x, l), \
         }
@@ -88,15 +96,16 @@ class TestCase():
         for p in product(*[self.__params[k] for k in self.__param_names]):
             param_dict = dict((k, v) for (k, v) in zip(self.__param_names, p))
             param_dict['name'] = path.basename(self.__geo_file).split('.')[0] \
+                + '_cm' + param_dict['charge_method'] \
                 + '_s' + param_dict['nsteps'] \
-		+ '_q' + param_dict['qeq_solver_type'] \
- 		+ '_qtol' + param_dict['qeq_solver_q_err'] \
- 		+ '_qds' + param_dict['qeq_domain_sparsity'] \
-                + '_pc' + param_dict['pre_comp_type'] \
-                + '_pctol' + param_dict['pre_comp_droptol'] \
-                + '_pcs' + param_dict['pre_comp_sweeps'] \
-                + '_pa' + param_dict['pre_app_type'] \
-                + '_paji' + param_dict['pre_app_jacobi_iters'] \
+		+ '_q' + param_dict['cm_solver_type'] \
+ 		+ '_qtol' + param_dict['cm_solver_q_err'] \
+ 		+ '_qds' + param_dict['cm_domain_sparsity'] \
+                + '_pc' + param_dict['cm_solver_pre_comp_type'] \
+                + '_pctol' + param_dict['cm_solver_pre_comp_droptol'] \
+                + '_pcs' + param_dict['cm_solver_pre_comp_sweeps'] \
+                + '_pa' + param_dict['cm_solver_pre_app_type'] \
+                + '_paji' + param_dict['cm_solver_pre_app_jacobi_iters'] \
 		+ '_t' + param_dict['threads']
 
 
@@ -128,7 +137,7 @@ class TestCase():
 
     def _process_result(self, fout, param):
         time = 0.
-        qeq = 0.
+        cm = 0.
         iters = 0.
         pre_comp = 0.
         pre_app = 0.
@@ -143,7 +152,7 @@ class TestCase():
             for line in fp:
                 line = line.split()
                 try:
-                    qeq = qeq + float(line[6])
+                    cm = cm + float(line[6])
                     iters = iters + float(line[8])
                     pre_comp = pre_comp + float(line[9])
                     pre_app = pre_app + float(line[10])
@@ -159,7 +168,7 @@ class TestCase():
                         pass
             cnt = cnt - 1
             if cnt > 0:
-                qeq = qeq / cnt
+                cm = cm / cnt
                 iters = iters / cnt
                 pre_comp = pre_comp / cnt
                 pre_app = pre_app / cnt
@@ -167,10 +176,10 @@ class TestCase():
 
         if cnt == int(param['nsteps']):
             fout.write(self.__result_body_fmt.format(path.basename(self.__geo_file).split('.')[0], 
-                param['nsteps'], param['qeq_solver_type'], param['qeq_solver_q_err'], param['qeq_domain_sparsity'],
-                param['pre_comp_type'], param['pre_comp_droptol'], param['pre_comp_sweeps'],
-                param['pre_app_type'], param['pre_app_jacobi_iters'], pre_comp, pre_app, iters, spmv,
-                qeq, param['threads'], time))
+                param['nsteps'], param['cm_solver_type'], param['cm_solver_q_err'], param['cm_domain_sparsity'],
+                param['cm_solver_pre_comp_type'], param['cm_solver_pre_comp_droptol'], param['cm_solver_pre_comp_sweeps'],
+                param['cm_solver_pre_app_type'], param['cm_solver_pre_app_jacobi_iters'], pre_comp, pre_app, iters, spmv,
+                cm, param['threads'], time))
         else:
             print('**WARNING: nsteps not correct in file {0}...'.format(log_file))
         fout.flush()
@@ -205,22 +214,26 @@ if __name__ == '__main__':
 
     header_fmt_str = '{:15}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:5}|{:10}|{:10}|{:10}|{:10}|{:10}|{:3}|{:10}\n'
     header_str = ['Data Set', 'Steps', 'QType', 'Q Tol', 'QDS', 'PreCT', 'PreCD', 'PreCS', 'PreAT', 'PreAJ', 'Pre Comp',
-            'Pre App', 'Iters', 'SpMV', 'QEq', 'Thd', 'Time (s)']
+            'Pre App', 'Iters', 'SpMV', 'CM', 'Thd', 'Time (s)']
     body_fmt_str = '{:15} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:5} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:10.3f} {:3} {:10.3f}\n'
 
     params = {
             'ensemble_type': ['0'],
             'nsteps': ['20'],
             'tabulate_long_range': ['0'],
-            'qeq_solver_type': ['0'],
-            'qeq_solver_q_err': ['1e-6'],
-            'qeq_domain_sparsity': ['1.0'],
-            'pre_comp_type': ['2'],
-            'pre_comp_refactor': ['100'],
-            'pre_comp_droptol': ['0.0'],
-            'pre_comp_sweeps': ['3'],
-            'pre_app_type': ['2'],
-            'pre_app_jacobi_iters': ['30'],
+            'charge_method': ['0'],
+            'cm_q_net': ['0.0'],
+            'cm_solver_type': ['0'],
+            'cm_solver_max_iters': ['20'],
+            'cm_solver_restart': ['100'],
+            'cm_solver_q_err': ['1e-6'],
+            'cm_domain_sparsity': ['1.0'],
+            'cm_solver_pre_comp_type': ['2'],
+            'cm_solver_pre_comp_refactor': ['100'],
+            'cm_solver_pre_comp_droptol': ['0.0'],
+            'cm_solver_pre_comp_sweeps': ['3'],
+            'cm_solver_pre_app_type': ['2'],
+            'cm_solver_pre_app_jacobi_iters': ['30'],
             'threads': ['1'],
             'geo_format': [],
     }