From 1f4bb3fb47c86dd9eeb89e4ea2db1c0155e01e99 Mon Sep 17 00:00:00 2001
From: athomps <athomps@f3b2605a-c512-4ea7-a41b-209d697bcdaa>
Date: Fri, 2 Sep 2011 02:40:00 +0000
Subject: [PATCH] Finished fix nphug

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@6919 f3b2605a-c512-4ea7-a41b-209d697bcdaa
---
 src/SHOCK/fix_nphug.cpp | 324 +++++++++++++++++++++++++++++++---------
 src/SHOCK/fix_nphug.h   |  13 +-
 2 files changed, 264 insertions(+), 73 deletions(-)

diff --git a/src/SHOCK/fix_nphug.cpp b/src/SHOCK/fix_nphug.cpp
index 0a2c3cded4..02e744cc9c 100644
--- a/src/SHOCK/fix_nphug.cpp
+++ b/src/SHOCK/fix_nphug.cpp
@@ -11,82 +11,100 @@
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
-/*
+#include "string.h"
+#include "stdlib.h"
+#include "fix_nphug.h"
+#include "modify.h"
+#include "error.h"
+#include "update.h"
+#include "compute.h"
+#include "force.h"
+#include "domain.h"
+#include "group.h"
+#include "math.h"
+#include "memory.h"
+#include "comm.h"
+#include "math.h"
 
-  This fix applies the NPHug Hugoniostat method of Ravelo et al.
+using namespace LAMMPS_NS;
 
-(Ravelo, Holian, Germann, and Lomdahl, PRB 70 014103 (2004))
+enum{ISO,ANISO,TRICLINIC}; // same as fix_nh.cpp
 
-It uses the Nose-Hoover thermostat and barostat (fix_nh.html).
-The Nose-Hoover barostat is used to compress the system 
-to a specified final stress state. This is done either
-hydrostatically (using keyword iso, aniso, or tri) or uniaxially
-(using keywords x, y, or z).  In the hydrostatic case,
-the cell dimensions change dynamically so that the average axial stress
-in all three directions converges towards the specified target value. 
-In the uniaxial case, the chosen cell dimension changes dynamically 
-so that the average
-axial stress in that direction converges towards the target value. The
-other two cell dimensions are kept fixed (zero lateral strain).
+/* ---------------------------------------------------------------------- */
 
-This leads to the following restrictions on the keywords:
+FixNPHug::FixNPHug(LAMMPS *lmp, int narg, char **arg) :
+  FixNH(lmp, narg, arg)
+{
 
-- The specified initial and
-final target pressures must be the same.
+  // extend vector of base-class computes
 
-- Only one of the following keywords may be used:
-iso, aniso, tri, x, y, z, 
+  size_vector += 3;
 
-- The keywords xy, xz, yz may not be used.
+  // turn off deviatoric flag and remove strain energy from vector
 
-- The only admissible value for the couple keyword is xyz,
-which has the same effect as keyword iso
+  deviatoric_flag = 0;
+  size_vector -= 1;
 
-- The drag parameter is proportional to the beta_H and beta_p
-damping coefficients in the Ravelo paper.
+  // use initial state as reference state
 
-- The temp keyword serves only to set the value of tdamp. The initial
-and final target temperatures are ignored. 
+  v0_set = p0_set = e0_set = 0;
 
-- The values of tdamp and pdamp are inversely proportional to the
-coupling rate nu_H and nu_p in the Ravelo paper
+  // check pressure settings
 
-- All other keywords function in the same way. 
+  if (p_start[0] != p_stop[0] ||
+      p_start[1] != p_stop[1] ||  
+      p_start[2] != p_stop[2])
+    error->all("Invalid argument for fix nphug");
 
-*/
+  // uniaxial = 0 means hydrostatic compression
+  // uniaxial = 1 means uniaxial compression
+  //      in x, y, or z (idir = 0, 1, or 2)
 
+  // isotropic hydrostatic compression
 
+  if (pstyle == ISO) {
+    uniaxial = 0;
 
+    // anisotropic compression
 
+  } else if (pstyle == ANISO) {
 
-#include "string.h"
-#include "fix_nphug.h"
-#include "modify.h"
-#include "error.h"
-#include "update.h"
-#include "compute.h"
-#include "force.h"
-#include "domain.h"
+    // anisotropic hydrostatic compression
 
-using namespace LAMMPS_NS;
+    if (p_start[0] == p_start[1] &&  
+	p_start[0] == p_start[2] )
+      uniaxial = 0;
 
-/* ---------------------------------------------------------------------- */
+    // uniaxial compression
 
-FixNPHug::FixNPHug(LAMMPS *lmp, int narg, char **arg) :
-  FixNH(lmp, narg, arg)
-{
-  // Hard-code to use initial state of system
+    else if (p_flag[0] == 1 && p_flag[1] == 0 
+	&& p_flag[2] == 0) {
+      uniaxial = 1;
+      idir = 0;
+    } else if (p_flag[0] == 0 && p_flag[1] == 1 
+	   && p_flag[2] == 0) {
+      uniaxial = 1;
+      idir = 1;
+    } else if (p_flag[0] == 0 && p_flag[1] == 0 
+	       && p_flag[2] == 1) {
+      uniaxial = 1;
+      idir = 2;
 
-  v0_set = p0_set = e0_set = 0;
+    } else error->all("Invalid argument for fix nphug");
+
+    // triclinic hydrostatic compression
 
-  // Hard-code to use z direction
+  } else if (pstyle == TRICLINIC) {
 
-  direction = 2;
-  if (p_flag[0] == 1 || p_flag[1] == 1 ||
-      p_flag[3] == 1 || p_flag[4] == 1 || p_flag[5] == 1)
-    error->all("Only pressure control in z direction to be used with fix nphug");
-  if (p_flag[2] == 0)
-    error->all("Pressure control in z direction must be used with fix nphug");
+    if (p_start[0] == p_start[1] &&  
+	p_start[0] == p_start[2] &&
+	p_start[3] == 0.0 &&  
+	p_start[4] == 0.0 &&  
+	p_start[5] == 0.0 )
+      uniaxial = 0;
+
+    else error->all("Invalid argument for fix nphug");
+  }
 
   if (!tstat_flag)
     error->all("Temperature control must be used with fix nphug");
@@ -190,8 +208,11 @@ void FixNPHug::setup(int vflag)
   } 
 
   if ( p0_set == 0 ) {
-    p0 = p_current[direction];
     p0_set = 1;
+    if (uniaxial == 1)
+      p0 = p_current[idir];
+    else
+      p0 = (p_current[0]+p_current[1]+p_current[2])/3.0;
   }
 
   if ( e0_set == 0 ) {
@@ -199,6 +220,12 @@ void FixNPHug::setup(int vflag)
     e0_set = 1;
   }
 
+  double masstot = group->mass(igroup);
+  rho0 = nktv2p*force->mvv2e*masstot/v0;
+
+  t_target = 0.01;
+
+  pe->addstep(update->ntimestep+1);
 }
 
 /* ----------------------------------------------------------------------
@@ -209,21 +236,9 @@ void FixNPHug::compute_temp_target()
 {
   t_target = t_current + compute_hugoniot();
   ke_target = tdof * boltz * t_target;
-  if (ke_target < 0.0) ke_target = 0.0;
-  
-  // If t_target is very small, need to choose 
-  // more reasonable value for use by barostat and 
-  // thermostat masses. ke_target is left as is.
-
-  if (t_target <= 1.0e-6) {
-    if (strcmp(update->unit_style,"lj") == 0) t0 = 1.0;
-    else t0 = 300.0;
-  }
-  pressure->addstep(update->ntimestep+1);
   pe->addstep(update->ntimestep+1);
 }
 
-
 /* ---------------------------------------------------------------------- */
 
 double FixNPHug::compute_etotal()
@@ -232,7 +247,7 @@ double FixNPHug::compute_etotal()
   epot = pe->compute_scalar();
   if (thermo_energy) epot -= compute_scalar();
   ekin = temperature->compute_scalar();
-  ekin *= 0.5 * temperature->dof * force->boltz;
+  ekin *= 0.5 * tdof * force->boltz;
   etot = epot+ekin;
   return etot;
 }
@@ -249,24 +264,193 @@ double FixNPHug::compute_vol()
 
 /* ----------------------------------------------------------------------
    Computes the deviation of the current point 
-   from the Hugoniot in energy units.
+   from the Hugoniot in temperature units.
 ------------------------------------------------------------------------- */
 
 double FixNPHug::compute_hugoniot()
 {
-  double v, e, p;
+  double v,e,p;
   double dhugo;
   
   e = compute_etotal();
   
   temperature->compute_vector();
-  pressure->compute_vector();
-  p = pressure->vector[direction];
+
+
+  if (uniaxial == 1) {
+    pressure->compute_vector();
+    p = pressure->vector[idir];
+  } else 
+    p = pressure->compute_scalar();
   
   v = compute_vol();
   
   dhugo = (0.5 * (p + p0 ) * ( v0 - v)) / 
     force->nktv2p + e0 - e;
 
+  dhugo /= tdof * boltz;
+
   return dhugo;
 }
+
+/* ----------------------------------------------------------------------
+   Compute shock velocity is distance/time units
+------------------------------------------------------------------------- */
+
+double FixNPHug::compute_us()
+{
+  double v,p;
+  double eps,us;
+  
+  temperature->compute_vector();
+
+  if (uniaxial == 1) {
+    pressure->compute_vector();
+    p = pressure->vector[idir];
+  } else 
+    p = pressure->compute_scalar();
+  
+  v = compute_vol();
+  
+  // Us^2 = (p-p0)/(rho0*eps)
+
+  eps = 1.0 - v/v0;
+  if (eps < 1.0e-10) us = 0.0;
+  else if (p < p0) us = 0.0; 
+  else us = sqrt((p-p0)/(rho0*eps));
+  
+  return us;
+}
+
+/* ----------------------------------------------------------------------
+   Compute particle velocity is distance/time units
+------------------------------------------------------------------------- */
+
+double FixNPHug::compute_up()
+{
+  double v;
+  double eps,us,up;
+  
+  v = compute_vol();
+  us = compute_us();
+
+  // u = eps*Us
+
+  eps = 1.0 - v/v0;
+  up = us*eps;
+
+  return up;
+}
+
+// look for index in local class
+// if index not found, look in base class
+
+double FixNPHug::compute_vector(int n)
+{
+  int ilen;
+
+  // n = 0: Hugoniot energy difference (temperature units)
+
+  ilen = 1;
+  if (n < ilen) return compute_hugoniot();
+  n -= ilen;
+
+  // n = 1: Shock velocity
+
+  ilen = 1;
+  if (n < ilen) return compute_us();
+  n -= ilen;
+
+  // n = 2: Particle velocity
+
+  ilen = 1;
+  if (n < ilen) return compute_up();
+  n -= ilen;
+
+  // index not found, look in base class
+
+  FixNH::compute_vector(n);
+
+}
+
+/* ----------------------------------------------------------------------
+   pack entire state of Fix into one write 
+------------------------------------------------------------------------- */
+
+void FixNPHug::write_restart(FILE *fp)
+{
+  int nsize = 3;
+
+  // Add on the base class size
+
+  int nsizetot = nsize + FixNH::size_restart();
+
+  double *list;
+  memory->create(list,nsize,"nphug:list");
+
+  int n = 0;
+
+  list[n++] = e0;
+  list[n++] = v0;
+  list[n++] = p0;
+
+  if (comm->me == 0) {
+    int sizetot = nsizetot * sizeof(double);
+    fwrite(&sizetot,sizeof(int),1,fp);
+    fwrite(list,sizeof(double),nsize,fp);
+  }
+
+  memory->destroy(list);
+
+  // Write the base class data without size
+
+  FixNH::write_restart_nosize(fp);
+
+}
+
+/* ----------------------------------------------------------------------
+   use state info from restart file to restart the Fix 
+------------------------------------------------------------------------- */
+
+void FixNPHug::restart(char *buf)
+{
+  int n = 0;
+  double *list = (double *) buf;
+  e0 = list[n++];
+  v0 = list[n++];
+  p0 = list[n++];
+
+  e0_set = 1;
+  v0_set = 1;
+  p0_set = 1;
+
+  // Call the base class function
+
+  buf += n*sizeof(double);
+  FixNH::restart(buf);
+
+}
+
+/* ---------------------------------------------------------------------- */
+
+int FixNPHug::modify_param(int narg, char **arg)
+{
+  if (strcmp(arg[0],"e0") == 0) {
+    if (narg < 2) error->all("Illegal fix nphug command");
+    e0 = atof(arg[1]);
+    e0_set = 1;
+    return 2;
+  } else if (strcmp(arg[0],"v0") == 0) {
+    if (narg < 2) error->all("Illegal fix nphug command");
+    v0 = atof(arg[1]);
+    v0_set = 1;
+    return 2;
+  } else if (strcmp(arg[0],"p0") == 0) {
+    if (narg < 2) error->all("Illegal fix nphug command");
+    p0 = atof(arg[1]);
+    p0_set = 1;
+    return 2;
+  }
+
+  return 0;
+}
diff --git a/src/SHOCK/fix_nphug.h b/src/SHOCK/fix_nphug.h
index 37ca8451ea..ee6f5b2ecf 100644
--- a/src/SHOCK/fix_nphug.h
+++ b/src/SHOCK/fix_nphug.h
@@ -30,20 +30,27 @@ class FixNPHug : public FixNH {
   ~FixNPHug();
   void init();
   void setup(int);
-  
+  int modify_param(int, char **);
+  void write_restart(FILE *);
+  void restart(char *);
+ 
  private:
   class Compute *pe;               // PE compute pointer
 
   void compute_temp_target();
+  double compute_vector(int);
   double compute_etotal();
   double compute_vol();
   double compute_hugoniot();
+  double compute_us();
+  double compute_up();
 
   char *id_pe;
   int peflag;
   int v0_set,p0_set,e0_set;
-  double v0,p0,e0;
-  int direction;
+  double v0,p0,e0,rho0;
+  int idir;
+  int uniaxial;
 };
 
 }
-- 
GitLab