ftp.nice.ch/pub/next/science/chemistry/WaterC.s.tar.gz#/WaterC/wengine.c

This is wengine.c in view mode; [Download] [Up]

#include "wstruct.h"
#include "wconst.c"

/*  The engine code. Adapted, optimized, fixed, hassled with, and torqued
		by:	M.L. (Loki) Demsey
			University of Arizona
			Geo Sciences Department
			for and help from: Dr. Denis Norton
			
    Original code, molded in FORTRAN from personal code and code from Haar,
    Gallagher, and Kell by James Johnson
    
    This is the commented-to-death version of the code; it is recommended
    that this be used only for reference and not compilation.
    The user realizes that this code is not supported and may
    be superceded at any moment.
 */

/* **********************************************************************
*
*   specs  - Input unit, triple point, saturation, and option specs:
*
*****        it, id, ip, ih, itripl, isat, iopt, useLVS, epseqn, icrit;
*
*            note that the returned value of isat may differ from
*            its input value and that icrit need not be specified
*            prior to invocation.
*
*
*   states - State variables: 
*
*****          temp, pres, dens(1), dens(2);
*
*            note that the first three of these must be specified prior
*            to invocation and that, in the case of saturation, vapor
*            density is returned in dens(1), liquid in dens(2).
*
*
*   props  - Thermodynamic, transport, electrostatic, and combined 
*            property values:
*
*****        A, G, S, U, H, Cv, Cp, Speed, alpha, beta, diel, visc,
*****        tcond, surten, tdiff, Prndtl, visck, albe, 
*****        ZBorn, YBorn, QBorn, daldT, XBorn
*
*
*   error  - LOGICAL argument that indicates success ("FALSE") or
*            failure ("TRUE") of the call, the latter value in 
*            response to out-of-bounds specs or states variables.
*
********************************************************************** */

void h2o92(specs,states,props,error)
int *error,specs[10];
double states[4],props[46];
{
  extern void unit(),LVSeqn(),HGKeqn(),load(),LVScon(),HGKcon();
  extern int valid(),crtreg();
  extern double TdegUS();
  double Dens[2],tempy;
  int useLVS;
  
  HGKcon();
  LVScon();
  unit(specs[0],specs[1],specs[2],specs[3],specs[4]);
  if (! valid(specs[0],specs[1],specs[2],specs[3],specs[4], &specs[5],specs[6],specs[7],specs[8],states[0],states[1],states[2]))
    { *error = 1;
      return;
    }
  else
    { *error = 0; }
  if ( crtreg(specs[5],specs[6],specs[0],&states[0],&states[1],&states[2]))
    { specs[9] = 1;
      useLVS = (specs[7] == 1);
    }
  else
    { specs[9] = useLVS = 0; }
  if (useLVS)
    { Dens[0] = states[2];
      LVSeqn(&specs[5],&specs[6],specs[4],&states[0],&states[1],Dens,specs[8]);
      Dens[0] /= 1000.0;
      if (specs[5] == 1)
        { Dens[1] /= 1000.0; }
    }
  else
    { Dens[0] = states[2] / 1000.0;
      HGKeqn(&specs[5],specs[6],specs[4],&states[0],&states[1],Dens,specs[8]);
    }
  load(1,wpvals.wprops,props);
  if (specs[5] == 1)
    { tempy = Dens[0];
      Dens[0] = Dens[1];
      Dens[1] = tempy;
      load(2,wpvals.wpliq,props);
    }
  states[0] = TdegUS(specs[0],states[0]);
  states[1] *= units.fp;
  states[2] = Dens[0] / units.fd;
  if (specs[5] == 1)
    { states[3] = Dens[1] / units.fd; }
  return;
}

/* -----------------------------------------------------------------
*** valid - Returns "TRUE" if unit and equation specifications 
*           are valid and input state conditions fall within
*           the HGK equation's region of validity;
*           returns "FALSE" otherwise. */

int valid(it,id,ip,ih,itripl,isat,iopt,useLVS,epseqn,Temp,Pres,Dens)
int it,id,ip,ih,itripl,iopt,useLVS,epseqn,*isat;
double Temp,Pres,Dens;
{  /* note switch from usual return declarations to suit ifs */
  extern int valspc(),valTD(),valTP();
  extern double TdegK();
  double T,D,P,Ttripl,Tcrit,Pcrit;
  int val;

/* ensure validity of input specifications */  
  if (! valspc(it,id,ip,ih,itripl,*isat,iopt,useLVS,epseqn))
      return 0;
/* convert to  degC, bars, g/cm3 */
  T = TdegK(it,Temp) - 273.15;
  D = Dens * units.fd;
  P = (Pres / units.fp) * 10.0;
  Ttripl = tpoint.Ttripl - 273.15;
  Tcrit = crits.Tc - 273.15;
  Pcrit = crits.Pc * 10.0;
  if (*isat == 0)
    { if (iopt == 1)
         val = valTD(T,D,isat,epseqn);
      else
         val = valTP(T,P);
    }
  else
    { if (iopt == 1)
        val = (((T + tolers.FPTOL) >= Ttripl) && ((T - tolers.FPTOL) <= Tcrit));
      else
        val = (((P + tolers.FPTOL) >= tpoint.Ptripl) && ((P - tolers.FPTOL) <= Pcrit));
    }
  return val;
}

/* -----------------------------------------------------------------
*** valspc - Returns "TRUE" if  it, id, ip, ih, itripl, isat, iopt,
*            useLVS, and epseqn values all define valid input;
*            returns "FALSE" otherwise. */
int valspc(it,id,ip,ih,itripl,isat,iopt,useLVS,epseqn)
int it,id,ip,ih,itripl,isat,iopt,useLVS,epseqn;
{
  return ((1 <= it) && (it <= 4) && (1 <= id) && (id <= 4) && (1 <= ip) && (ip <= 5) && (1 <= ih) && (ih <= 6) && (0 <= itripl) && (itripl <= 1) && (0 <= isat) && (isat <= 1) && (1 <= iopt) && (iopt <= 2) && (0 <= useLVS) && (useLVS <= 1) && (1 <= epseqn) && (epseqn <= 5));
}

/* -----------------------------------------------------------------
*** valTD - Returns "TRUE" if  T-D  defines liquid or vapor H2O
*           within validity limits of the HGK equation of state;
*           returns "FALSE" otherwise. */
int valTD(T,D,isat,epseqn)
double T,D;
int *isat;
int epseqn;
{
  extern void pcorr(),denLVS(),bb(),denHGK();
  extern double Pfind(),Psublm();
  int val,istemp;
  double Tk,Tcrit,Ttripl,Dlimit,P,Ps,Dv,Dl,PMPa,Dguess,Dsublm,dPdD;

  if (((T - tolers.FPTOL) > HGKbnd.Ttop) || ((T + tolers.FPTOL) < HGKbnd.Tbtm) || ((D - tolers.FPTOL) > HGKbnd.Dtop) || ((D + tolers.FPTOL) < HGKbnd.Dbtm))
     return 0;
  Tcrit = crits.Tc - 273.15;
  Ttripl = tpoint.Ttripl - 273.15;
  if (((T + tolers.FPTOL) >= Tcrit) || ((T >= liqice.TnIB30) && (D >= tpoint.Dltrip)))
    { Dlimit = liqice.sDIB30 * (T - liqice.TnIB30) + HGKbnd.Dtop;
      val = ((D - tolers.FPTOL) <= Dlimit);
    }
  else
    { if ((D - tolers.FPTOL) <= tpoint.Dltrip)
        { if (T >= Ttripl)
	    { val = 1;
	      Tk = T + 273.15;
	      if (Tk < coefs1.x[0])
	        { RTcurr.rt = aconst.gascon * Tk;
		  pcorr(0,Tk,&Ps,&Dl,&Dv,epseqn);
		}
	      else
	        { istemp = 1;
		  satur.DH2O = 0.0;
		  P = Pfind(istemp,&Tk,&satur.DH2O);
		  denLVS(istemp,&Tk,P);
		  Dv = satur.Dvap / 1000.0;
		  Dl = satur.Dliq / 1000.0;
		}
	      if ((D >= Dv) && (D <= Dl))
	          *isat = 1;
	    }
	  else
	    { P = Psublm(T);
	      PMPa = P / 10.0;
	      Tk = T + 273.15;
	      Dguess = PMPa / Tk / 0.4;
	      RTcurr.rt = aconst.gascon * Tk;
	      bb(Tk);
	      denHGK(&Dsublm,PMPa,Dguess,Tk,&dPdD);
	      val = ((D - tolers.FPTOL) <= Dsublm);
	    }
	}
      else
        { if (D <= liqice.Dli13)
	    { Dlimit = liqice.sDli1 * (T - liqice.Tli13) + liqice.Dli13;
	      val = ((D + tolers.FPTOL) >= Dlimit);
	    }
	  else
	    { Dlimit = liqice.sDli37 * (T - liqice.Tli13) + liqice.Dli13;
	      val = ((D - tolers.FPTOL) <= Dlimit);
	    }
       }
    }
  return val;
}

/* -----------------------------------------------------------------
*** valTP - Returns "TRUE" if  T-P  defines liquid or vapor H2O
*           within validity limits of the HGK equation of state;
*           returns "FALSE" otherwise. */
int valTP(T,P)
double T,P;
{
  int val;
  double Plimit,Psubl;
  extern double Psublm();
  
  if (((T - tolers.FPTOL) > HGKbnd.Ttop) || ((T + tolers.FPTOL) < HGKbnd.Tbtm) || ((P - tolers.FPTOL) > HGKbnd.Ptop) || ((P + tolers.FPTOL) < HGKbnd.Pbtm))
     return 0;
  else
     val = 1;
  if (P >= liqice.Pli13)
    { Plimit = liqice.sPli37 * (T - liqice.Tli13) + liqice.Pli13;
      val = ((P - tolers.FPTOL) <= Plimit);
    }
  else
    { if (P >= tpoint.Ptripl)
        { Plimit = liqice.sPli1 * (T - liqice.Tli13) + liqice.Pli13;
          val = ((P + tolers.FPTOL) >= Plimit);
	}
      else
        { Psubl = Psublm(T);
          val = ((P - tolers.FPTOL) <= Psubl);
        }
    }
  return val;
}

/* -----------------------------------------------------------------
*** Psublm - Returns  Psublimation(T)  computed from the 
*            equation given by  Washburn (1924): Monthly
*            Weather Rev., v.52, pp.488-490. */
double Psublm(Temp)
double Temp;
{
  double T,PmmHg;
  
  T = Temp + 273.1;
  PmmHg = pow(10.0, (-2445.5646/T + 8.2312*log10(T) - 0.01677006*T + 0.0000120514*T*T - 6.757169));
  return (PmmHg * 0.00133322);
/* converted from mmHg to bars */
}

/* -----------------------------------------------------------------
*** unit - Sets internal parameters according to user-specified 
*          choice of units.  Internal program units are degK(T),
*          and gm/cm**3(D); all other properties are computed in
*          dimensionless form and dimensioned at output time.
*          NOTE:  conversion factors for j/g ---> cal/(g,mole)
*          (ffh [3 & 4]) are consistent with those given in 
*          Table 1, Helgeson & Kirkham (1974a) for thermal calories, 
*          and differ slightly with those given by Haar et al (1984) 
*          for international calories. */
void unit(it,id,ip,ih,itripl)
int it,id,ip,ih,itripl;
{
  extern void tpset();
  double fft[4] = {1.0,1.0,0.555555556,0.555555556};
  double ffd[4] = {0.001,1.0,0.0180152,0.016018};
  double ffvd[4] = {1.0,10.0,0.555086816,0.671968969};
  double ffvk[4] = {1.0,10000.0,10000.0,10.76391042};
  double ffs[4] = {1.0,100.0,100.0,3.280833};
  double ffp[5] = {1.0,10.0,9.86923266716,145.038,10.1971};
  double ffh[6] = {1.0,1.0,18.0152,0.23901,4.305816,0.4299226};
  double ffst[4] = {1.0,1000.0,55.5086816,2.205061};
  double ffcd[4] = {1.0,0.01,0.01,0.3048};
  double ffch[6] = {0.001,1.0,1.0,0.23901,0.23901,0.000947244};

  units.ft = fft[it-1];
  units.fd = ffd[id-1];
  units.fvd = ffvd[id-1];
  units.fvk = ffvk[id-1];
  units.fs = ffs[id-1];
  units.fp = ffp[ip-1];
  units.fh = ffh[ih-1];
  units.fst = ffst[id-1];
  units.fc = ffcd[id-1] * ffch[ih-1];
  if (itripl == 1)
    tpset();
  return;
}

/* -----------------------------------------------------------------
*** crtreg - Returns "TRUE" if input state conditions fall within 
*            the critical region of H2O; otherwise returns "FALSE".
*            T, P, D, input in user-specified units, are returned in
*            degK, MPa, kg/m3. */
int crtreg(isat,iopt,it,T,P,D)
int isat,iopt,it;
double *T,*P,*D;
{
  int llim,ulim,val,isat1;
  double Pmin,Pmax,ddummy,Pstest;
  extern double Pfind();
  
  *T = TdegK(it,*T);
  if (isat == 0)
    { if (iopt == 1)
        { *D *= units.fd * 1000.0;
	  val = ((*T >= coefs1.x[0]) && (*T <= coefs1.x[2]) && (*D >= coefs1.x[3]) && (*D <= coefs1.x[4]));
	}
      else 
        { *P /= units.fp;
	  if ((*T < coefs1.x[0]) || (*T > coefs1.x[2]))
	    val = 0;
	  else
	    { Pmin = coefs1.x[5] + coefs1.x[9] * (*T - coefs1.x[0]);
	      Pmax = coefs1.x[6] + coefs1.x[10] * (*T - coefs1.x[1]);
	      llim = (*P >= Pmin);
	      ulim = (*P <= Pmax);
	      if (llim && ulim)
	        val = 1;
	      else
	        { if (llim && (*T <= coefs1.x[1]))
		    { isat1 = 1;
		      ddummy = 0.0;
		      Pstest = Pfind(isat1,T,&ddummy);
		      val = (*P <= Pstest);
		    }
		  else
		      val = 0;
	        }
	    }
         }
    }
  else
    { if (iopt == 1)
        val = (*T >= coefs1.x[0]);
      else
        { *P /= units.fp;
	  val = (*P >= coefs1.x[5]);
	}
    }
 return val;
}
 
/* -----------------------------------------------------------------
*** HGKeqn - Computes thermodynamic and transport properties of 
*            of H2O from the equation of state given by  
*            Haar, Gallagher, & Kell (1984). */
void HGKeqn(isat,iopt,itripl,Temp,Pres,Dens,epseqn)
int *isat,iopt,itripl,epseqn;
double *Temp,*Pres,Dens[2];
{
  int i;
  extern void bb(),calcv3(),thmHGK(),dimHGK();

  RTcurr.rt = aconst.gascon * *Temp;
  HGKsat(isat,iopt,itripl,Temp,Pres,Dens,epseqn);
  if (*isat == 0)
    { bb(*Temp);
      calcv3(iopt,itripl,*Temp,Pres,&Dens[0],epseqn);
      thmHGK(Dens[0],*Temp);
      dimHGK(*isat,itripl,*Temp,*Pres,Dens[0],epseqn);
    }
  else
    { for (i=0;i < 23;i++)
        wpvals.wpliq[i] = wpvals.wprops[i];
      dimHGK(2,itripl,*Temp,*Pres,Dens[1],epseqn);
    }
  return;
}
  
/* -----------------------------------------------------------------
*** HGKsat - If  isat=1, computes  Psat(T) or Tsat(P) (iopt=1,2),
*            liquid and vapor densities, and associated
*            thermodynamic and transport properties.
*            If  isat=0, checks whether  T-D or T-P (iopt=1,2)
*            falls on or within  TOL  of the liquid-vapor 
*            surface; if so, sets isat <- 1 and computes 
*            properties. */
void HGKsat(isat,iopt,itripl,Temp,Pres,Dens,epseqn)
int iopt,itripl,epseqn,*isat;
double *Temp,*Pres,Dens[2];
{
  double dltemp,dvtemp,Ptemp;
  extern double mfabs();
  extern void pcorr(),tcorr();

  if (*isat == 1)
    { if (iopt == 1)
        pcorr(itripl,*Temp,Pres,&Dens[0],&Dens[1],epseqn);
      else
        tcorr(itripl,Temp,*Pres,&Dens[0],&Dens[1],epseqn);
    }
  else
    { if ((*Temp > crits.Tc) || (*Temp < tpoint.Ttripl) || ((iopt == 2) && (*Pres > crits.Pc)))
        return;
      else
        { pcorr(itripl,*Temp,&Ptemp,&dltemp,&dvtemp,epseqn);
	  if (((iopt == 2) && (mfabs(*Pres-Ptemp) <= tolers.PTOL)) || ((iopt == 1) && ((mfabs(Dens[0] - dltemp) <= tolers.DTOL) || (mfabs(Dens[0] - dvtemp) <= tolers.DTOL))))
	    { *isat = 1;
	      *Pres = Ptemp;
	      Dens[0] = dltemp;
	      Dens[1] = dvtemp;
	    }
	}
     }
  return;
}

/* -----------------------------------------------------------------
*** calcv3 - Compute the dependent state variable. */
void calcv3(iopt,itripl,Temp,Pres,Dens,epseqn)
int iopt,itripl,epseqn;
double Temp,*Pres,*Dens;
{
  double ps,dll,dvv,dguess;
  extern void pcorr(),resid(),base(),ideal();

  if (iopt == 1)
    { resid(Temp,*Dens);
      base(*Dens,Temp);
      ideal(Temp);
      *Pres = RTcurr.rt * *Dens * aconst.zb + qqqq.q;
    }
  else
    { if (Temp < aconst.tz)
        pcorr(itripl,Temp,&ps,&dll,&dvv,epseqn);
      else
        { ps = 20000.0;
	  dll = 0.0;
	}
      if (*Pres > ps)
         dguess = dll;
      else
         dguess = *Pres / Temp / 0.4;
      denHGK(Dens,*Pres,dguess,Temp,&fcts.dpdd);
      ideal(Temp);
    }
  return;
}

/* -----------------------------------------------------------------
*** thmHGK - Computes thermodynamic functions in dimensionless
*            units from the HGK equation of state:  Helmholtz, Gibbs, 
*            internal energy, and enthalpy functions (ad, gd, ud, hd) are 
*            per RT; entropy and heat capacities (sd, cvd, cpd) are per R. */
void thmHGK(d,t)
double d,t;
{
  double z;

  z = aconst.zb + qqqq.q/RTcurr.rt/d;
  fcts.dpdd = RTcurr.rt * (aconst.zb + aconst.yb * aconst.dzb) + qqqq.q5;
  fcts.ad = basef.ab + resf.ar + idf.ai - aconst.uref/t + aconst.sref;
  fcts.gd = fcts.ad + z;
  fcts.ud = basef.ub + resf.ur + idf.ui - aconst.uref/t;
  fcts.dpdt = RTcurr.rt * d * basef.dpdtb + resf.dpdtr;
  fcts.cvd = basef.cvb + resf.cvr + idf.cvi;
  fcts.cpd = fcts.cvd + t * fcts.dpdt * fcts.dpdt / (d * d * fcts.dpdd * aconst.gascon);
  fcts.hd = fcts.ud + z;
  fcts.sd = basef.sb + resf.sr + idf.si - aconst.sref;
  fcts.dvdt = fcts.dpdt / fcts.dpdd / d / d;
  fcts.cjtt = 1.0 / d - t * fcts.dvdt;
  fcts.cjth = -fcts.cjtt / fcts.cpd / aconst.gascon;
  return;
}

/* -----------------------------------------------------------------
*** bb - Computes molecular parameters b, the "excluded volume" 
*        (eq A.3), and B, the second virial coefficient (eq A.4),
*        in cm3/g (b1,b2) and their first and second derivatives 
*        with respect to temperature (b1t,b1tt,b2t,b2tt). */
void bb(t)
double t;
{
  double v[10];
  int i;
  
  v[0] = 1.0;
  for (i=1; i < 10; i++)
     v[i] = v[i-1] * aconst.tz / t;
  ellcon.b1 = bconst.bp[0] + bconst.bp[1] * log(1.0 / v[1]);
  ellcon.b2 = bconst.bq[0];
  ellcon.b1t = bconst.bp[1] * v[1] / aconst.tz;
  ellcon.b2t = ellcon.b1tt = ellcon.b2tt = 0.0;
  for (i=2; i < 10; i++)
    { ellcon.b1 += bconst.bp[i] * v[i-1];
      ellcon.b2 += bconst.bq[i] * v[i-1];
      ellcon.b1t -= (i-1) * bconst.bp[i] * v[i-1] / t;
      ellcon.b2t -= (i-1) * bconst.bq[i] * v[i-1] / t;
      ellcon.b1tt += bconst.bp[i] * (i-1) * (i-1) * v[i-1] / t / t;
      ellcon.b2tt += bconst.bq[i] * (i-1) * (i-1) * v[i-1] / t / t;
    }
  ellcon.b1tt -= ellcon.b1t / t;
  ellcon.b2tt -= ellcon.b2t / t;
  return;
}

/* -----------------------------------------------------------------
*** base - Computes Abase, Gbase, Sbase, Ubase, Hbase, Cvbase
*          -- all per RT (dimensionless) --  as well as Pbase & dP/dT
*          -- both per (DRT) -- for the base function (ab, gb, sb, ub,
*          hb, cvb, pb, dpdtb).  See Haar, Gallagher & Kell (1979), eq(1). */
void base(d,t)
double d,t;
{
  double x,z0,dz0,bb2tt;

  aconst.yb = 0.25 * ellcon.b1 * d;
  x = 1.0 - aconst.yb;
  z0 = (1.0 + ellcon.g1 * aconst.yb + ellcon.g2 * aconst.yb * aconst.yb) / (x * x * x);
  aconst.zb = z0 + 4.0 * aconst.yb * (ellcon.b2/ellcon.b1 - ellcon.gf);
  dz0 = (ellcon.g1 + 2.0 * ellcon.g2 * aconst.yb) / (x * x * x) + 3.0 * (1.0 + ellcon.g1 * aconst.yb + ellcon.g2 * aconst.yb * aconst.yb) / (x * x * x * x);
  aconst.dzb = dz0 + 4.0 * (ellcon.b2/ellcon.b1 - ellcon.gf);
  basef.pb = aconst.zb;
  basef.ab = - log(x) - (ellcon.g2 - 1.0)/x + 28.16666667/x/x + 4.0*aconst.yb* (ellcon.b2 /ellcon.b1 - ellcon.gf) + 15.166666667 +log(d*t*aconst.gascon/0.101325);
  basef.gb = basef.ab + aconst.zb;
  basef.ub = -t * ellcon.b1t * (aconst.zb - 1.0 - d * ellcon.b2)/ellcon.b1 - d*t*ellcon.b2t;
  basef.sb = basef.ub - basef.ab;
  basef.hb = aconst.zb + basef.ub;
  bb2tt = t * t * ellcon.b2tt;
  basef.cvb = 2.0 * basef.ub + (z0 - 1.0)*(((t*ellcon.b1t/ellcon.b1)* (t*ellcon.b1t/ellcon.b1)) - t*t*ellcon.b1tt/ellcon.b1) - d*(bb2tt - ellcon.gf* ellcon.b1tt*t*t) - (t*ellcon.b1t/ellcon.b1)*(t*ellcon.b1t/ ellcon.b1)*aconst.yb*dz0;
  basef.dpdtb = basef.pb/t + d*(aconst.dzb*ellcon.b1t/4.0 + ellcon.b2t - ellcon.b2 /ellcon.b1 *ellcon.b1t);
  return;
}

/* -----------------------------------------------------------------
*** resid - Computes residual contributions to pressure (q), the 
*           Helmloltz function (ar) , dP/dD (q5), the Gibbs function 
*           (gr), entropy (sr), internal energy (ur), enthalpy (hr), 
*           isochoric heat capacity (cvr), and dP/dT.  The first 36 
*           terms of the residual function represent a global
*           least-squares fit to experimental data outside the 
*           critical region, terms 37-39 affect only the immediate
*           vicinity of the critical point, and the last term (40)
*           contributes only in the high pressure, low temperature
*           region. */
void resid(t,d)
double t,d;
{
  int i,k,l,km,zz;
  double dadt,e,q10,q20,v,dfdt,d2f,dpt,q2a,ddz,del,ex1,dex,tex;
  double att,tx,tau,ex2,qm,qp,fct,q5t,qr[11],qt[10];
  
  qr[0] = qqqq.q5 = qqqq.q = resf.ar = dadt = resf.cvr = resf.dpdtr = 0.0;
  e = exp(-aconst.aa * d);
  qr[1] = q10 = d * d * e;
  q20 = 1.0 - e;
  v = aconst.tz / t;
  qt[0] = t / aconst.tz;
  for (i=1;i<10;i++)
    { qr[i+1] = qr[i] * q20;
      qt[i] = qt[i-1] * v;
    }
  for (i=0;i<nconst.n;i++)
    { k = nconst.ii[i] + 1;
      l = nconst.jj[i];
      zz = k;
      if (k == 1)
         qp = nconst.g[i] * aconst.aa * qr[1] * qt[l];
      else
         qp = nconst.g[i] * aconst.aa * qr[k] * qt[l];
      qqqq.q += qp;
      qqqq.q5 += aconst.aa*(2.0/d - aconst.aa*(1.0 - e*(k-1)/q20))*qp;
      resf.ar += nconst.g[i] * qr[k+1] * qt[l] / q10 / zz / RTcurr.rt;
      dfdt = pow(q20,(double) k) * (1-l) * qt[l+1] / aconst.tz / k;
      d2f = l * dfdt;
      dpt = dfdt * q10 * aconst.aa * k / q20;
      dadt += nconst.g[i] * dfdt;
      resf.dpdtr += nconst.g[i] * dpt;
      resf.cvr += nconst.g[i] * d2f / aconst.gascon;
    }
  qp = q2a = 0.0;
  for (i=36;i<40;i++)
    { if (nconst.g[i] != 0.0)
        { k = nconst.ii[i];
	  km = nconst.jj[i];
	  ddz = addcon.adz[i-36];
	  del = d / ddz - 1.0;
	  if (mfabs(del) < 0.0000000001)
	    del = 0.0000000001;
	  ex1 = -addcon.aad[i-36] * pow(del,(double) k);
	  if (ex1 < tolers.EXPTOL)
	     dex = 0.0;
	  else
	     dex = exp(ex1) * pow(del,(double) km);
	  att = addcon.aat[i-36];
	  tx = addcon.atz[i-36];
	  tau = t / tx - 1.0;
	  ex2 = -att * tau * tau;
	  if (ex2 < tolers.EXPTOL)
	     tex = 0.0;
	  else
	     tex = exp(ex2);
	  q10 = dex * tex;
	  qm = km / del - k * addcon.aad[i-36] * pow(del,(double) (k-1));
	  fct = qm * d * d * q10 / ddz;
	  q5t = fct * (2.0 / d + qm / ddz) - (d / ddz) * (d / ddz) * q10 * (km / del / del + k*(k-1)*addcon.aad[i-36] * pow(del,(double) (k-2)));
	  qqqq.q5 += q5t * nconst.g[i];
	  qp += nconst.g[i] * fct;
	  dadt -= 2.0 * nconst.g[i] * att * tau * q10 / tx;
	  resf.dpdtr -= 2.0 * nconst.g[i] * att * tau * fct / tx;
	  q2a += t * nconst.g[i] * (4.0 * att * ex2 + 2.0 * att) * q10 / tx / tx;
	  resf.ar += q10 * nconst.g[i] / RTcurr.rt;
	}
    }
  resf.sr = -dadt / aconst.gascon;
  resf.ur = resf.sr + resf.ar;
  resf.cvr += q2a / aconst.gascon;
  qqqq.q += qp;
  return;
}

/* -----------------------------------------------------------------
*** ideal - Computes thermodynamic properties for H2O in the 
*           ideal gas state using equations given by Woolley (1979). */
void ideal(t)
double t;
{
  double tt,tl,emult;
  double c[18]={19.730271018,20.9662681977,-.483429455355, 6.05743189245,22.56023885,-9.87532442,-4.3135538513,.458155781,-.047754901883,.0041238460633,-.00027929052852,.000014481695261,-.00000056473658748,.000000016200446,-.0000000003303822796,.00000000000451916067368,-.0000000000000370734122708,.000000000000000137546068238};
  int i;
  
  tt = t / 100.0;
  tl = log(tt);
  idf.gi = -(c[0]/tt + c[1]) * tl;
  idf.hi = (c[1] + c[0]*(1 - tl)/tt);
  idf.cpi = c[1] - c[0]/tt;
  for (i=2;i<18;i++)
    { emult = pow(tt,(double)(i-5));
      idf.gi -= c[i] * emult;
      idf.hi += c[i] * (i-5) * emult;
      idf.cpi += c[i] * (i-5) * (i-4) * emult;
    }
  idf.ai = idf.gi - 1;
  idf.ui = idf.hi - 1;
  idf.cvi = idf.cpi - 1;
  idf.si = idf.ui - idf.ai;
  return;
}

/* -----------------------------------------------------------------
*** dalHGK - Computes/returns (d(alpha)/dt)p(d,t,alpha) 
*            for the Haar et al. (1983) equation of state. */
double dalHGK(d,t,alpha)
double d,t,alpha;
{
  double k,l,km,lm,kp,lp,x;
  double dydtp,dbdd,db2dd,db2ddt,db2dtp,db3ddt,db3dtt,drdd,dr2dd,dr2ddt;
  double e1,e2,tzt,dr2dtp,dr3ddt,dr3dtt,xtzt,ai,bi,di,ti,tau,del,ex1,dex;
  double ex2,tex,ex12,qm,xdell,xdelk;
  extern double mfabs();
  int i;

/* evaluate derivatives for the base function */
  aconst.yb = 0.25 * ellcon.b1 * d;
  x = 1.0 - aconst.yb;
  dydtp = (d/4.0)*(ellcon.b1t - ellcon.b1*alpha);
  dbdd = aconst.gascon*t* ((ellcon.b1/4.0/x) * (1.0 - (ellcon.g2-1.0)/x + (ellcon.g1+ellcon.g2+1.0)/x/x) + ellcon.b2 - ellcon.b1*ellcon.gf + 1.0/d);
  db2dd = aconst.gascon*t* ((ellcon.b1*ellcon.b1/16.0/x/x) * (1.0 - 2.0*(ellcon.g2-1.0)/x + 3.0 * (ellcon.g1+ellcon.g2+1.0)/x/x) -  1.0/d/d);
  db2ddt = aconst.gascon*t * ((ellcon.b1t/4.0/x/x) * (1.0 - (ellcon.g2-1.0)*(1.0+aconst.yb)/x + (ellcon.g1+ellcon.g2+1.0) * (1.0+2.0*aconst.yb)/x/x) + ellcon.b2t - ellcon.gf*ellcon.b1t) + dbdd/t;
  db2dtp = dbdd/t + aconst.gascon*t* ( (ellcon.b1*dydtp/4.0/x/x/x) * (1.0 - ellcon.g2 + 2.0 * (ellcon.g1+ellcon.g2+1.0)/x) + ((x*ellcon.b1t + ellcon.b1*dydtp)/4.0/x/x) * (1.0 - (ellcon.g2-1.0)/x + (ellcon.g1+ellcon.g2+1.0) /x/x) + ellcon.b2t - ellcon.gf*ellcon.b1t + alpha/d );
  db3ddt = db2dd/t + aconst.gascon*t * ( (ellcon.b1*ellcon.b1*dydtp/8.0/x/x/x/x) * (1.0 - ellcon.g2 + 3.0 * (ellcon.g1+ellcon.g2+1.0)/x) + (ellcon.b1*(x*ellcon.b1t + ellcon.b1*dydtp)/8.0/x/x/x) * (1.0 - 2.0*(ellcon.g2-1.0)/x + 3.0 * (ellcon.g1+ellcon.g2+1.0)/x/x) - 2.0*alpha/d/d );
  db3dtt = (db2ddt - dbdd/t)/t + aconst.gascon*t* ((ellcon.b1t*dydtp/2.0/x/x/x/x) * (1.0 - ellcon.g2 + (ellcon.g1+ellcon.g2+1.0)*(2.0+aconst.yb)/x) + ((x*ellcon.b1tt + 2.0*ellcon.b1t*dydtp)/4.0/x/x/x) * (1.0 - (ellcon.g2-1.0) *(1+aconst.yb)/x + (ellcon.g1+ellcon.g2+1.0)*(1.0+2.0*aconst.yb)/x/x) + ellcon.b2tt - ellcon.gf*ellcon.b1tt ) + (t*db2dtp - dbdd)/t/t;
/*  evaluate derivatives for the residual function */
  e1  = exp(-aconst.aa * d);
  e2  = 1.0 - e1;
  tzt = aconst.tz / t;
  drdd = dr2dd = dr2ddt = dr2dtp = dr3ddt = dr3dtt = 0.0;
  for (i=0;i<nconst.n;i++)
    { k = (double)(nconst.ii[i]) + 1.0;
      l = (double)(nconst.jj[i]) - 1.0;
      km = k - 1.0;
      lm = l - 1.0;
      kp = k + 1.0;
      lp = l + 1.0;
      xtzt = pow(tzt,l);
      drdd += nconst.g[i] * xtzt*pow(e2,km)*e1;
      dr2dd += nconst.g[i] * e1*xtzt*pow(e2,km) * (km*e1/e2 - 1.0);
      dr2ddt -= nconst.g[i]*e1*l*pow(e2,km)*pow(tzt,lp)/aconst.tz;
      dr2dtp += nconst.g[i]*e1*pow(e2,km)*xtzt * ( d*alpha - l/t - km*e1*d * alpha/e2 );
      dr3ddt += nconst.g[i]*( km*d*alpha*e1*e1*xtzt* pow(e2,k-3.0) + e1* xtzt * pow(e2,km)* (km*e1/e2 - 1.0) * (d*alpha -  l/t - km*d*alpha*e1/e2) );
      dr3dtt += nconst.g[i]*l*e1*pow(e2,km)*pow(tzt,lp)/aconst.tz *( lp/t + d*alpha * km*e1/e2 - d*alpha );
    }
  for (i=36;i<40;i++)
    { k = (double)(nconst.ii[i]);
      l = (double)(nconst.jj[i]);
      km = k - 1.0;
      lm = l - 1.0;
      kp = k + 1.0;
      lp = l + 1.0;
      ai = addcon.aad[i-36];
      bi = addcon.aat[i-36];
      di = addcon.adz[i-36];
      ti = addcon.atz[i-36];
      tau = t/ti - 1.0;
      del = d/di - 1.0;
      if (mfabs(del) < 0.0000000001)
         del = 0.0000000001;
      ex1 = -ai * pow(del,k);
      if (ex1 < tolers.EXPTOL) 
          dex = 0.0;
      else
          dex = exp(ex1);
      ex2 = -bi * tau * tau;
      if (ex2 <= tolers.EXPTOL) 
          tex = 0.0;
      else
          tex = exp(ex2);
      ex12 = dex * tex;
      qm  = l/del - k*ai*pow(del,km);
      xdell = pow(del,l);
      xdelk = pow(del,k);
      drdd += nconst.g[i]*xdell*ex12/di*qm;
      dr2dd += nconst.g[i]*xdell*ex12/di/di * (qm*qm -  l/di/di - ai*k*km* pow(del,k-2.0));
      dr2ddt -= nconst.g[i]*2.0*bi*tau*ex12*xdell/ti/di*qm;
      dr2dtp += nconst.g[i]/di*( d*alpha*xdell*ex12/di/del/del * (l + ai*k*km *xdelk) + qm * ( ex12 * ( xdell* (k*ai*d*alpha*pow(del,km)/di -  2.0*bi*tau/ti) - l*d*alpha*pow(del,lm)/di)));
      dr3ddt += nconst.g[i]/di/di*( xdell*ex12* (2.0*qm*(l*d*alpha/di/del/del + ai*k*km*d*alpha*pow(del,k-2.0)/di) - 2.0*l*d*alpha/di/del/del/del + ai*k*km* (k-2.0)*pow(del,k-3.0)*d*alpha/di) + (qm*qm - l/del/del - ai*k*km* pow(del,k-2.0)) *(ex12*xdell*( ai*k*pow(del,k-1.0)*d*alpha/di - 2.0*bi*tau/ti ) - ex12*l*pow(del,l-1.0)*d*alpha/di));
      dr3dtt -= 2.0*nconst.g[i]*bi/ti/di * ( tau*xdell*ex12*d* alpha/del/del / di * (l + ai*k*km*pow(del,k)) + qm*( xdell*ex12*( ai*k*d*alpha*tau*pow(del,km) /di + (1.0 - 2.0*bi*tau*tau)/ti - tau*l*d*alpha/di/del )));
    }
  return ((db3dtt + dr3dtt)*(2.0*(dbdd + drdd) + d*(db2dd + dr2dd)) - (db2ddt + dr2ddt)*(2.0*(db2dtp + dr2dtp) + d*(db3ddt + dr3ddt) - d*alpha*(db2dd + dr2dd))) / (2.0*(dbdd + drdd) + d*(db2dd + dr2dd)) / (2.0*(dbdd + drdd) + d*(db2dd + dr2dd));
/* returns (d(alpha)/dT)P */
}   

/* -----------------------------------------------------------------
*** denHGK - Computes density (d in g/cm3) and dP/dD (dPdd) as
*            f(p(MPa),t(degK)) from an initial density guess (dguess). */
void denHGK(d,p,dguess,t,dpdd)
double *d,*dpdd,p,dguess,t;
{
  int i,except1;
  double pp,dpdx,x,dp;
  extern double mfabs();

  i = 0;
  *d = dguess;
  do
    { i++;
      except1 = 0;
      if (*d <= 0.0)
         *d = 0.00000001;
      if (*d > 1.9)
         *d = 1.9;
      resid(t,*d);
      base(*d,t);
      pp = RTcurr.rt * (*d) * basef.pb + qqqq.q;
      *dpdd = RTcurr.rt * (aconst.zb + aconst.yb * aconst.dzb) + qqqq.q5;
/* if  dpdd < 0  assume d in 2-phase region and adjust accordingly */
      if (*dpdd <= 0.0)
        { except1 = 1;
	  if (dguess >= 0.2967)
	    *d *= 1.02;
	  else
	    *d *= 0.98;
	}
      if ((i <= 10) && except1)
        { ; }
      else
        { dpdx = *dpdd * 1.1;
	  if (dpdx < 0.1)
	    dpdx = 0.1;
	  dp = mfabs(1.0 - pp/p);
	  if ((dp < 0.00000001) || ((dguess > 0.3) && (dp < 0.0000001)) || ((dguess > 0.7) && (dp < 0.000001)))
	     return;
	  x = (p - pp) / dpdx;
	  if (mfabs(x) > 0.1)
	     x *= 0.1 / mfabs(x);
	  *d += x;
	  if (*d <= 0.0)
	     *d = 0.00000001;
	}
    } while (i <= 30);
  return;
}

/* -----------------------------------------------------------------
*** PsHGK - Returns an approximation to Psaturation(T) that agrees
*           to within 0.02% of that predicted by the HGK surface
*           for temperatures up to within roughly a degree of
*           the critical point. */
double PsHGK(t)
double t;
{
  double a[8] = {-7.8889166,2.5514255,-6.716169,33.239495,-105.38479,174.35319, -148.39348,48.631602};
  double val,v,w,pl,b,q;
  extern double mfabs();
  int i;
  
  if (t <= 314.0)
    { pl = 6.3573118 - 8858.843 / t + 607.56335 * pow(t,-0.6);
      val = 0.1 * exp(pl);
    }
  else
    { v = t / 647.25;
      w = mfabs(1.0 - v);
      b = 0.0;
      for (i=0;i<8;i++)
        b += a[i] * pow(w,(((double) i) + 2.0) / 2.0);
      q = b / v;
      val = 22.093 * exp(q);
    }
  return val;
}

/* -----------------------------------------------------------------
*** TsHGK - Returns Tsaturation(P). */
double TsHGK(p)
double p;
{
  double val,pl,tg,pp,dp;
  extern double PsHGK(),TdsdT(),mfabs();
  int k,okay;
  
  val = 0.0;
  if (p > 22.05)
    return val;
  k = 0;
  pl = 2.302585 + log(p);
  tg = 372.83 + pl * (27.7589 + pl * (2.3819 + pl * (0.24834 + pl*0.0193855)));
  okay = 0;
  while (!okay)
    { if (tg < 273.15)
        tg = 273.15;
      if (tg > 674.0)
        tg = 674.0;
      if (k >= 8)
        { val = tg;
	  okay = 1;
	}
      else
        { k++;
	  pp = PsHGK(tg);
	  dp = TdPsdT(tg);
	  if (mfabs(1.0 - pp/p) < 0.00001)
	    { val = tg;
	      okay = 1;
	    }
	  else
	     tg *= (1.0 + (p - pp)/dp);
	}
    }
  return val;
}

/* -----------------------------------------------------------------
*** TdPsdT - Returns  T*(dPsat/dT). */
double TdPsdT(t)
double t;
{
  double a[8] = {-7.8889166,2.5514255,-6.716169,33.239495,-105.38479,174.35319,
  		 -148.39348,48.631602};
  double v,w,b,c,y,q;
  int i;
  
  v = t / 647.25;
  w = 1.0 - v;
  b = c = 0.0;
  for (i=0;i<8;i++)
    { y = a[i] * pow(w,(((double) i) + 2.0) / 2.0);
      c += y/w*(0.5 - 0.5*(i+1) - 1.0/v);
      b += y;
    }
  q = b / v;
  return 22.093 * exp(q) * c;
}

/* -----------------------------------------------------------------
*** corr - Computes liquid and vapor densities (dliq & dvap)
*          and  (Gl-Gv)/RT  (delg) for T-P conditions on or
*          near the saturation surface. */
void corr(itripl,t,p,dl,dv,delg,epseqn)
int itripl,epseqn;
double t,p,*dl,*dv,*delg;
{
  double dguess,gl,gv,dpdd;
  extern void denHGK(),thmHGK(),dimHGK(),ideal(),bb();

  bb(t);
  dguess = *dl;
  if (*dl <= 0.0)
     dguess = 1.11 - 0.0004 * t;
  denHGK(dl,p,dguess,t,&dpdd);
  ideal(t);
  thmHGK(*dl,t);
/* save liquid properties */
  dimHGK(1,itripl,t,p,*dl,epseqn);
  gl = fcts.gd;
  dguess = *dv;
  if (*dv <= 0.0)
     dguess = p / RTcurr.rt;
  denHGK(dv,p,dguess,t,&dpdd);
  if (*dv < 0.0000005)
     *dv = 0.0000005;
  ideal(t);
  thmHGK(*dv,t);
/* *** vapor properties will be available
*** in COMMON /fcts/ (dimensionless) after
*** pcorr's final call of corr (delg < 10d-4) */
  gv = fcts.gd;
  *delg = gl - gv;
  return;
}

/* -----------------------------------------------------------------
*** pcorr - Computes Psaturation(T) (p) and liquid and vapor
*           densities (dl & dv) from refinement of an initial
*           approximation (PsHGK(t)) in accord with  Gl = Gv. */
void pcorr(itripl,t,p,dl,dv,epseqn)
int itripl,epseqn;
double t,*p,*dl,*dv;
{
  double dp,delg;
  extern double PsHGK(),mfabs();
  extern void corr();
  int okay;

  *p = PsHGK(t);
  *dl = *dv = 0.0;
  okay = 0;
  while (! okay)
    { corr(itripl,t,*p,dl,dv,&delg,epseqn);
      dp = delg * aconst.gascon * t / (1.0/(*dv) - 1.0/(*dl));
      *p += dp;
      if (mfabs(delg) <= 0.0001)
         okay = 1;
    }
  return;
}

/* -----------------------------------------------------------------
*** tcorr - Computes Tsaturation(P) (t) and liquid and vapor
*           densities (dl & dv) from refinement of an initial
*           approximation (TsHGK(p)) in accord with  Gl = Gv. */
void tcorr(itripl,t,p,dl,dv,epseqn)
int itripl,epseqn;
double *t,p,*dl,*dv;
{
  double dp,delg;
  extern double TsHGK(),TdPsdT(),mfabs();
  extern void corr();
  int okay;
  
  *t = TsHGK(p);
  if (*t == 0.0)
    return;
  *dl = *dv = 0.0;
  okay = 0;
  while (!okay)
    { RTcurr.rt = *t * aconst.gascon;
      corr(itripl,*t,p,dl,dv,&delg,epseqn);
      dp = delg * aconst.gascon * (*t) / (1.0/(*dv) - 1.0/(*dl));
      *t *= (1.0 - dp/TdPsdT(*t));
      if (mfabs(delg) <= 0.0001)
         okay = 1;
    }
  return;
}

/* -----------------------------------------------------------------
*** LVSeqn - Computes thermodynamic and transport properties of 
*            critical region H2O (369.85-419.85 degC, 
*            0.20-0.42 gm/cm3) from the fundamental equation given 
*            by Levelt Sengers, et al (1983): J.Phys.Chem.Ref.Data,
*            V.12, No.1, pp.1-28. */
void LVSeqn(isat,iopt,itripl,T,P,Dens,epseqn)
int *isat,*iopt,itripl,epseqn;
double *T,*P,Dens[2];
{
  extern void LVSsat(),thmLVS(),dimLVS(),denLVS(),cpswrap();
  double dl,dv,cdens;
  int cpoint,okay,ioptsv = 0;
  
  cpoint = okay = 0;
  satur.DH2O = Dens[0];
  while (!okay)
    { LVSsat(*iopt,isat,T,P,&satur.DH2O);
      if ((*isat != 0) || (*iopt != 1))
         denLVS(*isat,T,*P);
      if (*isat == 0)
         Dens[0] = satur.DH2O;
      else
        { Dens[0] = satur.Dliq;
	  Dens[1] = satur.Dvap;
	}
      if (*isat == 0)
        { thmLVS(*isat,*T,param.r1,param.th1);
	  dimLVS(*isat,itripl,param.th1,*T,(*P*10.0),&dl,&dv,wpvals.wprops, epseqn);
	  if (cpoint)
	    { cpswrap();
	      Dens[0] = Dens[1] = cdens;
	      *isat = 1;
	      *iopt = ioptsv;
	    }
	  okay = 1;
	}
      else
        { param.th1 = -1.0;
	  thmLVS(*isat,*T,param.r1,param.th1);
	  dimLVS(*isat,itripl,param.th1,*T,(*P*10.0),&dl,&dv,wpvals.wprops, epseqn);
	  param.th1 = 1.0;
	  thmLVS(*isat,*T,param.r1,param.th1);
	  dimLVS(*isat,itripl,param.th1,*T,(*P*10.0),&dl,&dv,wpvals.wprops, epseqn);
	  if (dl == dv)
	    { cpoint = 1;
	      cdens = dl;
	      *T = 647.0670000003;
	      *P = 22.0460000008;
	      ioptsv = *iopt;
	      *iopt = 2;
	      *isat = 0;
	    }
	  else
	    okay = 1;
	}
    }
  return;
}

/* -----------------------------------------------------------------
*** cpswrap - Load critical point A, G, U, H, S, Vs, Di, ZB, 
*            albe values from wpliq into wprops and 
*            approximations to critical Cv, Cp, alpha, beta, 
*            visc, tcond, Prndtl, tdiff, visck, YB, QB, XB, 
*            daldT, st values from wprops into wpliq. */
void cpswrap()
{
  
  wpvals.wprops[0] = wpvals.wpliq[0];
  wpvals.wprops[1] = wpvals.wpliq[1];
  wpvals.wprops[2] = wpvals.wpliq[2];
  wpvals.wprops[3] = wpvals.wpliq[3];
  wpvals.wprops[4] = wpvals.wpliq[4];
  wpvals.wprops[10] = wpvals.wpliq[10];
  wpvals.wprops[18] = wpvals.wpliq[18];
  wpvals.wprops[13] = wpvals.wpliq[13];
  wpvals.wpliq[5] = wpvals.wprops[5];
  wpvals.wpliq[6] = wpvals.wprops[6];
  wpvals.wpliq[8] = wpvals.wprops[8];
  wpvals.wpliq[9] = wpvals.wprops[9];
  wpvals.wpliq[19] = wpvals.wprops[19];
  wpvals.wpliq[20] = wpvals.wprops[20];
  wpvals.wpliq[22] = wpvals.wprops[22];
  wpvals.wpliq[12] = wpvals.wprops[12];
  wpvals.wpliq[14] = wpvals.wprops[14];
  wpvals.wpliq[15] = wpvals.wprops[15];
  wpvals.wpliq[21] = wpvals.wprops[21];
  wpvals.wpliq[17] = wpvals.wprops[17];
  wpvals.wprops[7] = wpvals.wpliq[7] = 42.9352766443498 * units.fs;
  wpvals.wprops[11] = wpvals.wpliq[11] = wpvals.wprops[16] = wpvals.wpliq[16] = 1000000.0;
  return;
}

/* -----------------------------------------------------------------
*** LVSsat - If  isat=1,  computes  Psat(T) or Tsat(P) (iopt=1,2).
*            If  isat=0,  checks whether  T-D or T-P (iopt=1,2)
*            falls on or within  TOL  of the liq-vap surface; if so,
*            isat <- 1  and  T <- Tsat. */
void LVSsat(iopt,isat,T,P,D)
int iopt,*isat;
double *T,*P,*D;
{
  double ERRTOL = 0.000000000001,TCTOL = 0.01,Tsat;
  extern double mfabs(),TsLVS(),Pfind();
  extern void backup(),restor();
  
  if (*isat == 1)
    { if (iopt == 1)
        *P = Pfind(*isat,T,D);
      *T = TsLVS(*isat,*P);
    }
  else
    { if (iopt == 1)
         *P = Pfind(*isat,T,D);
      if ((*P - ERRTOL) > crits.Pc)
         return;
      else
        { backup();
	  Tsat = TsLVS(*isat,*P);
	  if (mfabs(Tsat-(*T)) < TCTOL)
	    { *T = Tsat;
	      *isat = 1;
	    }
	  else
	    restor();
	}
    }
  return;
}

/* -----------------------------------------------------------------
*** denLVS - Calculates  DH2O(T,P)  or  Dvap,Dliq(T,P) from the 
*            Levelt Sengers, et al (1983) critical region 
*            equation of state. */
void denLVS(isat,T,P)
int isat;
double *T,P;
{
  double s[2],sd[2],Pnext,Pdif,delD,Tw,dTw,rho1,rho2;
  extern double Pfind(),mfabs();
  extern void ss();
  int i;
  
  if (isat == 0)
    { satur.DH2O = crits.rhoc;
      for (i=0;i<20;i++)
        { Pnext = Pfind(isat,T,&satur.DH2O);
	  Pdif = Pnext - P;
	  if (satur.iphase == 2)
	    { if (mfabs(Pdif) <= 0.0)
	        return;
              if (Pdif < 0.0)
	        satur.DH2O = coefs1.x[4];
              else
	        satur.DH2O = coefs1.x[3];
	    }
	  else
	    { delD = -Pdif/deri2.dPdD;
	      satur.DH2O += delD;
	      if (satur.DH2O < coefs1.x[3])
	        satur.DH2O = coefs1.x[3];
              if (satur.DH2O > coefs1.x[4])
	        satur.DH2O = coefs1.x[4];
	      if (mfabs(delD/satur.DH2O) < 0.000001)
	        return;
	    }
	}
    }
  else
    { Tw = -crits.Tc / *T;
      dTw = 1.0 + Tw;
      ss(param.r1,param.th1,s,sd);
      rho1 = 1.0 + coefs1.q[8]*dTw + coefs1.a[0] * (s[0] + s[1]);
      rho2 = coefs1.a[6]*pow(param.r1,coefs1.a[5]) + coefs1.a[11]* pow(param.r1,coefs1.q[15]);
      satur.Dvap = crits.rhoc * (rho1 - rho2);
      satur.Dliq = crits.rhoc * (rho1 + rho2);
    }
  return;
}

/* -----------------------------------------------------------------
*** TsLVS - Returns saturation T(P) */
double TsLVS(isat,P)
int isat;
double P;
{
  double val,D,Pnext,dT;
  extern double Pfind(),mfabs();
  int i;
  
  val = crits.Tc - 1.0;
  D = crits.rhoc;
  for (i=0;i<20;i++)
    { Pnext = Pfind(isat,&val,&D);
      dT = (Pnext - P) / deri2.dPdT;
      val -= dT;
      if (val > crits.Tc)
        val = crits.Tc;
      else
        { if (mfabs(dT/val) < 0.00000001)
	    return val;
	}
    }
  return val;
}

/* -----------------------------------------------------------------
*** Pfind - Returns P(T,D).  Computes (dP/dD)T when invoked by SUB 
*           Dfind (isat=0) and (dP/dT)D when invoked by SUB TsLVS 
*           (isat=1).  Also computes 1st & 2nd partial derivatives 
*           the singular part of the potential (Delta P tilde) that
*           are used in SUB thmLVS. */
double Pfind(isat,T,D)
int isat;
double *T,*D;
{
  double sd[2],val,tee,rho,tt1,tt2,Pw0,dPw0,da4,dPw;
  double Uw,dPdTcd,dPwdTw,rho1,rhodi,Cvcoex,err,Pwmu;
  extern double mfabs();
  extern void aux(),conver(),ss();
  /* EQUIV CRAP */
  
  deriv.xk[0] = coefs1.a[6];
  deriv.xk[1] = coefs1.a[11];
  if (mfabs(*T-crits.Tc) < tolers.FPTOL)
    *T = crits.Tc;
  tee = (*T - crits.Tc) / crits.Tc;
  deriv.Tw = -crits.Tc / (*T);
  deriv.dTw = 1.0 + deriv.Tw;
  if (isat == 0)
    { rho = *D / crits.rhoc;
      conver(rho,tee,&deriv.amu,&param.th1,&param.r1,&rho1,deriv.s,&rhodi,&err);
    }
  else
    { param.th1 = abc2.th = -1.0;
      param.r1 = abc2.r = deriv.dTw/(1.0 - coefs1.a[8]);
      ss(param.r1,param.th1,deriv.s,sd);
      rho = param.th1 * (coefs1.a[6]*pow(param.r1,coefs1.a[5]) + coefs1.a[11]*pow(param.r1, coefs1.q[15])) + coefs1.a[0]*(deriv.s[0] + deriv.s[1]);
      rho += 1.0 + coefs1.q[8]*deriv.dTw;
      deriv.amu = 0.0;
      *D = rho * crits.rhoc;
    }
  tt1 = param.th1 * param.th1;
  tt2 = tt1 * tt1;
  Pw0 = 1.0 + deriv.dTw * (coefs1.a[4] + deriv.dTw*(coefs1.a[3] + deriv.dTw* coefs1.a[1]));
  if (isat == 0)
     Pwmu = deriv.amu*rhodi;
  else
     Pwmu = 0.0;
  deriv.p0th = coefs1.q[10] + coefs1.q[11]*tt1 + coefs1.q[12]*tt2;
  deriv.p1th = coefs1.q[17] + coefs1.q[18]*tt1 + coefs1.q[19]*tt2;
  dPw0 = coefs1.a[6]* deriv.p0th*pow(param.r1,2.0-coefs1.q[9]);
  da4 = coefs1.a[11] * deriv.p1th * pow(param.r1,2.0-coefs1.q[14]);
  dPw = coefs1.a[9]*(dPw0+da4);
  deriv.Pw = Pw0 + Pwmu + dPw;
  val = deriv.Pw * crits.Pcon * (*T);
  if (mfabs(param.th1) < 1.0)
     satur.iphase = 1;
  else
    { satur.iphase = 2;
      deriv.dP0dT = coefs1.a[4] + deriv.dTw*(2.0*coefs1.a[3] + 3.0* coefs1.a[1]*deriv.dTw);
      deriv.dM0dT = coefs1.a[13] + deriv.dTw*(2.0*coefs1.a[14] + 3.0* coefs1.a[15]*deriv.dTw);
      Uw = deriv.dP0dT - rho*deriv.dM0dT + coefs1.q[8]*deriv.amu + deriv.s[0] + deriv.s[1];
      dPdTcd = Uw + rho*deriv.dM0dT;
      dPwdTw = deriv.Pw - deriv.Tw*dPdTcd;
      deri2.dPdT = crits.Pcon * dPwdTw;
    }
  aux(param.r1,param.th1,&deriv.d2PdT2,&deriv.d2PdMT,&deriv.d2PdM2,coefs1.a[9], deriv.xk,sd,&Cvcoex);
  if (satur.iphase == 1)
    deri2.dPdD = crits.dPcon * (*D) * (*T) / deriv.d2PdM2;
  return val;
}

/* -----------------------------------------------------------------
*** aux - Calculates some second derivatives of the 
*         anomalous part of the equation of state. */
void aux(r1,th1,d2PdT2,d2PdMT,d2PdM2,aa,xk,sd,Cvcoex)
double r1,th1,*d2PdT2,*d2PdMT,*d2PdM2,aa,xk[2],sd[2],*Cvcoex;
{
  double s[2],w[2],y[2],z[2],coex[2],deli,ww,yy,zz,gamma,tt1,ter,g;
  double alhi,beti,gami,a1,a2,a4,f1;

  int i;
  
  deli = ww = yy = zz = *Cvcoex = 0.0;
  s[0] = coefs1.a[16] + coefs1.a[17]*th1*th1;
  s[1] = coefs1.a[18] + coefs1.a[19]*th1*th1;
  sd[0] = 2.0 * th1 * coefs1.a[17];
  sd[1] = 2.0 * th1 * coefs1.a[19];
  gamma = coefs1.a[5] * (coefs1.a[10] - 1.0);
  tt1 = th1 * th1;
  ter = 2.0 * coefs1.a[5] * coefs1.a[10] - 1.0;
  g = (1.0 + (coefs1.a[8] * ter - 3.0) * tt1 - coefs1.a[8] * (ter - 2.0) * tt1 * tt1);
  for (i=0;i<2;i++)
    { alhi = coefs1.q[9] - deli;
      beti = coefs1.a[5] + deli;
      gami = gamma - deli;
      if (r1 != 0.0)
        { w[i] = (1.0 - alhi)*(1.0-3.0*tt1)*s[i]-coefs1.a[5]*coefs1.a[10] * (1.0-tt1)*th1*(sd[i]);
	  w[i] = (w[i] * pow(r1,-alhi)) * xk[i]/g;
	  ww += w[i];
	  y[i] = beti*(1.0 - 3.0*tt1)*th1 - coefs1.a[5]*coefs1.a[10]*(1.0 - tt1)*th1;
	  y[i] = (y[i] * pow(r1,beti-1.0)) * xk[i] / g;
	  yy += y[i];
	  z[i] = 1.0-coefs1.a[8]*(1.0-(2.0*beti))*tt1;
	  z[i] = (z[i] * pow(r1,-gami)) * xk[i] / g;
	  zz += z[i];
	  a1 = (coefs1.a[5]*(coefs1.a[10]-3.0)-3.0*deli-coefs1.a[8]*alhi*gami)/ (2.0*coefs1.a[8]*coefs1.a[8]*(2.0- alhi)*(1.0-alhi)*alhi);
	  a2 = -(1 +((coefs1.a[5]*(coefs1.a[10]-3.0)-3.0*deli-coefs1.a[8]*alhi* ter)/(2.0*coefs1.a[8]*(1.0 - alhi)*alhi)));
	  a4 = 1.0 + ((ter - 2.0)/(2.0*alhi));
	  f1 = a1 + a2 + a4;
	  coex[i]=((2.0-alhi)*(1.0-alhi)*pow(r1,-alhi)*f1*xk[i]);
	  *Cvcoex += coex[i];
	}
      deli = 0.5;
    }
  *d2PdT2 = aa * ww;
  *d2PdMT = yy + aa * coefs1.a[0] * ww;
  *d2PdM2 = zz/aa + 2.0 * coefs1.a[0] * yy + coefs1.a[0] * coefs1.a[0] * aa * ww;
  return;
}

/* -----------------------------------------------------------------
*** conver - Transforms  T,D  to  parametric variables  r,theta 
*            according to the revised and scaled equations. */
void conver(rho,Tee,amu,th1,r1,rho1s,s1,rhodi,error1)
double rho,Tee,*amu,*th1,*r1,*rho1s,s1[2],*rhodi,*error1;
{
  double sd[2],Tstar,dtstin,rhodit,drho,rho1co,twofaz,y1,den1,tt,rhoweg;
  double den12,den2,slope,hold,error2,rho1s2;
  extern void ss(),rtheta();
  extern double mfabs(),copysign();
  int i;
  
  Tstar = Tee + 1.0;
  dtstin = 1.0 - (1.0 / Tstar);
  *r1 = dtstin;
  if (dtstin <= 0.0)
    { *r1 = dtstin  / (1.0 - coefs1.a[8]);
      *th1 = 1.0;
    }
  else
    *th1 = 0.0;
  ss(*r1,*th1,s1,sd);
  *rhodi = 1.0 + coefs1.q[8] * dtstin;
  rhodit = *rhodi + coefs1.a[0] * s1[0] + coefs1.a[0] * s1[1];
  drho = rho - rhodit;
  *amu = 0.0;
  if (dtstin <= 0.0)
    { rho1co = coefs1.a[6] * pow(*r1,coefs1.a[5]) + coefs1.a[11] * pow(*r1,coefs1.q[15]);
      twofaz = rho1co;
      if (mfabs(drho) <= twofaz)
        { *rho1s = copysign(rho1co,drho) + coefs1.a[0] * s1[0];
	  *th1 = copysign(1.0,drho);
	  *error1 = 1.0;
	  abc2.r = *r1;
	  abc2.th = *th1;
	  return;
	}
    }
  if (drho == 0.0)
    { *th1 = 0.0;
      *r1 = dtstin;
      *rho1s = coefs1.a[0] * s1[0];
    }
/* rule for first pass */
  y1 = dtstin;
  den1 = rho - rhodit;
  rtheta(r1,th1,den1,y1);
  tt = *th1 * *th1;
  *amu = coefs1.a[9] * pow(*r1,coefs1.a[5]*coefs1.a[10]) * *th1 * (1.0 - tt);
  y1 = dtstin + coefs1.a[0] * *amu;
  ss(*r1,*th1,s1,sd);
  rhoweg = coefs1.a[11] * pow(*r1,coefs1.q[15]) * *th1 + coefs1.a[0] * s1[1];
  *rho1s = den1 + coefs1.a[0] * s1[0] +  rhoweg;
  *error1 = rho - *rhodi - *rho1s;
  abc2.r = *r1;
  abc2.th = *th1;
  if (mfabs(*error1) < 0.00001)
    return;
/* rule for second pass */
  den12 = rho - *rhodi - coefs1.a[0] * s1[0] + rhoweg;
  if (den12 == den1)
    den12 = den1 - 0.000001;
  rtheta(r1,th1,den12,y1);
  tt = *th1 * *th1;
  *amu = coefs1.a[9] * pow(*r1,coefs1.a[5]*coefs1.a[10]) * *th1 * (1.0 - tt);
  y1 = dtstin + coefs1.a[0] * *amu;
  ss(*r1,*th1,s1,sd);
  rhoweg = coefs1.a[11] * pow(*r1,coefs1.q[15]) * *th1 + coefs1.a[0] * s1[1];
  rho1s2 = den12 + coefs1.a[0] * s1[0] +  rhoweg;
  error2 = rho - *rhodi - rho1s2;
  if (mfabs(error2) < 0.00001)
    { abc2.r = *r1;
      abc2.th = *th1;
      *error1 = error2;
      *rho1s = rho1s2;
      return;
    }
/* rule for nth pass */
  den2 = den12;
  for (i=0;i<10;i++)
    { slope = (error2 - *error1)/(den2-den1);
      hold = den2;
      den2 = den1 - (*error1/slope);
      rtheta(r1,th1,den2,y1);
      tt = *th1 * *th1;
      *amu = coefs1.a[9] * pow(*r1,(coefs1.a[5]*coefs1.a[10])) * *th1 * (1.0 - tt);
      y1 = dtstin + coefs1.a[0] * *amu;
      ss(*r1,*th1,s1,sd);
      rhoweg = coefs1.a[11] * pow(*r1,coefs1.q[15]) * *th1 + coefs1.a[0] * s1[1];
      *rho1s = den2 + coefs1.a[0] * s1[0] +  rhoweg;
      *error1 = error2;
      error2 = rho - *rhodi - rho1s2;
      abc2.r = *r1;
      abc2.th = *th1;
      if (mfabs(error2) < 0.000001)
        return;
    }
  return;
}

/* -----------------------------------------------------------------
*** rtheta - Fits data for  1.0 < theta < 1.000001.
*            Solves:
*                     rho = em*theta*(r**beta)
*                     Tee = r*(1.0d0-besq*theta*theta)
*
*   Routine given by Moldover (1978): Jour. Res. NBS, v. 84, n. 4,
*   p. 329 - 334. From Loki: Moldover's code used extensive goto-ing; I
*   rewrote this using boolean checks and do-whiles */
void rtheta(r,theta,rho,Tee)
double *r,*theta,rho,Tee;
{
  int do600,do496,i;
  extern double copysign(),mfabs();
  double bee,z,c,z2,z3,dz,absrho;
  
  do600 = do496 = 0;
  if ((coefs1.a[6] <= 0.0) || (coefs1.a[8] <= 1.0) || ((absrho=mfabs(rho)) < 0.000000000001))
    { if (mfabs(Tee) >= 0.000000000001)
        do600 = 1;
    }
  else
    { bee = sqrt(coefs1.a[8]);
      if (mfabs(Tee) < 0.000000000001)
        { *theta = copysign(1.0,rho)/bee;
	  *r = pow(rho/(coefs1.a[6]*(*theta)),1.0/coefs1.a[5]);
	  return;
	}
      if (Tee < 0.0)
        { z = 1.0 - (1.0 - bee) * Tee / (1.0 - coefs1.a[8]) * pow(coefs1.a[6]/absrho ,1.0/coefs1.a[5]); }
      else
        { z = pow(1.0+Tee*pow(coefs1.a[6]/bee/absrho,1.0/coefs1.a[5]), -coefs1.a[5]); }
      if (z > (1.00234 * bee))
        { do496 = do600 = 1; }
      else
        { c = -rho * bee/coefs1.a[6]/pow(mfabs(Tee),coefs1.a[5]);
          z = copysign(z,rho);
          for (i=0;i<16;i++)
            { z2 = z * z;
	      z3 = 1.0 - z2;
	      dz = z3 * (z + c * pow(mfabs(z3), coefs1.a[5]))/(z3 + 2.0 * coefs1.a[5] * z2);
	      z -= dz;
	      if (mfabs(dz/z) < 0.000000000001)
	        { *theta = z/bee;
	          *r = mfabs(Tee/(1.0 - z*z));
	          return;
	        }
	    }
	}
    }
  if (!do600)
    { if (mfabs(*theta) > 1.0001)
        *theta /= mfabs(*theta);
      return;
    }
  if ((Tee < 0.0) || do496)
    { *theta = copysign(1.0,rho);
      *r = mfabs(Tee/(1.0- coefs1.a[8]));
      return;
    }
  *theta = 0.000000000001;
  *r = Tee;
  return; 
}

/* -----------------------------------------------------------------
*** ss - Computes terms of the summation that defines  dPotl/dT
*        and the 1st derivative of the theta (s) square polynomial. */
void ss(r,th,s,sd)
double r,th,s[2],sd[2];
{
  double sx[2],tt;

  tt = th * th;
  sx[0] = coefs1.a[16] + coefs1.a[17] * tt;
  sd[0] = 2.0 * coefs1.a[17] * th;
  sx[1] = coefs1.a[18] + coefs1.a[19] * tt;
  sd[1] = 2.0 * coefs1.a[19] * th;
  s[0] = sx[0] * coefs1.a[9] * coefs1.a[6] * pow(r,1.0-coefs1.q[9]);
  s[1] = sx[1] * coefs1.a[9] * coefs1.a[11] * pow(r,1.0-coefs1.q[14]);
  abc1.dPdM = pow(r,coefs1.a[5])*coefs1.a[6]*th + coefs1.a[0]* pow(r,1.0-coefs1.q[9])*coefs1.a[9]*coefs1.a[6]*sx[0] + pow(r,coefs1.q[15]) *coefs1.a[11]*th + coefs1.a[0]*pow(r,1.0-coefs1.q[14])*coefs1.a[9]* coefs1.a[11]*sx[1];
  return;
}

/* -----------------------------------------------------------------
*** thmLVS - Calculates thermodynamic and transport properties
*            of critical region H2O using the Levelt Sengers, et al
*            (1983) equation of state. */
void thmLVS(isat,T,r1,th1)
int isat;
double T,r1,th1;
{
  double sd[2],d2P0dT,d2M0dT,rho,Uw,dPdT2,dPwdTw,dPdTal,CviTw2;
  double Cvw,Cpw,Hw,Sw,Scond,Cvcoex;
  extern void aux(),ss();

  d2P0dT = 2.0*coefs1.a[3] + 6.0*coefs1.a[1]*deriv.dTw;
  d2M0dT = 2.0*coefs1.a[14] + 6.0*coefs1.a[15]*deriv.dTw;
  deriv.dP0dT = coefs1.a[4] + deriv.dTw*(2.0*coefs1.a[3] + 3.0*coefs1.a[1]* deriv.dTw);
  deriv.dM0dT = coefs1.a[13] + deriv.dTw*(2.0*coefs1.a[14] + 3.0*coefs1.a[15]* deriv.dTw);
  if (isat == 0)
    { rho = satur.DH2O / crits.rhoc;
      Uw = deriv.dP0dT - rho*deriv.dM0dT + coefs1.q[8]*deriv.amu + deriv.s[0] + deriv.s[1];
    }
  else
    { rho = th1 * (coefs1.a[6] * pow(r1,coefs1.a[5]) + coefs1.a[11] * pow(r1,coefs1.q[15])) + coefs1.a[0]*(deriv.s[0]+deriv.s[1]);
      rho += 1.0 + coefs1.q[8]*deriv.dTw;
      Uw = deriv.dP0dT - rho*deriv.dM0dT + coefs1.q[8] * deriv.amu + deriv.s[0] + deriv.s[1];
      satur.DH2O = rho * crits.rhoc;
      dPdT2 = deriv.Pw - deriv.Tw*(Uw + rho*deriv.dM0dT);
      therm.heat = 1000.0*T*(crits.Pcon*dPdT2)*(1.0/satur.Dvap - 1.0/satur.Dliq);
      ss(r1,th1,deriv.s,sd);
      aux(r1,th1,&deriv.d2PdT2,&deriv.d2PdMT,&deriv.d2PdM2,coefs1.a[9], deriv.xk,sd,&Cvcoex);
      if (r1 != 0.0)
        deri2.dPdD = crits.dPcon * satur.DH2O * T / deriv.d2PdM2;
    }
  if (r1 != 0.0)
    { abc3.dPdTcd = deriv.dP0dT + coefs1.q[8]*(deriv.amu - rho/deriv.d2PdM2) + deriv.s[0] + deriv.s[1] - deriv.d2PdMT*rho/deriv.d2PdM2;
      dPwdTw = deriv.Pw - deriv.Tw*abc3.dPdTcd;
      dPdTal = crits.Pcon * dPwdTw;
      CviTw2 = d2P0dT - rho*d2M0dT + deriv.d2PdT2 - (coefs1.q[8]+deriv.d2PdMT)* (coefs1.q[8] + deriv.d2PdMT)/deriv.d2PdM2;
      Cvw = CviTw2 * deriv.Tw * deriv.Tw;
      Cpw = Cvw + deriv.d2PdM2*dPwdTw*dPwdTw / (rho*rho);
      therm.betaw = 1.0 / (satur.DH2O*deri2.dPdD);
      therm.alphw = therm.betaw * dPdTal;
      therm.Speed = 1000.0 * sqrt(Cpw/Cvw*deri2.dPdD);
    }
  else
    { Cvw = Cpw = therm.betaw = therm.alphw = 1.0;
      therm.Speed = 0.0;
    }
  Hw = deriv.Pw - deriv.Tw*Uw;
  Sw = Hw - rho*(deriv.amu+coefs1.a[12]+deriv.dTw*(coefs1.a[13]+deriv.dTw* (coefs1.a[14]+deriv.dTw*coefs1.a[15])));
  Scond = crits.Scon / satur.DH2O;
  therm.U = Uw * crits.Ucon / satur.DH2O;
  therm.H = Hw * Scond * T;
  therm.Entrop = Sw * Scond;
  therm.AE = therm.U - T * therm.Entrop;
  therm.GE = therm.H - T * therm.Entrop;
  therm.Cv = Cvw * Scond;
  therm.Cp = Cpw * Scond;
  return;
}

/* -----------------------------------------------------------------
*** dalLVS - Computes/returns (d(alpha)/dt)p(D,T,alpha) 
*            for the Levelt Sengers et al. (1983) 
*            equation of state.  Note that D (kg/m**3),
*            T (degK), P (MPa), alpha (degK**-1). */
double dalLVS(D,T,P,alpha)
double D,T,P,alpha;
{
  double dsdT[2],sp[2],dspdT[2],k[2],calpha[2],cbeta[2],delT,b1,b2;
  double cgamma[2],u[2],v[2],w[2],dudT[2],dvdT[2],dwdT[2],ar1,a01,ar2,a02;
  double amult,d0dT,drdT,q,dqdT,dP0dTT,ddelMT,dPdTT,dPdMMT,dPdMTT,dPPTT,pterm;
  extern double mfabs();
  int i;
  
  if (abc2.r == 0.0)
    return 1000000.0;
  k[0] = coefs1.a[6];
  k[1] = coefs1.a[11];
  calpha[0] = coefs1.q[9];
  calpha[1] = coefs1.q[14];
  cbeta[0] = coefs1.a[5];
  cbeta[1] = coefs1.q[15];
  cgamma[0] = cbeta[0] * (coefs1.a[10] - 1.0);
  cgamma[1] = cgamma[0] - coefs1.q[13];
  delT = (T - crits.Tc) / T;
  deriv.s[0] = coefs1.a[16] + coefs1.a[17] * abc2.th * abc2.th;
  deriv.s[1] = coefs1.a[18] + coefs1.a[19] * abc2.th * abc2.th;
  sp[0] = 2.0 * coefs1.a[17] * abc2.th;
  sp[1] = 2.0 * coefs1.a[19] * abc2.th;
/* *********************************************************************
***
*** Compute drdT and d0dT from solution of the linear system
***
***                      ax = b
***
*** d(dPdM)/dT = -D/Dc*alpha - P11*Tc/T**2 = ar1*drdT + a01*d0dT = b1
*** d(delT)/dT =           Tc/T**2         = ar2*drdT + a02*d0dT = b2
*** */
  b1 = -D / crits.rhoc * alpha - coefs1.q[8]*crits.Tc/T/T;
  b2 = crits.Tc / (T * T);
  ar1 = a01 = 0.0;
  for (i=0;i<2;i++)
    { ar1 += k[i]*(cbeta[i]*abc2.th*pow(abc2.r,cbeta[i]-1.0) + coefs1.a[9]*coefs1.a[0]*(1.0 - calpha[i])* pow(abc2.r,-calpha[i])* deriv.s[i]);
      a01 += k[i]*(pow(abc2.r,cbeta[i]) + coefs1.a[9]*coefs1.a[0]*sp[i]*pow(abc2.r,1.0 - calpha[i]));
    }
  ar2 = 1.0 - coefs1.a[8]*abc2.th*abc2.th - coefs1.a[9]*coefs1.a[0]*cbeta[0]*coefs1.a[10]*(1.0-abc2.th*abc2.th)*abc2.th *pow(abc2.r,(cbeta[0]*coefs1.a[10] - 1.0));
  a02 = 3.0*coefs1.a[9]*coefs1.a[0]*abc2.th*abc2.th*pow(abc2.r,cbeta[0]*coefs1.a[10]) - 2.0*coefs1.a[8]*abc2.r*abc2.th - coefs1.a[9]*coefs1.a[0]*pow(abc2.r,cbeta[0] * coefs1.a[10]);
/* *********************************************************************
*** solve the linear system with simplistic GE w/ partial pivoting
********************************************************************* */
  if (mfabs(ar1) > mfabs(ar2))
    { amult = -ar2 / ar1;
      d0dT = (b2 + amult*b1) / (a02 + amult*a01);
      drdT = (b1 - a01*d0dT) / ar1;
    }
  else
    {
      amult = -ar1 / ar2;
      d0dT  = (b1 + amult*b2) / (a01 + amult*a02);
      drdT  = (b2 - a02*d0dT) / ar2;
    }
/* *********************************************************************
***
*** Compute theta polynomials and their tempertaure derivatives
*** */
  dspdT[0] = 2.0*coefs1.a[17]*d0dT;
  dspdT[1] = 2.0*coefs1.a[19]*d0dT;
  dsdT[0] = dspdT[0]*abc2.th;
  dsdT[1] = dspdT[1]*abc2.th;
  q = 1.0 + (coefs1.a[8]*(2.0*cbeta[0]*coefs1.a[10]-1.0)-3.0)*abc2.th*abc2.th - coefs1.a[8]*(2.0*cbeta[0]*coefs1.a[10] - 3.0)*abc2.th*abc2.th*abc2.th*abc2.th;
  dqdT = 2.0*(coefs1.a[8]*(2.0*cbeta[0]*coefs1.a[10]-1.0)-3.0)*abc2.th*d0dT - 4.0*coefs1.a[8]*(2.0*cbeta[0]* coefs1.a[10] -3.0)*abc2.th*abc2.th*abc2.th*d0dT;
  for (i=0;i<2;i++)
    { u[i] = (1.0-coefs1.a[8]*(1.0-2.0*cbeta[i])*abc2.th*abc2.th)/q;
      dudT[i] = (-2.0*coefs1.a[8]*(1.0-2.0*cbeta[i])*abc2.th*d0dT - u[i]*dqdT)/q;
      v[i]= ((cbeta[i]-cbeta[0]*coefs1.a[10])*abc2.th+(cbeta[0]*coefs1.a[10]-3.0*cbeta[i])*abc2.th*abc2.th*abc2.th)/q;
      dvdT[i] = ((cbeta[i]-cbeta[0]*coefs1.a[10])*d0dT+3.0*(cbeta[0]*coefs1.a[10]-3.0*cbeta[i])*abc2.th*abc2.th*d0dT - v[i]*dqdT) / q;
      w[i] = ((1.0 - calpha[i])*(1.0-3.0*abc2.th*abc2.th)*deriv.s[i] - cbeta[0]*coefs1.a[10]*(abc2.th-abc2.th*abc2.th*abc2.th)* sp[i]) / q;
      dwdT[i] = ((1.0-calpha[i])*((1.0-3.0*abc2.th*abc2.th)*dsdT[i]-6.0*abc2.th*deriv.s[i]*d0dT)-cbeta[0] *coefs1.a[10]*((abc2.th-abc2.th*abc2.th*abc2.th)*dspdT[i] + sp[i]*(d0dT - 3.0*abc2.th*abc2.th*d0dT)) - w[i]*dqdT) / q;
    }
/* *********************************************************************
***
*** Compute dP0dTT, ddelMT, dPdTT, dPdMMT, dPdMTT, dPPTT
*** */
  dP0dTT = crits.Tc/(T*T) * (2.0*coefs1.a[3] + 6.0*coefs1.a[1]*delT);
  ddelMT = coefs1.a[9]*pow(abc2.r,cbeta[0]*coefs1.a[10])*(cbeta[0]*coefs1.a[10]*abc2.th/abc2.r*(1.0-abc2.th*abc2.th)*drdT + (1.0-3.0*abc2.th*abc2.th)*d0dT);
  dPdTT = dPdMMT = dPdMTT = 0.0;
  for (i=0;i<2;i++)
    { dPdTT += coefs1.a[9]*k[i] * (pow(abc2.r,1.0-calpha[i])*dsdT[i] + deriv.s[i]*(1.0 - calpha[i])*pow(abc2.r,-calpha[i])*drdT);
      dPdMMT += k[i] * ((pow(abc2.r,-cgamma[i])*dudT[i] - u[i]*cgamma[i]*pow(abc2.r, -1.0-cgamma[i])*drdT) / coefs1.a[9] + 2.0*coefs1.a[0]*(pow(abc2.r,cbeta[i]-1.0)*dvdT[i] + v[i]*(cbeta[i] - 1.0)*pow(abc2.r,cbeta[i]-2.0)*drdT) + coefs1.a[9]*coefs1.a[0]*coefs1.a[0]*(pow(abc2.r,-calpha[i])*dwdT[i] - calpha[i]*w[i] *pow(abc2.r,-1.0-calpha[i])*drdT));
      dPdMTT += k[i] * (pow(abc2.r,cbeta[i]-1.0)*dvdT[i] +v[i]*(cbeta[i] - 1.0)* pow(abc2.r,cbeta[i]-2.0)*drdT + coefs1.a[9]*coefs1.a[0]*(pow(abc2.r,-calpha[i])*dwdT[i] - calpha[i]*pow(abc2.r,-1.0 - calpha[i])*drdT*w[i]));
    }
  dPPTT = dP0dTT + dPdTT + coefs1.q[8]*ddelMT - D/crits.rhoc*dPdMTT/deriv.d2PdM2 +(coefs1.q[8] + deriv.d2PdMT)*(D/crits.rhoc*alpha/deriv.d2PdM2+D/crits.rhoc*dPdMMT /(deriv.d2PdM2*deriv.d2PdM2));
  pterm = P/crits.Pc + abc3.dPdTcd;
/* return (d(alpha)/dT)P */
  return (crits.Tc*crits.rhoc*crits.rhoc/(D*D*T*T) * (-2.0/T*deriv.d2PdM2*pterm + 2.0*alpha*deriv.d2PdM2*pterm + pterm*dPdMMT +deriv.d2PdM2*dPPTT));
}

/* -----------------------------------------------------------------
*** backup - Save Pfind COMMON values during saturation check. */
void backup()
{
  store.isav1 = satur.iphase;
  store.sav2 = param.r1;
  store.sav3 = param.th1;
  store.sav4 = deriv.amu;
  store.sav5 = deriv.s[0];
  store.sav6 = deriv.s[1];
  store.sav7 = deriv.Pw;
  store.sav8 = deriv.Tw;
  store.sav9 = deriv.dTw;
  store.sav10 = deriv.dM0dT;
  store.sav11 = deriv.dP0dT;
  store.sav12 = deriv.d2PdM2;
  store.sav13 = deriv.d2PdMT;
  store.sav14 = deriv.d2PdT2;
  store.sav15 = deriv.p0th;
  store.sav16 = deriv.p1th;
  store.sav17 = deriv.xk[0];
  store.sav18 = deriv.xk[1];
  store.sav19 = deri2.dPdD;
  return;
}

/* -----------------------------------------------------------------
*** restor - Restore Pfind COMMON values after saturation check. */
void restor()
{
  satur.iphase = store.isav1;
  param.r1 = store.sav2;
  param.th1 = store.sav3;
  deriv.amu = store.sav4;
  deriv.s[0] = store.sav5;
  deriv.s[1] = store.sav6;
  deriv.Pw = store.sav7;
  deriv.Tw = store.sav8;
  deriv.dTw = store.sav9;
  deriv.dM0dT = store.sav10;
  deriv.dP0dT = store.sav11;
  deriv.d2PdM2 = store.sav12;
  deriv.d2PdMT = store.sav13;
  deriv.d2PdT2 = store.sav14;
  deriv.p0th = store.sav15;
  deriv.p1th = store.sav16;
  deriv.xk[0] = store.sav17;
  deriv.xk[1] = store.sav18;
  deri2.dPdD = store.sav19;
  return;
}

/* -----------------------------------------------------------------
*** load - Load thermodynamic and transport property values from
*          ptemp into props. */
void load(phase,ptemp,props)
int phase;
double ptemp[23],props[46];
/*  The indexing system was switched over from a two-dimensional array to a one-dimensional array. */
{
  int i,key[46] = {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46};
  
  for (i=0;i<23;i++)
     props[key[(phase-1)*23 + i] - 1] = ptemp[i];
  return;
}

/* -----------------------------------------------------------------
*** tpset - Dimension triple point  U, S, H, A, G  values (in J/g from
*           Table 2, Helgeson & Kirkham, 1974a) into user-specified units. */
void tpset()
{
  double Utr= -15766.0,Str= 3.5144,Htr= -15971.0,Atr= -12870.0,Gtr= -13073.0;
  
  tpoint.Utripl = Utr*units.fh;
  tpoint.Stripl = Str*units.fh;
  tpoint.Htripl = Htr*units.fh;
  tpoint.Atripl = Atr*units.fh;
  tpoint.Gtripl = Gtr*units.fh;
  return;
}

/* -----------------------------------------------------------------
*** triple - Convert  U, S, H, A, G  values computed with reference to  
*            zero triple point properties (Haar et al., 1984; 
*            Levelt Sengers et al., 1983) into values referenced to 
*            triple point properties given by  Helgeson and Kirkham, 1974a. */
void triple(T,wpzero)
double T,wpzero[23];
{
  int A=0,G=1,S=2,U=3,H=4;
  double TS;
  
  wpzero[S] += tpoint.Stripl;
  TS = T * wpzero[S] - tpoint.Ttripl*tpoint.Stripl;
  wpzero[G] = wpzero[H] - TS + tpoint.Gtripl;
  wpzero[A] = wpzero[U] - TS + tpoint.Atripl;
  wpzero[H] += tpoint.Htripl;
  wpzero[U] += tpoint.Utripl;
  return;
}

/* -----------------------------------------------------------------
*** TdegK - Returns input temperature  t  converted from 
*           user-specified units to degK. */
double TdegK(it,t)
int it;
double t;
{
  switch (it)
   { case 1 : return t;
     case 2 : return t + 273.15;
     case 3 : return t / 1.8;
     default: return (t+459.67)/1.8;
   }
}

/* -----------------------------------------------------------------
*** TdegUS - Returns input temperature  t  converted 
*            from degK to user-specified units. */
double TdegUS(it,t)
int it;
double t;
{
  switch (it)
   { case 1 : return t;
     case 2 : return t - 273.15;
     case 3 : return t * 1.8;
     default: return t * 1.8 - 459.67;
   }
}

/* -----------------------------------------------------------------
*** dimHGK - Dimensions thermodynamic and transport property values 
*            computed from the HGK equation of state per user-specified 
*            choice of units. */
void dimHGK(isat,itripl,t,p,d,epseqn)
int isat,itripl,epseqn;
double t,p,d;
{
  double pbars,dkgm3,betaPa,betab,CpJKkg;
  extern double viscos(),thcond(),surten(),dalHGK(),mfabs();
  extern void Born92(),triple();
  int aw=0,gw=1,sw=2,uw=3,hw=4,cvw=5,cpw=6,vsw=7,alw=8,bew=9,diw=10,viw=11,tcw=12, stw=13,tdw=14,Prw=15,vikw=16,albew=17,ZBw=18,YBw=19,QBw=20,dalwdT=21,XBw=22;
  
  wpvals.wprops[aw] = fcts.ad*RTcurr.rt*units.fh;
  wpvals.wprops[gw] = fcts.gd*RTcurr.rt*units.fh;
  wpvals.wprops[sw] = fcts.sd*aconst.gascon*units.fh*units.ft;
  wpvals.wprops[uw] = fcts.ud*RTcurr.rt*units.fh;
  wpvals.wprops[hw] = fcts.hd*RTcurr.rt*units.fh;
  wpvals.wprops[cvw] = fcts.cvd*aconst.gascon*units.fh*units.ft;
  wpvals.wprops[cpw] = fcts.cpd*aconst.gascon*units.fh*units.ft;
  wpvals.wprops[vsw] = sqrt(mfabs(fcts.cpd*fcts.dpdd*1000.0/fcts.cvd)) * units.fs;
  wpvals.wprops[bew] = 1.0/(d*fcts.dpdd*units.fp);
  wpvals.wprops[alw] = d * fcts.dvdt;
  wpvals.wprops[dalwdT] = dalHGK(d,t,wpvals.wprops[alw]);
  pbars = p*10.0;
  dkgm3 = d * 1000.0;
  betaPa = wpvals.wprops[bew]*units.fp / 1000000.0;
  betab = wpvals.wprops[bew]*units.fp / 10.0;
  CpJKkg = wpvals.wprops[cpw]/units.fh/units.ft * 1000.0;
  wpvals.wprops[viw] = viscos(t,pbars,dkgm3,betaPa) * units.fvd;
  wpvals.wprops[tcw] = thcond(t,pbars,dkgm3,wpvals.wprops[alw],betaPa) * units.fc * units.ft;
  if ((isat == 0) || (isat == 2))
    wpvals.wprops[stw] = 0.0;
  else
    wpvals.wprops[stw] = surten(t) * units.fst;
  Born92(t,pbars,(dkgm3/1000.0),betab,wpvals.wprops[alw],wpvals.wprops[dalwdT],&wpvals.wprops[diw],&wpvals.wprops[ZBw],&wpvals.wprops[QBw],&wpvals.wprops[YBw],&wpvals.wprops[XBw],epseqn);
  wpvals.wprops[tdw] = wpvals.wprops[tcw]/units.fc/units.ft / (dkgm3 * CpJKkg) * units.fvk;
  if (wpvals.wprops[tcw] != 0.0)
    wpvals.wprops[Prw] = wpvals.wprops[viw]/units.fvd * CpJKkg / (wpvals.wprops[tcw]/units.fc/units.ft);
  else
    wpvals.wprops[Prw] = 0.0;
  wpvals.wprops[vikw] = wpvals.wprops[viw]/ units.fvd / dkgm3 * units.fvk;
  wpvals.wprops[albew] = wpvals.wprops[alw] / wpvals.wprops[bew];
  if (itripl == 1)
    triple(t,wpvals.wprops);
  return;
}

/* -----------------------------------------------------------------
*** dimLVS - Dimension critical region properties per user-specs
*            and load into tprops. */
void dimLVS(isat,itripl,theta,T,Pbars,dl,dv,tprops,epseqn)
int isat,itripl,epseqn;
double theta,T,Pbars,*dl,*dv,tprops[23];
{
  double CpJKkg,betaPa,betab,dkgm3;
  extern double mfabs(),dalLVS(),visoc(),thcond(),surten();
  extern void triple(),Born92();
  int aw=0,gw=1,sw=2,uw=3,hw=4,cvw=5,cpw=6,vsw=7,alw=8,bew=9,diw=10,viw=11,tcw=12,stw=13,tdw=14,Prw=15,vikw=16,albew=17,ZBw=18,YBw=19,QBw=20,dalwdT=21,XBw=22;
  
  if (isat == 1)
    { *dv = satur.Dvap;
      *dl = satur.Dliq;
    }
  tprops[aw] = therm.AE * units.fh;
  tprops[gw] = therm.GE * units.fh;
  tprops[sw] = therm.Entrop * units.fh * units.ft;
  tprops[uw] = therm.U * units.fh;
  tprops[hw] = therm.H * units.fh;
  tprops[cvw] = therm.Cv * units.fh * units.ft;
  tprops[cpw] = therm.Cp * units.fh * units.ft;
  tprops[vsw] = therm.Speed * units.fs;
  tprops[bew] = therm.betaw / units.fp;
  tprops[alw] = therm.alphw;
  abc2.th = theta;
  tprops[dalwdT] = dalLVS(satur.DH2O,T,Pbars/10.0,tprops[alw]);
  CpJKkg = therm.Cp * 1000.0;
  betaPa = therm.betaw / 1000000.0;
  betab = therm.betaw / 10.0;
  if (mfabs(theta) != 1.0)
    { dkgm3 = satur.DH2O;
      tprops[stw] = 0.0;
    }
  else
    { if (theta <  0.0)
        { dkgm3 = satur.Dvap;
	  tprops[stw] = 0.0;
	}
      else
        { dkgm3 = satur.Dliq;
	  tprops[stw] = surten(T) * units.fst;
	}
    }
  Born92(T,Pbars,(dkgm3/1000.0),betab,tprops[alw],tprops[dalwdT],&tprops[diw], &tprops[ZBw],&tprops[QBw],&tprops[YBw],&tprops[XBw],epseqn);
  tprops[viw] = viscos(T,Pbars,dkgm3,betaPa) * units.fvd;
  tprops[tcw] = thcond(T,Pbars,dkgm3,tprops[alw],betaPa) * units.fc * units.ft;
  tprops[tdw] = tprops[tcw]/units.fc/units.ft / (dkgm3 * CpJKkg) * units.fvk;
  tprops[Prw] = tprops[viw]/units.fvd * CpJKkg / (tprops[tcw]/units.fc/units.ft);
  tprops[vikw] = tprops[viw]/units.fvd / dkgm3 * units.fvk;
  tprops[albew] = tprops[alw] / tprops[bew];
  if (itripl == 1)
    triple(T,tprops);
  return;
}

/* -----------------------------------------------------------------
*** viscos - Returns dynamic viscosity of H2O in kg/m*s (= Pa*s)
*            if  Tk, Pbars  falls within the validity region (specified 
*            by the initial IF statement) of the Watson et al. (1980)
*            equation; otherwise returns zero.  See equations 3.1-2 and
*            4.1-5 and Tables 1, 6, and 8 from Sengers and 
*            Kamgar-Parsi (1984). */
double viscos(Tk,Pbars,Dkgm3,betaPa)
double Tk,Pbars,Dkgm3,betaPa;
{
  double a[4] = {0.0181583,0.0177624,0.0105287,-0.0036744};
  double b[42]= {0.5132047,  0.3205656,  0.0,0.0,
     -0.7782567,  0.1885447,  0.2151778,  0.7317883,
      1.2410440,  1.4767830,  0.0,0.0,
     -0.2818107, -1.0707860, -1.2631840,  0.0,
     0.0,0.0,0.1778064,  0.4605040,
     0.2340379, -0.4924179,  0.0,0.0,
     -0.0417661,  0.0,0.0,0.1600435,
     0.0,0.0,0.0,       -0.01578386,
    0.0,0.0,0.0,0.0,0.0,0.0,0.0,-0.003629481,0.0,0.0};
  double tol = 0.01,TdegC,T,D,sum,u0,u1,xt,u2;
  int i,j;
  
  TdegC = Tk - 273.15;
  if ((Pbars > (5000.0+tol)) || ((Pbars > (3500.0+tol)) && (TdegC > (150.0+tol))) || ((Pbars > (3000.0+tol)) && (TdegC > (600.0+tol))) || (TdegC > (900.0+tol)))
    return 0.0;
  T = Tk / 647.27;
  D = Dkgm3 / 317.763;
  sum = 0.0;
  for (i=0;i<4;i++)
    sum += a[i]/pow(T,(double) i);
  u0 = 0.000001 * sqrt(T) / sum;
  sum = 0.0;
  for (i=0;i<6;i++)
    for (j=0;j<7;j++)
      sum += b[j*6+i] * pow((1.0/T-1),(double) i) * pow((D-1),(double) j);
  u1 = exp(D*sum);
  if ((0.997 <= T) && (T <= 1.0082) && (0.755 <= D) && (D <= 1.2900))
    { xt = 22115000.0 / (100973.324169) * betaPa * Dkgm3 * Dkgm3;
      if (xt < 22.0)
        u2 = 1.0;
      else
        u2 = 0.922 * pow(xt,0.0263);
    }
  else
    u2 = 1.0;
  return u0*u1*u2;
}

/* -----------------------------------------------------------------
*** thcond - Returns thermal conductivity of H2O in J/m*deg*s (=W/m*deg)
*            if  Tk, Pbars  falls within the validity region (specified 
*            by the initial IF statement) of the Sengers et al. (1984)
*            equation; returns zero otherwise.  See equations 3.2-14
*            and tables 2-5 and I.5-6 from the above reference. */
double thcond(Tk,Pbars,Dkgm3,alph,betaPa)
double Tk,Pbars,Dkgm3,alph,betaPa;
{
  int i,j;
  double T,D,sum,L0,L1,L2,TdegC,u0,u1,xt,dPdT;
  double aL[4] = { 2.02223,14.11166,5.25597,-2.0187 };
  double au[4] = { .0181583,.0177624,.0105287,-.0036744 };
  double bL[30] = {  1.329304600, -0.404524370,  0.244094900,
             0.018660751, -0.129610680,  0.044809953,
            1.701836300, -2.215684500,  1.651105700,
            -0.767360020,  0.372833440, -0.112031600,
            5.224615800, -10.12411100,  4.987468700,
           -0.272976940, -0.430833930,  0.133338490,
            8.712767500, -9.500061100,  4.378660600,
           -0.917837820,  0.0,          0.0,
              -1.852599900,  0.934046900,  0.0,
             0.0,          0.0,          0.0};
  double bu[30] = {  0.5019380,  0.2356220, -0.2746370,  0.1458310,
           -0.0270448,  0.1628880,  0.7893930, -0.7435390,
           0.2631290, -0.0253093, -0.1303560,  0.6736650,
        -0.9594560,  0.3472470, -0.0267758,  0.9079190,
         1.2075520, -0.6873430,  0.2134860, -0.0822904,
         -0.5511190,  0.0670665, -0.4970890,  0.1007540,
           0.0602253,  0.1465430, -0.0843370,  0.1952860,
       -0.0329320, -0.0202595};
  double tol = .01;
  
  TdegC = Tk - 273.15;
  if ((Pbars > (4000.0+tol)) || ((Pbars > (2000.0+tol)) && (TdegC > (125.0+tol))) || ((Pbars > (1500.0+tol)) && (TdegC > (400.0+tol))) || (TdegC > (800.0+tol)))
    return 0.0;
  T = Tk / 647.27;
  D = Dkgm3 / 317.763;
  sum = 0.0;
  for (i=0;i<4;i++)
    sum += aL[i]/pow(T,(double) i);
  L0 = sqrt(T) / sum;
  sum = 0.0;
  for (i=0;i<5;i++)
    for (j=0;j<6;j++)
      sum += bL[i*6+j] * pow((1.0/T-1),(double) i) * pow((D-1),(double) j);
  L1 = exp(D*sum);
  sum = 0.0;
  for (i=0;i<4;i++)
    sum += au[i]/pow(T,(double) i);
  u0 = 0.000001 * sqrt(T) / sum;
  sum = 0.0;
  for (i=0;i<6;i++)
    for (j=0;j<5;j++)
      sum += bu[i*5+j] * pow((1.0/T-1),(double) i) * pow((D-1),(double) j);
  u1 = exp(D*sum);
  xt = 22115000.0 / (100973.324169) * betaPa * Dkgm3 * Dkgm3;
  dPdT = (647.27/22115000.0) * alph/betaPa;
  L2 = 0.000000037711 / (u0*u1) * T*T/(D*D) * dPdT * dPdT * pow(xt,0.4678) * sqrt(D) * exp(-18.66*(T-1)*(T-1) - pow((D-1),4.0));
  return L0*L1+L2;
}

/* -----------------------------------------------------------------
*** surten - Returns the surface tension of vapor-saturated liquid
*            H2O in MPa*cm (converted from N/m) as computed from
*            the Vargaftik et al. (1983) equation.  See equations
*            10.1-2, Kestin et al. (1984); compare also equation
*            C.5 and table 11, Haar et al. (1984). */

double surten(Tsatur)
double Tsatur;
{
  double Tnorm;

  if ((Tsatur < 273.16) || (Tsatur > 647.067))
    return 0.0;
  if (Tsatur >= (647.067-0.0000000001))
    Tnorm = 0.0;
  else
    Tnorm = (0.999686 - Tsatur/647.27) / 0.999686;
  return 0.2358*pow(Tnorm,1.256)*(1.0 - 0.625*Tnorm);
}

/* -----------------------------------------------------------------
*** Born92 - Computes the Z, Q, Y, and X Born functions at TK, Pbars.
***        epseqn = 4 ...... use Johnson-Norton (1991) equation */
void Born92(TK,Pbars,dgcm3,betab,alphaK,daldT,eps,Z,Q,Y,X,epseqn)
int epseqn;
double TK,Pbars,dgcm3,betab,alphaK,daldT,*eps,*Z,*Q,*Y,*X;
{
  double TdegC,dedP,dedT,d2edT2;
  extern void JN91(),epsBrn();
  
  *eps = *Z = *Y = *Q = *X = 0.0;
  TdegC = TK - 273.15;
  if ((TdegC > (1000.0+0.001)) || (Pbars > (5000.0+0.001)))
    return;
  if (epseqn == 4)
    { JN91(TK,dgcm3,betab,alphaK,daldT,eps,&dedP,&dedT,&d2edT2);
      epsBrn(*eps,dedP,dedT,d2edT2,Z,Q,Y,X);
      return;
    }
  /* more axed code per .f */
  return;
}

/* -----------------------------------------------------------------
*** JN91 - Compute (eps, dedP, dedT, d2edT2)(T,D) using equations 
***        given by Johnson and Norton (1991); fit parameters 
***        regressed from least squares fit to dielectric data
***        consistent with the HK74 equation and low temperatures,
***        and with the Pitz83 equation at high temperatures.
***
***          Units: T ............... K
***                 D ............... g/cm**3
***                 beta, dedP ...... bar**(-1)
***                 alpha, dedT ..... K**(-1)
***                 daldT, d2edT2 ... K**(-2) */
void JN91(T,D,beta,alpha,daldT,eps,dedP,dedT,d2edT2)
double T,D,beta,alpha,daldT,*eps,*dedP,*dedT,*d2edT2;
{  /*OK OK*/
  int i;
  double Tn,T2,T3,Tr2;
  double c[5],dcdT[5],dc2dTT[5];
  double Tref = 298.15;
  double a[10] = { 14.70333593,212.8462733,-115.4445173,19.55210915, -83.30347980,32.13240048,-6.694098645,-37.86202045,68.87359646, -27.29401652 };
  
  Tn = T / Tref;
  T2 = T * T;
  T3 = T2 * T;
  Tr2 = Tref * Tref;
  
  c[0] = 1.0;
  dcdT[0] = dc2dTT[0] = 0.0;
  
  c[1] = a[0]/Tn;
  dcdT[1] = -a[0]*Tref/T2;
  dc2dTT[1] = 2.0*a[0]*Tref/T3;
  
 
  c[2] = a[1]/Tn + a[2] + a[3]*Tn;
  dcdT[2] = -a[1]*Tref/T2 + a[3]/Tref;
  dc2dTT[2] = 2.0*a[1]*Tref/T3;
  
  c[3] = a[4]/Tn + a[5]*Tn + a[6]*Tn*Tn;
  dcdT[3] = -a[4]*Tref/T2 + a[5]/Tref + 2.0*a[6]*T/Tr2;
  dc2dTT[3] = 2.0*a[4]*Tref/T3 + 2.0*a[6]/(Tref*Tref);
  
  c[4] = a[7]/(Tn*Tn) + a[8]/Tn + a[9];
  dcdT[4] = -2.0*a[7]*Tr2/T3 - a[8]*Tref/T2;
  dc2dTT[4] = 6.0*a[7]*Tr2/(T2*T2) + 2.0*a[8]*Tref/T3;
  
  *eps = *dedP = *dedT = *d2edT2 = 0.0;
  for (i=0;i<5;i++)
    *eps += c[i]*pow(D,(double) i);
    
  for (i=0;i<5;i++)
    *dedP += i*c[i]*pow(D,(double) i);
  *dedP *= beta;
  
  for (i=0;i<5;i++)
    *dedT += pow(D,(double) i)*(dcdT[i] - i*alpha*c[i]);
    
  for (i=0;i<5;i++)
    *d2edT2 += pow(D,(double) i)*(dc2dTT[i] - i*(alpha*dcdT[i] + c[i]*daldT) - i*alpha* (dcdT[i] - i*alpha*c[i]));
    
  return;
}

/* -----------------------------------------------------------------
*** epsBrn - Compute the Z, Q, Y, and X Born functions from their
***          eps, dedP, dedT, and d2edT2 counterparts. */
void epsBrn(eps,dedP,dedT,d2edT2,Z,Q,Y,X)
double eps,dedP,dedT,d2edT2,*Z,*Q,*Y,*X;
{
  *Z = -1.0/eps;
  *Q = 1.0/(eps*eps) * dedP;
  *Y = 1.0/(eps*eps) * dedT;
  *X = 1.0/(eps*eps) * d2edT2 - 2.0*eps * (*Y) * (*Y);
  return;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.