LALSimulation  5.4.0.1-fe68b98
LALSimNeutronStarEOSPiecewisePolytrope.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 J. Creighton, B. Lackey
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with with program; see the file COPYING. If not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  * MA 02110-1301 USA
18  */
19 /**
20  * @addtogroup LALSimNeutronStarEOS_c
21  * @{
22  */
23 /**
24  * @name Creation routines for piecewise polytrope equations of state
25  * @{
26  */
27 
28 /** @cond */
29 
30 /* Store data for generating polytropic EOS so you don't have to reevaluate it
31  * every time. */
32 /* Accepts up to 100 polytrope pieces. */
33 enum {N_POLY_MAX = 100};
34 struct tagLALSimNeutronStarEOSDataPiecewisePolytrope {
35  int nPoly; /* number of polytrope pieces */
36  double rhoTab[N_POLY_MAX]; /* starting rest-mass density of polytropic piece i (kg/m^3) */
37  double epsilonTab[N_POLY_MAX]; /* starting energy density of polytropic piece i (J/m^3) */
38  double pTab[N_POLY_MAX]; /* starting pressure of polytropic piece i (Pa, J/m^3) */
39  double kTab[N_POLY_MAX]; /* polytropic constant of piece i */
40  double gammaTab[N_POLY_MAX]; /* adiabatic index of piece i */
41  double nTab[N_POLY_MAX]; /* polytropic index n_i = 1/(Gamma_i - 1) */
42  double aTab[N_POLY_MAX]; /* integration constant (Eq. 3) of PRD 79, 124032 (2009) */
43  double hTab[N_POLY_MAX]; /* dimensionless pseudo-enthalpy = ln(specific enthalpy/c^2) */
44 };
45 
46 /* FUNCTIONS OF PSEUDO-ENTHALPY */
47 
48 /* Determine which polytrope piece you are in. */
49 /* hTab[i] is starting pseudo-enthalpy of polytropic piece i */
50 static int polytrope_index_of_h(double h, LALSimNeutronStarEOS * eos)
51 {
52  int i = eos->data.piecewisePolytrope->nPoly - 1;
53 
54  while (h <= eos->data.piecewisePolytrope->hTab[i] && i > 0)
55  i--;
56 
57  return i;
58 }
59 
60 /* Rest-mass density as a function of pseudo-enthalpy h */
61 static double eos_rho_of_h_piecewise_polytrope(double h,
63 {
64  int i = polytrope_index_of_h(h, eos); /* index for polytrope piece */
65  double enthalpy = exp(h); /* the real enthalpy */
66  double k_i = eos->data.piecewisePolytrope->kTab[i];
67  double n_i = eos->data.piecewisePolytrope->nTab[i];
68  double a_i = eos->data.piecewisePolytrope->aTab[i];
69  double num, den;
70 
71  num = enthalpy - 1.0 - a_i;
72  den = (n_i + 1.0) * k_i; /* never 0 */
73 
74  return pow(num / den, n_i);
75 }
76 
77 /* Pressure as a function of pseudo-enthalpy h */
78 static double eos_p_of_h_piecewise_polytrope(double h,
80 {
81  int i = polytrope_index_of_h(h, eos); /* index for polytrope piece */
82  double enthalpy = exp(h); /* the real enthalpy */
83  double k_i = eos->data.piecewisePolytrope->kTab[i];
84  double n_i = eos->data.piecewisePolytrope->nTab[i];
85  double a_i = eos->data.piecewisePolytrope->aTab[i];
86  double num, den;
87 
88  num = enthalpy - 1.0 - a_i;
89  den = (n_i + 1.0) * k_i; /* never 0 */
90 
91  return k_i * pow(num / den, n_i + 1.0);
92 }
93 
94 /* Energy density as a function of pseudo-enthalpy h */
95 static double eos_e_of_h_piecewise_polytrope(double h,
97 {
98  int i = polytrope_index_of_h(h, eos); /* index for polytrope piece */
99  double n_i = eos->data.piecewisePolytrope->nTab[i];
100  double a_i = eos->data.piecewisePolytrope->aTab[i];
101  double enthalpy = exp(h); /* the real enthalpy */
102  double rho = eos_rho_of_h_piecewise_polytrope(h, eos);
103 
104  double num = 1.0 + a_i + n_i * enthalpy;
105  double den = n_i + 1.0; /* never 0 */
106 
107  return rho * num / den;
108 }
109 
110 ///* depsilon/dp blows up as h->0 and enthalpy->1 */
111 //static double eos_dedp_of_h_piecewise_polytrope(double h, LALSimNeutronStarEOS *eos)
112 //{
113 // int i = polytrope_index_of_h(h, eos); /* index for polytrope piece */
114 // double enthalpy = exp(h); /* specific enthalpy */
115 // double n_i = eos->data.piecewisePolytrope->nTab[i];
116 // double a_i = eos->data.piecewisePolytrope->aTab[i];
117 //
118 // return (n_i*enthalpy)/(enthalpy - 1.0 - a_i);
119 //}
120 
121 /* v=sqrt(dp/depsilon)->0 as h->0 and enthalpy->1 */
122 static double eos_v_of_h_piecewise_polytrope(double h,
123  LALSimNeutronStarEOS * eos)
124 {
125  int i = polytrope_index_of_h(h, eos); /* index for polytrope piece */
126  double enthalpy = exp(h); /* specific enthalpy */
127  double n_i = eos->data.piecewisePolytrope->nTab[i];
128  double a_i = eos->data.piecewisePolytrope->aTab[i];
129 
130  return sqrt((enthalpy - 1.0 - a_i) / (n_i * enthalpy));
131 }
132 
133 /* FUNCTIONS OF PRESSURE */
134 
135 /* Determine which polytrope piece you are in. */
136 /* pTab[i] is starting pressure of polytropic piece i */
137 static int polytrope_index_of_p(double p, LALSimNeutronStarEOS * eos)
138 {
139  int i = eos->data.piecewisePolytrope->nPoly - 1;
140 
141  while (p <= eos->data.piecewisePolytrope->pTab[i] && i > 0)
142  i--;
143 
144  return i;
145 }
146 
147 static double eos_h_of_p_piecewise_polytrope(double p,
148  LALSimNeutronStarEOS * eos)
149 {
150  int i = polytrope_index_of_p(p, eos); /* index for polytrope piece */
151  double k_i = eos->data.piecewisePolytrope->kTab[i];
152  double n_i = eos->data.piecewisePolytrope->nTab[i];
153  double a_i = eos->data.piecewisePolytrope->aTab[i];
154 
155  double enthalpy =
156  1.0 + a_i + (n_i + 1.0) * k_i * pow(p / k_i, 1.0 / (n_i + 1.0));
157 
158  // printf("%d\t%e\t%e\t%e\t%e\n", i, k_i, n_i, a_i, log(enthalpy));
159 
160  return log(enthalpy); /* convert from real enthalpy to pseudo-enthalpy h */
161 }
162 
163 //static double eos_rho_of_p_piecewise_polytrope(double p, LALSimNeutronStarEOS *eos)
164 //{
165 // int i = polytrope_index_of_p(p, eos); /* index for polytrope piece */
166 // double k_i = eos->data.piecewisePolytrope->kTab[i];
167 // double n_i = eos->data.piecewisePolytrope->nTab[i];
168 //
169 // return pow(p/k_i, n_i/(n_i+1.0));
170 //}
171 
172 static double eos_e_of_p_piecewise_polytrope(double p,
173  LALSimNeutronStarEOS * eos)
174 {
175  double rho;
176  int i = polytrope_index_of_p(p, eos); /* index for polytrope piece */
177  double k_i = eos->data.piecewisePolytrope->kTab[i];
178  double n_i = eos->data.piecewisePolytrope->nTab[i];
179  double a_i = eos->data.piecewisePolytrope->aTab[i];
180 
181  rho = pow(p / k_i, n_i / (n_i + 1.0));
182 
183  return (1.0 + a_i) * rho + n_i * p;
184 }
185 
186 /* depsilon/dp blows up as p->0 */
187 static double eos_dedp_of_p_piecewise_polytrope(double p,
188  LALSimNeutronStarEOS * eos)
189 {
190  double epsilon;
191  int i = polytrope_index_of_p(p, eos); /* index for polytrope piece */
192  double gamma_i = eos->data.piecewisePolytrope->gammaTab[i];
193 
194  epsilon = eos_e_of_p_piecewise_polytrope(p, eos);
195 
196  return (epsilon + p) / (gamma_i * p); /* returns nan at p=0 */
197 }
198 
199 ///* v=sqrt(dp/depsilon)->0 as p->0 */
200 //static double eos_v_of_p_piecewise_polytrope(double p, LALSimNeutronStarEOS *eos)
201 //{
202 // double epsilon;
203 // int i = polytrope_index_of_p(p, eos); /* index for polytrope piece */
204 // double gamma_i = eos->data.piecewisePolytrope->gammaTab[i];
205 //
206 // epsilon = eos_e_of_p_piecewise_polytrope(p, eos);
207 //
208 // return sqrt( (gamma_i*p)/(epsilon + p) ); /* currently nan at p=0*/
209 //}
210 
211 
212 static void eos_free_piecewise_polytrope(LALSimNeutronStarEOS * eos)
213 {
214  if (eos) {
215  LALFree(eos->data.piecewisePolytrope);
216  LALFree(eos);
217  }
218 }
219 
220 
221 /* Minimum pseudo-enthalpy at which EOS becomes acausal (speed of sound > 1).
222  * If the EOS is always causal, return some large value hmax instead. */
223 static double eos_min_acausal_pseudo_enthalpy_piecewise_polytrope(double hmax,
224  LALSimNeutronStarEOS * eos)
225 {
226  int i;
227  int nPoly = eos->data.piecewisePolytrope->nPoly;
228  double n_i, a_i, h_i, h_ip1;
229  double vSound;
230  double enthalpyMinAcausal;
231  double hMinAcausal = hmax; /* default large number for EOS that is always causal */
232 
233  /* For each polytrope piece, speed of sound increases monotonically. */
234  /* If v > 1 at beginning of piece, hMinAcausal = h_i */
235  /* If v > 1 at end of piece, then find where v = 1 in this piece. */
236  /* If v !> 1 at end of piece, then EOS is always causal in this piece. */
237 
238  for (i = 0; i < nPoly; i++) {
239  n_i = eos->data.piecewisePolytrope->nTab[i];
240  a_i = eos->data.piecewisePolytrope->aTab[i];
241  h_i = eos->data.piecewisePolytrope->hTab[i];
242 
243  /* find vSound at beginning of polytrope piece */
244  if (i == 0)
245  vSound = 0.0;
246  else
247  vSound = eos_v_of_h_piecewise_polytrope(h_i, eos);
248  if (vSound > 1.0) { /* there is a discontinuity in vSound at h = h_i and it first becomes >1 here */
249  hMinAcausal = h_i;
250  break; /* You have hMinAcausal. You're done. Get out of for loop. */
251  }
252 
253  /* find vSound at end of polytrope piece */
254  if (i == nPoly - 1) {
255  vSound = 1 / n_i; /* vSound at h = infinity */
256  } else {
257  h_ip1 = eos->data.piecewisePolytrope->hTab[i + 1]; /* not defined for i = nPoly-1 */
258  vSound = eos_v_of_h_piecewise_polytrope(h_ip1, eos);
259  }
260  if (vSound > 1) { /* find the density within this polytrope piece where EOS first becomes acausal */
261  enthalpyMinAcausal = (1 + a_i) / (1 - n_i); /* v = 1 here */
262  hMinAcausal = log(enthalpyMinAcausal);
263  break; /* You have hMinAcausal. You're done. Get out of for loop. */
264  }
265  }
266 
267  /* Value of h where EOS first becomes acausal. */
268  /* Or, if EOS is always causal, hmax */
269  return hMinAcausal;
270 }
271 
272 #if 0
273 static void
274 print_piecewise_polytrope_data(LALSimNeutronStarEOSDataPiecewisePolytrope *
275  data)
276 {
277  int i;
278 
279  printf("nPoly = %d\n", data->nPoly);
280 
281  printf("i =\t\t");
282  for (i = 0; i < data->nPoly; i++)
283  printf("%d\t\t", i);
284  printf("\n");
285 
286  printf("rhoTab[i] =\t");
287  for (i = 0; i < data->nPoly; i++)
288  printf("%e\t", data->rhoTab[i]);
289  printf("\n");
290 
291  printf("epsilonTab[i] =\t");
292  for (i = 0; i < data->nPoly; i++)
293  printf("%e\t", data->epsilonTab[i]);
294  printf("\n");
295 
296  printf("pTab[i] =\t");
297  for (i = 0; i < data->nPoly; i++)
298  printf("%e\t", data->pTab[i]);
299  printf("\n");
300 
301  printf("kTab[i] =\t");
302  for (i = 0; i < data->nPoly; i++)
303  printf("%e\t", data->kTab[i]);
304  printf("\n");
305 
306  printf("gammaTab[i] =\t");
307  for (i = 0; i < data->nPoly; i++)
308  printf("%e\t", data->gammaTab[i]);
309  printf("\n");
310 
311  printf("nTab[i] =\t");
312  for (i = 0; i < data->nPoly; i++)
313  printf("%e\t", data->nTab[i]);
314  printf("\n");
315 
316  printf("aTab[i] =\t");
317  for (i = 0; i < data->nPoly; i++)
318  printf("%e\t", data->aTab[i]);
319  printf("\n");
320 
321  printf("hTab[i] =\t");
322  for (i = 0; i < data->nPoly; i++)
323  printf("%e\t", data->hTab[i]);
324  printf("\n");
325 }
326 #endif
327 
328 /** @endcond */
329 
330 /* GLOBAL FUNCTIONS */
331 
332 /**
333  * @brief Creates a polytrope Equation of State defined by p = K rho^Gamma.
334  * @param Gamma Polytrope adiabatic index.
335  * @param reference_pressure_si Reference pressure in Pa.
336  * @param reference_density_si Density at the reference pressure in kg/m^3.
337  * @return A pointer to a newly created EOS structure.
338  */
340  double reference_pressure_si, double reference_density_si)
341 {
343  LALSimNeutronStarEOSDataPiecewisePolytrope *data;
344 
345  /* reference pressure, density in geometric units of m^-2 */
346  double p = reference_pressure_si * LAL_G_C4_SI;
347  double rho = reference_density_si * LAL_G_C2_SI;
348 
349  eos = LALCalloc(1, sizeof(*eos));
350  data = LALCalloc(1, sizeof(*data));
351 
352  eos->datatype = LALSIM_NEUTRON_STAR_EOS_DATA_TYPE_PIECEWISE_POLYTROPE;
353  eos->data.piecewisePolytrope = data;
354  if(snprintf(eos->name, sizeof(eos->name),
355  "Gamma=%g Polytrope (p=%g Pa @ rho=%g kg/m^3)", Gamma,
356  reference_pressure_si, reference_density_si) >= (signed) sizeof(eos->name))
357  XLAL_PRINT_WARNING("EOS name too long");
358 
359  /* setup function pointers */
360  eos->free = eos_free_piecewise_polytrope;
361  eos->e_of_p = eos_e_of_p_piecewise_polytrope;
362  eos->h_of_p = eos_h_of_p_piecewise_polytrope;
363  eos->e_of_h = eos_e_of_h_piecewise_polytrope;
364  eos->rho_of_h = eos_rho_of_h_piecewise_polytrope;
365  eos->p_of_h = eos_p_of_h_piecewise_polytrope;
366  eos->dedp_of_p = eos_dedp_of_p_piecewise_polytrope;
367  eos->v_of_h = eos_v_of_h_piecewise_polytrope;
368 
369  /* calculate all the quantities (rho, epsilon, p, k, gamma, n, a, h) in data structure */
370  eos->data.piecewisePolytrope->nPoly = 1;
371  eos->data.piecewisePolytrope->rhoTab[0] = 0.0;
372  eos->data.piecewisePolytrope->epsilonTab[0] = 0.0;
373  eos->data.piecewisePolytrope->pTab[0] = 0.0;
374  eos->data.piecewisePolytrope->kTab[0] = p / pow(rho, Gamma);
375  eos->data.piecewisePolytrope->gammaTab[0] = Gamma;
376  eos->data.piecewisePolytrope->nTab[0] = 1.0 / (Gamma - 1.0);
377  eos->data.piecewisePolytrope->aTab[0] = 0.0;
378  eos->data.piecewisePolytrope->hTab[0] = 0.0;
379 
380  /* maximum pressure, pseudo-enthalpy to use for generating mass-radius curves */
381  eos->pmax = 10.0 * LAL_NUCLEAR_DENSITY_GEOM_SI;
382  eos->hmax = eos_h_of_p_piecewise_polytrope(eos->pmax, eos);
383  /* smallest pseudo-enthalpy where EOS becomes acausal */
384  eos->hMinAcausal =
385  eos_min_acausal_pseudo_enthalpy_piecewise_polytrope(eos->hmax, eos);
386 
387 #if 0
388  print_piecewise_polytrope_data(eos->data.piecewisePolytrope);
389  printf("datatype = %d\n", eos->datatype);
390  printf("pmax = %e\n", eos->pmax);
391  printf("hmax = %e\n", eos->hmax);
392  printf("hMinAcausal = %e\n", eos->hMinAcausal);
393 #endif
394 
395  return eos;
396 }
397 
398 /* In retrospect, the naming of the dividing densities (rho0, rho1, rho2) and adiabatic indices (gamma1, gamma2, gamma3) are not consistent */
399 /**
400  * @brief Creates a 4-parameter piecewise-polytrope Equation of State.
401  * @details A 4-piece piecewise polytrope as described in
402  * Physical Review D 79, 124032 (2009) in which the low-density part is
403  * fit to the SLY4 EOS. The remaining pieces are described by adiabatic
404  * indices gamma1, gamma2, and gamma3, where gamma1 is the adiabatic index
405  * for densities < 10^17.7 kg/m^3, gamma2 is the adiabatic index for densities
406  * in the range 10^17.7 kg/m^3 to 10^18 kg/m^3, and gamma3 is the adiabatic
407  * index for densities > 10^18 kg/m^3. The base-10 logarithm of the pressure in
408  * Pa at a density of 10^17.7 kg/m^3 is specified by logp1_si.
409  * @param logp1_si Base 10 logarithm of the pressure in Pa at the reference
410  * density of 10^17.7 kg/m^3.
411  * @param gamma1 Adiabatic index for densities below 10^17.7 kg/m^3.
412  * @param gamma2 Adiabatic index for densities from 10^17.7 kg/m^3
413  * to 10^18 kg/m^3.
414  * @param gamma3 Adiabatic index for densities above 10^18 kg/m^3.
415  * @return A pointer to a newly created EOS structure.
416  */
418  logp1_si, double gamma1, double gamma2, double gamma3)
419 {
421  LALSimNeutronStarEOSDataPiecewisePolytrope *data;
422 
423  /* Data for the 4-piece piecewise polytrope fit to the low-density part of
424  * the SLY4 EOS. Pressure is defined in Pa (N/m^2), and rest-mass density
425  * is in kg/m^3. In the paper PRD 79, 124032 (2009) which used cgs, the
426  * k_i values in Table II should be multiplied by c^2. */
427  double rhoLow[] = { 0, 2.44033979e10, 3.78358138e14, 2.62780487e15 };
428  double kLow[] =
429  { 1.0801158752700761e7, 1.311359898998385e10, 6.507604807550857e19,
430  3.053461077133694e8 };
431  double gammaLow[] = { 1.58424999, 1.28732904, 0.62223344, 1.35692395 };
432 
433  /*
434  * These are the cgs values:
435  * double rhoLow[] = {0, 2.44033979e7, 3.78358138e11, 2.62780487e12};
436  * double kLow[] = {6.11252036792443e12, 9.54352947022931e14, 4.787640050002652e22, 3.593885515256112e13};
437  * double gammaLow[] = {1.58424999, 1.28732904, 0.62223344, 1.35692395};
438  */
439 
440  double rho0, rho1, rho2;
441  double p1; /* pressure at 10^17.7 kg/m^3 */
442  double p1min; /* Minimum allowed value of p1 s.t. high density EOS has larger pressure than low density EOS */
443  double k1, k2, k3;
444  double rhoJoin1, rhoJoin2, pJoin1, pJoin2, gammaJoin, kJoin; /* constants for extra polytrope if it's needed */
445  int i;
446  double k_i, rho_i, gamma_i, p_i, n_i, a_i, a_im1, n_im1, epsilon_i,
447  enthalpy_i, h_i;
448 
449  if (gamma1 <= 1.0 || gamma2 <= 1.0 || gamma3 <= 1.0)
451  "Adiabatic indices gamma1=%g, gamma2=%g, and gamma3=%g "
452  "must all be greater than 1", gamma1, gamma2, gamma3);
453 
454  /* Transition densities between the 3 high-density polytropes */
455  rho1 = pow(10, 17.7);
456  rho2 = pow(10, 18.0);
457 
458  /* pressure at rho1 */
459  p1 = pow(10, logp1_si);
460 
461  /* pressure constants */
462  k1 = p1 / pow(rho1, gamma1);
463  k2 = p1 / pow(rho1, gamma2);
464  k3 = k2 * pow(rho2, gamma2 - gamma3);
465 
466  /* Calculate the variable joining density rho0 between the high and low
467  * density EOS */
468  rho0 = pow(kLow[3] / k1, 1.0 / (gamma1 - gammaLow[3]));
469 
470  p1min = kLow[3] * pow(rho1, gammaLow[3]);
471  if (logp1_si < log10(p1min) || logp1_si > 34.5)
473  "logp1_si=%g should be between %g and 34.5", logp1_si,
474  log10(p1min));
475 
476  /* allocate memory */
477  eos = LALCalloc(1, sizeof(*eos));
478  data = LALCalloc(1, sizeof(*data));
479 
480  eos->datatype = LALSIM_NEUTRON_STAR_EOS_DATA_TYPE_PIECEWISE_POLYTROPE;
481  eos->data.piecewisePolytrope = data;
482 
483  if(snprintf(eos->name, sizeof(eos->name), "4-Piece Poly (p1=10^%.4g Pa,"
484  "G1=%.4g,G2=%.4g,G3=%.4g)", logp1_si, gamma1, gamma2, gamma3) >= (int) sizeof(eos->name))
485  XLAL_PRINT_WARNING("EOS name too long");
486 
487  /* setup function pointers */
488  eos->free = eos_free_piecewise_polytrope;
489  eos->e_of_p = eos_e_of_p_piecewise_polytrope;
490  eos->h_of_p = eos_h_of_p_piecewise_polytrope;
491  eos->e_of_h = eos_e_of_h_piecewise_polytrope;
492  eos->rho_of_h = eos_rho_of_h_piecewise_polytrope;
493  eos->p_of_h = eos_p_of_h_piecewise_polytrope;
494  eos->dedp_of_p = eos_dedp_of_p_piecewise_polytrope;
495  eos->v_of_h = eos_v_of_h_piecewise_polytrope;
496 
497 
498  /* Add another polytrope if the joining density is below the start of the
499  * last low density polytrope or above the end of the first high density
500  * polytrope. */
501  if ((rho0 > rhoLow[3]) && (rho0 < rho1)) {
502  /* No issue. There will be a total of 7 polytropes. */
503 
504  eos->data.piecewisePolytrope->kTab[0] = kLow[0];
505  eos->data.piecewisePolytrope->kTab[1] = kLow[1];
506  eos->data.piecewisePolytrope->kTab[2] = kLow[2];
507  eos->data.piecewisePolytrope->kTab[3] = kLow[3];
508  eos->data.piecewisePolytrope->kTab[4] = k1;
509  eos->data.piecewisePolytrope->kTab[5] = k2;
510  eos->data.piecewisePolytrope->kTab[6] = k3;
511 
512  eos->data.piecewisePolytrope->gammaTab[0] = gammaLow[0];
513  eos->data.piecewisePolytrope->gammaTab[1] = gammaLow[1];
514  eos->data.piecewisePolytrope->gammaTab[2] = gammaLow[2];
515  eos->data.piecewisePolytrope->gammaTab[3] = gammaLow[3];
516  eos->data.piecewisePolytrope->gammaTab[4] = gamma1;
517  eos->data.piecewisePolytrope->gammaTab[5] = gamma2;
518  eos->data.piecewisePolytrope->gammaTab[6] = gamma3;
519 
520  eos->data.piecewisePolytrope->rhoTab[0] = rhoLow[0];
521  eos->data.piecewisePolytrope->rhoTab[1] = rhoLow[1];
522  eos->data.piecewisePolytrope->rhoTab[2] = rhoLow[2];
523  eos->data.piecewisePolytrope->rhoTab[3] = rhoLow[3];
524  eos->data.piecewisePolytrope->rhoTab[4] = rho0;
525  eos->data.piecewisePolytrope->rhoTab[5] = rho1;
526  eos->data.piecewisePolytrope->rhoTab[6] = rho2;
527 
528  eos->data.piecewisePolytrope->nPoly = 7;
529 
530  } else {
531  /* You have to add an 8th polytrope between gammaLow[3] and gamma1. */
532  /* It will be between the densities rhoJoin1 and rhoJoin2. */
533  rhoJoin1 = 5.0e15;
534  rhoJoin2 = 1.0e16;
535 
536  /* Calculate the pressure at the start and end densities. */
537  pJoin1 = kLow[3] * pow(rhoJoin1, gammaLow[3]);
538  pJoin2 = k1 * pow(rhoJoin2, gamma1);
539 
540  /* Calculate K and Gamma for the joining polytrope */
541  gammaJoin = log(pJoin2 / pJoin1) / log(rhoJoin2 / rhoJoin1);
542 
543  kJoin = pJoin1 / pow(rhoJoin1, gammaJoin);
544 
545  /* Now join all 8 polytropes. */
546  eos->data.piecewisePolytrope->kTab[0] = kLow[0];
547  eos->data.piecewisePolytrope->kTab[1] = kLow[1];
548  eos->data.piecewisePolytrope->kTab[2] = kLow[2];
549  eos->data.piecewisePolytrope->kTab[3] = kLow[3];
550  eos->data.piecewisePolytrope->kTab[4] = kJoin;
551  eos->data.piecewisePolytrope->kTab[5] = k1;
552  eos->data.piecewisePolytrope->kTab[6] = k2;
553  eos->data.piecewisePolytrope->kTab[7] = k3;
554 
555  eos->data.piecewisePolytrope->gammaTab[0] = gammaLow[0];
556  eos->data.piecewisePolytrope->gammaTab[1] = gammaLow[1];
557  eos->data.piecewisePolytrope->gammaTab[2] = gammaLow[2];
558  eos->data.piecewisePolytrope->gammaTab[3] = gammaLow[3];
559  eos->data.piecewisePolytrope->gammaTab[4] = gammaJoin;
560  eos->data.piecewisePolytrope->gammaTab[5] = gamma1;
561  eos->data.piecewisePolytrope->gammaTab[6] = gamma2;
562  eos->data.piecewisePolytrope->gammaTab[7] = gamma3;
563 
564  eos->data.piecewisePolytrope->rhoTab[0] = rhoLow[0];
565  eos->data.piecewisePolytrope->rhoTab[1] = rhoLow[1];
566  eos->data.piecewisePolytrope->rhoTab[2] = rhoLow[2];
567  eos->data.piecewisePolytrope->rhoTab[3] = rhoLow[3];
568  eos->data.piecewisePolytrope->rhoTab[4] = rhoJoin1;
569  eos->data.piecewisePolytrope->rhoTab[5] = rhoJoin2;
570  eos->data.piecewisePolytrope->rhoTab[6] = rho1;
571  eos->data.piecewisePolytrope->rhoTab[7] = rho2;
572 
573  eos->data.piecewisePolytrope->nPoly = 8;
574 
575  XLAL_PRINT_INFO("An extra polytrope was used to join the low and high density regions.");
576  }
577 
578  /* convert to geometric units and place in piecwisePolytrope structure */
579  for (i = 0; i < eos->data.piecewisePolytrope->nPoly; i++) {
580  eos->data.piecewisePolytrope->rhoTab[i] *= LAL_G_C2_SI;
581  gamma_i = eos->data.piecewisePolytrope->gammaTab[i];
582  eos->data.piecewisePolytrope->kTab[i] *=
583  pow(LAL_G_SI, 1.0 - gamma_i) * pow((double)LAL_C_SI,
584  2.0 * gamma_i - 4.0);
585  }
586 
587  /* calculate remaining quantities (p, n, a, epsilon, h) in data structure */
588  for (i = 0; i < eos->data.piecewisePolytrope->nPoly; i++) {
589  k_i = eos->data.piecewisePolytrope->kTab[i];
590  rho_i = eos->data.piecewisePolytrope->rhoTab[i];
591  gamma_i = eos->data.piecewisePolytrope->gammaTab[i];
592 
593  p_i = k_i * pow(rho_i, gamma_i);
594  n_i = 1.0 / (gamma_i - 1.0);
595 
596  if (i == 0) {
597  a_i = 0.0;
598  } else {
599  a_im1 = eos->data.piecewisePolytrope->aTab[i - 1];
600  n_im1 = eos->data.piecewisePolytrope->nTab[i - 1];
601  a_i = a_im1 + (n_im1 - n_i) * p_i / rho_i;
602  }
603 
604  epsilon_i = (1.0 + a_i) * rho_i + n_i * p_i;
605 
606  if (i == 0) {
607  enthalpy_i = 1.0; /* p/rho -> 0 as rho -> 0, and a_0 = 0 */
608  } else {
609  enthalpy_i = 1.0 + a_i + (n_i + 1) * p_i / rho_i;
610  }
611  h_i = log(enthalpy_i);
612 
613  eos->data.piecewisePolytrope->pTab[i] = p_i;
614  eos->data.piecewisePolytrope->nTab[i] = n_i;
615  eos->data.piecewisePolytrope->aTab[i] = a_i;
616  eos->data.piecewisePolytrope->epsilonTab[i] = epsilon_i;
617  eos->data.piecewisePolytrope->hTab[i] = h_i;
618  }
619 
620  eos->pmax = 10.0 * LAL_NUCLEAR_DENSITY_GEOM_SI;
621  eos->hmax = eos_h_of_p_piecewise_polytrope(eos->pmax, eos);
622  eos->hMinAcausal =
623  eos_min_acausal_pseudo_enthalpy_piecewise_polytrope(eos->hmax, eos);
624 
625 #if 0
626  print_piecewise_polytrope_data(eos->data.piecewisePolytrope);
627  printf("datatype = %d\n", eos->datatype);
628  printf("pmax = %e\n", eos->pmax);
629  printf("hmax = %e\n", eos->hmax);
630  printf("hMinAcausal = %e\n", eos->hMinAcausal);
631 #endif
632 
633  return eos;
634 }
635 
636 /** @} */
637 /** @} */
#define LALCalloc(m, n)
#define LALFree(p)
#define LAL_G_C2_SI
Factor to convert density in kg/m^3 to geometerized units of m^-2.
#define LAL_NUCLEAR_DENSITY_GEOM_SI
Nuclear density in geometrized units of m^-2.
struct tagLALSimNeutronStarEOS LALSimNeutronStarEOS
Incomplete type for the neutron star Equation of State (EOS).
#define LAL_G_C4_SI
Factor to convert pressure in Pa to geometerized units of m^-2.
double i
Definition: bh_ringdown.c:118
sigmaKerr data[0]
const double rho2
#define LAL_C_SI
#define LAL_G_SI
LALSimNeutronStarEOS * XLALSimNeutronStarEOSPolytrope(double Gamma, double reference_pressure_si, double reference_density_si)
Creates a polytrope Equation of State defined by p = K rho^Gamma.
LALSimNeutronStarEOS * XLALSimNeutronStarEOS4ParameterPiecewisePolytrope(double logp1_si, double gamma1, double gamma2, double gamma3)
Creates a 4-parameter piecewise-polytrope Equation of State.
#define XLAL_PRINT_INFO(...)
#define XLAL_ERROR_NULL(...)
#define XLAL_PRINT_WARNING(...)
XLAL_EINVAL
list p