PLUTO
zeta_tables.c
Go to the documentation of this file.
1 #include "pluto.h"
2 
3 static void MakeZetaTables(double *, double *, int);
4 
5 /* Vibrational and Rotational Temperatures for molecular hydrogen */
6 #define THETA_V 6140.0
7 #define THETA_R 85.5
8 
9 /* Switch to choose the molecular hydrogen spin states.
10  * 0 : Only Para hydrogen ,
11  * 1 : Equilibrium (DEFAULT),
12  * 2 : Ortho to para ratio of 3:1. */
13 #define ORTHO_PARA_MODE 1
14 
15 /* ********************************************************************* */
16 void GetFuncDum(double T, double *funcdum_val)
17 /*!
18  * Interpolate the value of a function of \c zetaR from the table
19  * that is used to estimate the value of EH2.
20  *
21  * \param [in] T Value of temperature in kelvin.
22  * \param [out] *funcdum_val Pointer to the value of function of zetaR
23  *
24  * \return This function has no return value.
25  *
26  * \b Reference:\n
27  * D'Angelo, G. et al, ApJ 778 2013.
28  *********************************************************************** */
29 {
30  int klo, khi, kmid;
31  int nsteps = 5000;
32  double mu, Tmid, dT;
33  static double *lnT, *funcdum;
34  double y, dy;
35  int indx;
36 
37 /* -------------------------------------------
38  Make table on first call
39  ------------------------------------------- */
40 
41  if (lnT == NULL){
42  lnT = ARRAY_1D(nsteps, double);
43  funcdum = ARRAY_1D(nsteps, double);
44  MakeZetaTables(lnT, funcdum, nsteps);
45  }
46  y = log(T);
47 
48 /* -------------------------------------------------
49  Since the table has regular spacing in log T,
50  we divide by the increment to find the nearest
51  node in the table.
52  ------------------------------------------------- */
53 
54  if (y > lnT[nsteps-2]) {
55  *funcdum_val = funcdum[nsteps-2];
56  } else if (y < lnT[0]) {
57  *funcdum_val = funcdum[0];
58  } else{
59  dy = lnT[1] - lnT[0];
60  indx = floor((y - lnT[0])/dy);
61 
62  if (indx >= nsteps || indx < 0){
63  print1 ("! GetFuncDum: indx out of range, indx = %d\n",indx);
64  print1 ("! T = %12.6e\n",T);
65  QUIT_PLUTO(1);
66  }
67  *funcdum_val = (funcdum[indx]*(lnT[indx+1] - y)
68  + funcdum[indx+1]*(y - lnT[indx]))/dy;
69  }
70 }
71 
72 /* ********************************************************************* */
73 void MakeZetaTables(double *lnT, double *funcdum, int nsteps)
74 /*!
75  * Compute tables from iterative summation involed to estimate
76  * partition function of parahydrogen (\f$ \zeta_P\f$) and
77  * orthohydrogen (\f$ \zeta_O\f$) and their derivatives with respect
78  * to temperature. Then further estimate \f$\zeta_R\f$ and finally
79  * the function of \f$ \zeta_R\f$ that goes into the estimation of
80  * EH2.
81  * The partition function and its derivative can be written as
82  * \f[
83  * \left\{\begin{array}{l}
84  * \zeta = \DS \sum_i a_ie^{-b_i/T} \\ \noalign{\medskip}
85  * \zeta' = \DS \frac{1}{T^2}\sum_i a_ib_ie^{-b_i/T}
86  * \end{array}\right.
87  * \f]
88  * where <tt>i=0,2,4,...</tt> is even for parahydrogen while
89  * <tt>i=1,3,5,...</tt> is odd for orthoyhdrogen.
90  * One can see that in the limit of zero temperatures, \f$ \zeta_P \to 1,
91  * \, \zeta'_P \to 0\f$ while \f$\zeta_O\to 0,\,\zeta'_O\to0\f$.
92  * Then \f$ \zeta'_O/\zeta_O\f$ is ill-defined in the low temperature limit
93  * since it becomes \c 0/0.
94  * To avoid this, we rewrite \c zetaO by extracting the first term from
95  * the summation:
96  * \f[
97  * \left\{\begin{array}{l}
98  * \zeta_O = \DS e^{-b_1/T}\sum_i a_ie^{-\Delta b_i/T} \\ \noalign{\medskip}
99  * \zeta'_O = \DS \frac{1}{T^2}e^{-b_1/T}
100  * \left[ b_1 \sum_i a_ie^{-\Delta b_i/T}
101  * +\sum_i a_i\Delta b_ie^{-\Delta b_i/T}\right]
102  * \end{array}\right.
103  * \f]
104  * where \f$\Delta b_i = b_i-b_1\f$.
105  * Taking the ratio:
106  * \f[
107  * \frac{\zeta'_O}{\zeta_O} = \frac{1}{T^2}
108  * \frac{ b_1 \sum_i a_ie^{-\Delta b_i/T}
109  * + \sum_i a_i\Delta b_ie^{-\Delta b_i/T}}
110  * {\sum_i a_ie^{-\Delta b_i/T}}
111  * \qquad\Longrightarrow\qquad
112  * \frac{\zeta'_O}{\zeta_O} - \frac{b_1}{T^2}= \frac{1}{T^2}
113  * \frac{\sum_i a_i\Delta b_ie^{-\Delta b_i/T}}
114  * {\sum_i a_ie^{-\Delta b_i/T}} \to 0 \quad{\rm as}\quad T\to 0
115  * \f]
116  * The expression on the right (that appears in the computation of
117  * \f$\zeta'_R\f$) is now well-behaved and it reproduces the
118  * low temperature limit correctly.
119  * You can convince yourself by playing with the following MAPLE script
120  * \code
121  restart;
122  a[0] := 1; a[1] := 3; a[2] := 5; a[3] := 7;
123  b[0] := 0; b[1] := 2*theta; b[2] := 6*theta; b[3] := 12*theta;
124 
125  zeta[P] := a[0]*exp(-b[0]*y) + a[2]*exp(-b[2]*y);
126  dzeta[P] := y^2*(a[0]*b[0]*exp(-b[0]*y) + a[2]*b[2]*exp(-b[2]*y));
127 
128  zeta[O] := a[1]*exp(-b[1]*y) + a[3]*exp(-b[3]*y);
129  dzeta[O] := y^2*(a[1]*b[1]*exp(-b[1]*y) + a[3]*b[3]*exp(-b[3]*y));
130  rP := dzeta[P]/zeta[P];
131  rO := dzeta[O]/zeta[O];
132 
133  rOminus := rO - b[1]*y^2;
134  simplify(rOminus);
135  * \endcode
136  *
137  *
138  * \param [in] lnT Array of Logrithmic values of Gas
139  * temperatures from 0.01 K to 10^12 K.
140  * \param [in] nsteps Number of equal spacings in T.
141  * \param [out] funcdum The function of zetaR that goes into EH2.
142  *
143  * \return This function has no return value
144  *
145  * \b Reference: \n
146  * - D'Angelo, G. et. al ApJ 778, 2013 (Eq. 23)
147  *
148  *********************************************************************** */
149 {
150  int i,j;
151  double Temp0 = 0.01*T_CUT_RHOE;
152  double Tmax = 1.0e12;
153  double dy = log(Tmax/Temp0)*(1./nsteps);
154  double dT = Temp0*exp(dy);
155  double T, a, b, b1, scrh, inv_T2;
156  double zetaP, dzetaP, zetaO, dzetaO, zetaR, dzetaR;
157  double dum1, dum2, dum3;
158  double alpha, beta, gamma;
159  double dzO_zO_m, db, sum1, sum2;
160 
161  print1 ("> MakeZetaTables(): generating Zeta tables...\n");
162 
163  if (ORTHO_PARA_MODE == 0){
164  alpha = 1.0; beta = 0.0; gamma = 0.0;
165  }else if(ORTHO_PARA_MODE == 2){
166  alpha = 0.25; beta = 0.75; gamma = 0.0;
167  }else{
168  alpha = 1.0; beta = 0.0; gamma = 1.0;
169  }
170 
171  b1 = 2.0*THETA_R;
172  for(j = 0; j < nsteps; j++){
173  T = Temp0*exp(j*dy);
174  inv_T2 = 1.0/(T*T);
175  zetaO = zetaP = dzetaP = dzetaO = 0.0;
176  dzO_zO_m = sum1 = sum2 = 0.0;
177  for(i = 0; i <= 10000; i++){
178  a = 2*i + 1;
179  b = i*(i + 1)*THETA_R;
180  if (i%2 == 0){
181  scrh = a*exp(-b/T);
182  zetaP += scrh;
183  dzetaP += scrh*b;
184  }else{
185  db = b - b1;
186  scrh = a*exp(-db/T);
187  sum1 += scrh;
188  sum2 += scrh*db;
189  }
190  }
191  dzetaP *= inv_T2;
192 
193  zetaO = exp(-b1/T)*sum1;
194  dzetaO = exp(-b1/T)*(b1*sum1 + sum2)*inv_T2;
195 
196  dzO_zO_m = sum2/sum1*inv_T2; /* = zeta'(O)/zeta(O) - 2*theta/T^2 */
197 
198  lnT[j] = log(T);
199 
200  /* -----------------------------------------
201  Compute table
202  ----------------------------------------- */
203 
204  scrh = zetaO*exp(2.0*THETA_R/T);
205 
206  zetaR = pow(zetaP,alpha)*pow(scrh,beta) + 3.0*gamma*zetaO;
207  dzetaR = (zetaR - 3.0*gamma*zetaO)*(alpha*(dzetaP/zetaP) +
208  beta*dzO_zO_m) + 3.0*gamma*dzetaO;
209  dum1 = THETA_V/T;
210  dum2 = dum1*exp(-dum1)/(1.0 - exp(-dum1));
211  dum3 = (T/zetaR)*dzetaR;
212  funcdum[j] = 1.5 + dum2 + dum3;
213  }
214 }
215 
static double alpha
Definition: init.c:3
static double a
Definition: init.c:135
tuple T
Definition: Sph_disk.py:33
#define T_CUT_RHOE
Sets the lowest cut-off temperature used in the PVTE_LAW equation of state.
Definition: eos.h:69
void print1(const char *fmt,...)
Definition: amrPluto.cpp:511
tuple scrh
Definition: configure.py:200
static void MakeZetaTables(double *, double *, int)
Definition: zeta_tables.c:73
#define THETA_R
Definition: zeta_tables.c:7
#define THETA_V
Definition: zeta_tables.c:6
void GetFuncDum(double T, double *funcdum_val)
Definition: zeta_tables.c:16
int j
Definition: analysis.c:2
PLUTO main header file.
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
int i
Definition: analysis.c:2
#define ORTHO_PARA_MODE
Definition: zeta_tables.c:13
#define QUIT_PLUTO(e_code)
Definition: macros.h:125