JDFTx  1.2.0
Fex_ScalarEOS_internal.h
1 /*-------------------------------------------------------------------
2 Copyright 2011 Ravishankar Sundararaman
3 
4 This file is part of JDFTx.
5 
6 JDFTx is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 JDFTx is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with JDFTx. If not, see <http://www.gnu.org/licenses/>.
18 -------------------------------------------------------------------*/
19 
20 #ifndef JDFTX_FLUID_FEX_SCALAREOS_INTERNAL_H
21 #define JDFTX_FLUID_FEX_SCALAREOS_INTERNAL_H
22 
23 #include <core/Units.h>
24 #include <core/scalar.h>
25 
27 { double T, b;
28 
29  double vdwRadius() const
30  { return pow(3.*b/(16.*M_PI), 1./3);
31  }
32 
33  __hostanddev__ double getAhs(double N, double& Ahs_N, double Vhs) const
34  { double n3 = Vhs*N; if(n3 >= 1.) { Ahs_N = NAN; return NAN; }
35  double den = 1./(1-n3);
36  Ahs_N = T*Vhs * (den*den*den)*2*(2-n3);
37  return T * (den*den)*n3*(4-3*n3); //corresponds to Carnahan-Starling EOS
38  }
39 };
40 
42 {
43  double alpha, prefacHB, prefacVW1, prefacVW2;
44  double lambda, C1, nHB, dnHB;
45  double nc, VPzi;
46 
47  JeffereyAustinEOS_eval(double T)
48  { this->T = T;
49 
50  const double TB = 1408.4 * Kelvin; //Boyle temperature
51  const double vB = 4.1782e-5 * pow(meter,3)/mol; //Boyle volume
52  const double Tf = 273.16 * Kelvin; //Triple point temperature
53 
54  //Some of the random Jeff-Austin EOS parameters (see their paper for details)
55  alpha = 2.145*vB;
56  const double bStar = 1.0823*vB;
57  const double aVW = 0.5542 * Joule*pow(meter,3)/pow(mol,2);
58  lambda = 0.3241;
59  C1 = 0.7140;
60  nHB = (0.8447e6/18.01528) * mol/pow(meter,3);
61  dnHB = 0.1687*nHB;
62 
63  const double epsHB = -11.49 * KJoule/mol;
64  const double S0 = -61.468 * Joule/(mol*Kelvin), omega0 = exp(-S0);
65  const double SHB = -5.128 * Joule/(mol*Kelvin), omegaHB = exp(-SHB);
66  const double b1 = 0.25081;
67  const double b2 = 0.99859;
68 
69  b = vB * (0.2*exp(-21.4*pow(T/TB+0.0445,3)) - b1*exp(1.016*T/TB) + b2);
70  prefacHB = -2*T * log((omega0+omegaHB*exp(-epsHB/T))/(omega0+omegaHB)) * exp(-0.18*pow(T/Tf,8)) * (1+C1);
71  prefacVW1 = -T*alpha/(lambda*b);
72  prefacVW2 = bStar*T + aVW;
73 
74  //vapor pressure correction prefactor:
75  const double A1 = -2.9293;
76  const double A2 = 0.1572;
77  const double A5 = 1.873;
78  const double kappa = 0.8921;
79  const double Tc = 647.096*Kelvin;
80  nc = (322/18.01528) * mol/liter;
81  VPzi = A1*exp(-A5*pow(T/Tc,6)) * (pow(T/Tc - kappa, 2) + A2);
82  }
83 
84  __hostanddev__ double getVPphiInt(double n, double& VPphiInt_n) const
85  { const double A4 = 0.0610;
86  const double d0 = 1.917;
87  const double d1 = 26.01;
88  const double beta = 3.24;
89  double x = n/nc, xPowBetaM1 = pow(x, beta-1.), xPow57 = pow(x,5.7);
90  double den = 1./(d0*(1 + d0*x*(1 + d0*x)) + x*d1*xPowBetaM1);
91  double den_x = -den*den*(d0*d0*(1 + d0*x*2) + beta*d1*xPowBetaM1);
92  double expTerm = exp(-A4*xPow57*x);
93  VPphiInt_n = expTerm*(A4*xPow57*6.7*den-den_x);
94  return -nc*expTerm*den;
95  }
96 
97  //Compute the per-particle free energies at each grid point, and the gradient w.r.t the weighted density
98  __hostanddev__ void operator()(int i, const double* Nbar, double* Aex, double* Aex_Nbar, double Vhs) const
99  {
100  if(Nbar[i]<0.)
101  { Aex[i] = 0.;
102  Aex_Nbar[i] = 0.;
103  return;
104  }
105  //HB part:
106  double gaussHB = exp(pow((Nbar[i]-nHB)/dnHB,2));
107  double fHBden = C1 + gaussHB;
108  double fHBdenPrime = gaussHB * 2*(Nbar[i]-nHB)/pow(dnHB,2);
109  double AHB = prefacHB / fHBden;
110  double AHB_Nbar = -AHB * fHBdenPrime/fHBden;
111  //VW part:
112  double Ginv = 1 - lambda*b*Nbar[i]; if(Ginv<=0.0) { Aex_Nbar[i] = NAN; Aex[i]=NAN; return; }
113  double VPphiInt_Nbar, VPphiInt = getVPphiInt(Nbar[i], VPphiInt_Nbar);
114  double AVW = prefacVW1*log(Ginv) + (VPzi*VPphiInt - Nbar[i])*prefacVW2;
115  double AVW_Nbar = T*alpha/Ginv + (VPzi*VPphiInt_Nbar - 1.) * prefacVW2;
116  //FMT part:
117  double AFMT_Nbar, AFMT = getAhs(Nbar[i], AFMT_Nbar, Vhs);
118  //Total
119  Aex_Nbar[i] = AHB_Nbar + AVW_Nbar - AFMT_Nbar;
120  Aex[i] = AHB + AVW - AFMT;
121  }
122 };
123 
126 {
127  double lambda, prefacQuad, prefacVap, prefacPole;
128 
130  TaoMasonEOS_eval(double T, double Tc, double Pc, double omega)
131  { this->T = T;
132 
133  //Constants in vapor pressure correction:
134  double kappa = 1.093 + 0.26*(sqrt(0.002+omega) + 4.5*(0.002+omega));
135  double A1 = 0.143;
136  double A2 = 1.64 + 2.65*(exp(kappa-1.093)-1);
137  //Boyle temperature and volume:
138  double TB = Tc * (2.6455 - 1.1941*omega);
139  double vB = (Tc/Pc) * (0.1646 + 0.1014*omega);
140  //Temperature dependent functions:
141  const double a1 = -0.0648, a2 = 1.8067, c1 = 2.6038, c2 = 0.9726;
142  double alpha = vB*( a1*exp(-c1*T/TB) + a2*(1 - exp(-c2*pow(TB/T,0.25))) );
143  double B = (Tc/Pc) * (0.1445+omega*0.0637 + (Tc/T)*(-0.330 + (Tc/T)*(-0.1385+0.331*omega + (Tc/T)*(-0.0121-0.423*omega + pow(Tc/T,5)*(-0.000607-0.008*omega)))));
144  b = vB*( a1*(1-c1*T/TB)*exp(-c1*T/TB) + a2*(1 - (1+0.25*c2*pow(TB/T,0.25))*exp(-c2*pow(TB/T,0.25))) );
145  lambda = 0.4324 - 0.3331*omega;
146  //Coalesce prefactors for each free energy term:
147  prefacQuad = -T*(alpha - B);
148  prefacVap = prefacQuad * (-A1 * (exp(kappa*Tc/T)-A2)) / (2*sqrt(1.8)*b);
149  prefacPole = alpha*T/(lambda*b);
150  }
151 
152  //Compute the per-particle free energies at each grid point, and the gradient w.r.t the weighted density
153  __hostanddev__ void operator()(int i, const double* Nbar, double* Aex, double* Aex_Nbar, double Vhs) const
154  {
155  if(Nbar[i]<0.)
156  { Aex[i] = 0.;
157  Aex_Nbar[i] = 0.;
158  return;
159  }
160  //VW part:
161  double Ginv = 1 - lambda*b*Nbar[i]; if(Ginv<=0.0) { Aex_Nbar[i] = NAN; Aex[i]=NAN; return; }
162  double AVW = Nbar[i]*prefacQuad + prefacPole*(-log(Ginv));
163  double AVW_Nbar = prefacQuad + prefacPole*(lambda*b/Ginv);
164  //Vapor pressure correction:
165  double b2term = sqrt(1.8)*b*b;
166  double bn2term = b2term*Nbar[i]*Nbar[i];
167  double Avap = prefacVap * atan(bn2term);
168  double Avap_Nbar = prefacVap * b2term*Nbar[i]*2. / (1 + bn2term*bn2term);
169  //FMT part:
170  double AFMT_Nbar, AFMT = getAhs(Nbar[i], AFMT_Nbar, Vhs);
171  //Total
172  Aex_Nbar[i] = AVW_Nbar + Avap_Nbar - AFMT_Nbar;
173  Aex[i] = AVW + Avap - AFMT;
174  }
175 };
176 
177 #endif // JDFTX_FLUID_FEX_SCALAREOS_INTERNAL_H
ScalarField pow(const ScalarField &, double alpha)
Elementwise power (preserve input)
ScalarField sqrt(const ScalarField &)
Elementwise square root (preserve input)
const double Joule
Definition: Units.h:30
const double Kelvin
Definition: Units.h:33
const double meter
Definition: Units.h:38
ScalarField log(const ScalarField &)
Elementwise logarithm (preserve input)
double prefacVW2
prefactors to the HB and VW terms
Definition: Fex_ScalarEOS_internal.h:43
Definition: Fex_ScalarEOS_internal.h:41
const double KJoule
Definition: Units.h:31
Definition: Fex_ScalarEOS_internal.h:26
Commonly used measurement units in terms of atomic units.
const double mol
(= Avogadro number)
Definition: Units.h:46
ScalarField exp(const ScalarField &)
Elementwise exponential (preserve input)
const double liter
Definition: Units.h:39
TaoMasonEOS_eval(double T, double Tc, double Pc, double omega)
Construct the equation of state for temperature T, given critical point and acentricity (all in atomi...
Definition: Fex_ScalarEOS_internal.h:130
Tao-Mason equation of state [F. Tao and E. A. Mason, J. Chem. Phys. 100, 9075 (1994)].
Definition: Fex_ScalarEOS_internal.h:125
double b
temperature and exclusion volume
Definition: Fex_ScalarEOS_internal.h:27
double VPzi
vapor-pressure correction temperature dependent prefactor
Definition: Fex_ScalarEOS_internal.h:45