Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALSimulation 6.2.0.1-b246709
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
LALSimNeutronStarEOSDynamicPolytrope.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013 J. Lucaccioni, L. Wade
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 dynamic polytrope equations of state
25 * @{
26 */
27
28#include <lal/LALSimReadData.h>
29#include <gsl/gsl_interp.h>
30#include <lal/LALSimNeutronStar.h>
31
32/** @cond */
33
34/* Calculates the energy density given the pressure using an n-piece dynamic polytrope. */
35static double non_causal_Nparams(double p, double esec[], double psec[], double gsec[], size_t nsec){
36 double e;
37 int k;
38 // Find the polytrope section
39 for (k = 0; k <= (int)nsec - 2; ++k)
40 if (p < psec[k+1])
41 break;
42 // Eq. (5) of PRD 97, 123019 (2018)
43 e = (esec[k] - psec[k] / (gsec[k] - 1)) * pow(p / psec[k], 1 / gsec[k]) + p / (gsec[k] - 1);
44 return e;
45}
46
47/* Calculates the energy density given the pressure for an n-piece causal dynamic polytrope. */
48static double causal_Nparams(double p, double esec[], double psec[], double usec[], double vsec[], size_t nsec){
49 double e;
50 int k;
51 // Find the polytrope section
52 for (k = 0; k <= (int)nsec - 2; ++k)
53 if (p < psec[k+1])
54 break;
55 // Eq. (14) of PRD 97, 123019 (2018)
56 e = esec[k] + p - psec[k] + (psec[k] * usec[k] / (1 + vsec[k+1])) * (pow(p / psec[k], 1 + vsec[k+1]) - 1);
57 return e;
58}
59
60/** @endcond */
61
62/**
63 * @brief Reads dynamic analytic eos parameters to make an eos.
64 * @details Reads an array of eos parameters to construct either the causal
65 * analytic eos or non-causal analytic polytrope generically outlined in PRD 97,
66 * 123019 (2018). The models are dynamic because the stitching pressures are
67 * also parameter choices.
68 * @param[in] parameters[] Array of dynamic analytic eos parameters.
69 * [param0, log10(p1), param1, log10(p2), ... , log10(pN), paramN], where
70 * pressure is in SI units, and the params are either gammas (adiabatic
71 * indexes) for the non-causal polytrope model or the vs (speed function
72 * exponents) for the causal analytic model.
73 * @param[in] nsec The number of sections (pressure sub-domains) to stitch to
74 * crust eos.
75 * @param[in] causal Option to use causal version (0=non-causal, 1=causal).
76 * @return A pointer to neutron star equation of state structure.
77 */
78LALSimNeutronStarEOS *XLALSimNeutronStarEOSDynamicAnalytic(double parameters[], size_t nsec, int causal){
79 // Check that causal flag appropriately assigned
80 if (causal!=0 && causal!=1)
81 XLAL_ERROR_NULL(XLAL_EINVAL,"Did not specify which approach to take, Causal or Non-Causal");
82
83 // Size is the number of polytrope pieces to stitch to low-density EOS
84 if (nsec<1)
85 XLAL_ERROR_NULL(XLAL_EINVAL,"Number of polytrope pieces should be at least 1\n");
86
87 // Declares the max pressure(pmax). Units in geom.
88 // Chosen to match spectral decomposition and correspond to e0 and p0 for
89 // SLY EOS just below 0.5*rho_nuc. See Sec IID of PRD 98 063004 (2018) for
90 // more details. Note: Make adjustable in the future.
91 double pmax = 9.829054605e-8;
92 double p0 = 4.43784199e-13;
93
94 // Pull out and convert pressure parameters
95 double psec[nsec];
96 psec[0]=p0;
97 for (int i=1; i < (int)nsec; i++)
98 // Odd indices, SI -> geom (so c=1)
99 psec[i] = pow(10,parameters[i*2-1])*LAL_G_C4_SI;
100
101 if (psec[nsec-1]>pmax)
102 XLAL_ERROR_NULL(XLAL_EINVAL,"Highest p is set larger than %e, the limit at which EOS is generated\n",pmax);
103
104 // Fill in arrays with SLy data. Units in geom.
105 // These values agree with LALSimNeutronStarEOS_SLY.dat
106 double SLYdat_p[] = {2.497300e-31, 1.592353e-30,
107 1.015332e-29, 6.474064e-29, 4.128057e-28,
108 2.632173e-27, 1.678353e-26, 1.070168e-25,
109 6.823712e-25, 4.351004e-24, 1.915235e-23,
110 8.060015e-23, 3.231442e-22, 4.345220e-22,
111 1.185661e-21, 3.166995e-21, 8.312020e-21,
112 2.151541e-20, 5.516008e-20, 7.219725e-20,
113 1.345952e-19, 2.502695e-19, 3.411564e-19,
114 4.160967e-19, 5.668037e-19, 1.050983e-18,
115 1.946632e-18, 3.604079e-18, 4.678197e-18,
116 6.363735e-18, 8.659043e-18, 1.177398e-17,
117 1.601262e-17, 2.068090e-17, 2.812536e-17,
118 3.823860e-17, 4.915329e-17, 6.683492e-17,
119 9.088690e-17, 1.198055e-16, 1.235236e-16,
120 1.679755e-16, 2.145757e-16, 2.389499e-16,
121 2.718344e-16, 3.695792e-16, 4.805438e-16,
122 6.228231e-16, 6.448839e-16, 6.519069e-16,
123 6.900794e-16, 7.517173e-16, 7.841887e-16,
124 8.122810e-16, 8.948228e-16, 1.780309e-15,
125 2.831705e-15, 4.352574e-15, 6.442724e-15,
126 9.210148e-15, 1.726355e-14, 2.961343e-14,
127 4.760077e-14, 7.280619e-14, 1.069739e-13,
128 1.786341e-13, 3.178976e-13, 4.169395e-13,
129 4.437842e-13, 8.192049e-13, 2.464440e-12,
130 5.749505e-12, 1.129311e-11, 1.962992e-11,
131 3.125683e-11, 4.664233e-11, 6.623341e-11,
132 9.045725e-11, 1.197311e-10, 1.544499e-10,
133 1.949854e-10, 2.417178e-10, 2.949858e-10,
134 3.551282e-10, 4.224506e-10, 4.972587e-10,
135 5.798254e-10, 6.704065e-10, 7.692419e-10,
136 8.765628e-10, 9.925676e-10, 1.117413e-09,
137 1.251265e-09, 1.394370e-09, 1.546730e-09,
138 1.708591e-09, 1.880037e-09, 2.061232e-09, 2.252177e-09};
139
140 // Ensure p0 is in the crust eos range
141 size_t SLYdat_p_size = sizeof(SLYdat_p) / sizeof(*SLYdat_p);
142 if (psec[0] > SLYdat_p[SLYdat_p_size - 1])
143 XLAL_ERROR_NULL(XLAL_EINVAL,"p0 is set larger than %e, the limit of crust data",SLYdat_p[SLYdat_p_size - 1]);
144 if (psec[0] < SLYdat_p[0])
145 XLAL_ERROR_NULL(XLAL_EINVAL,"p0 is set smaller than %e, the lowest value of crust data",SLYdat_p[0]);
146
147 double SLYdat_e[] = {9.768004e-24, 3.088914e-23,
148 9.768005e-23, 3.088915e-22, 9.768010e-22,
149 3.088918e-21, 9.768031e-21, 3.088931e-20,
150 9.768115e-20, 3.088985e-19, 7.759067e-19,
151 1.949099e-18, 4.896221e-18, 6.163579e-18,
152 1.229692e-17, 2.454210e-17, 4.898236e-17,
153 9.773109e-17, 1.950244e-16, 2.455315e-16,
154 3.892642e-16, 6.169263e-16, 7.768370e-16,
155 9.006424e-16, 1.192376e-15, 1.890371e-15,
156 3.094528e-15, 4.906359e-15, 5.964589e-15,
157 7.510611e-15, 9.797770e-15, 1.233538e-14,
158 1.553357e-14, 1.881882e-14, 2.462712e-14,
159 3.100969e-14, 3.743924e-14, 4.918149e-14,
160 6.194543e-14, 7.622245e-14, 8.111554e-14,
161 1.052007e-13, 1.264362e-13, 1.370769e-13,
162 1.557999e-13, 2.029004e-13, 2.471392e-13,
163 3.112816e-13, 3.195299e-13, 3.221410e-13,
164 3.362136e-13, 3.585373e-13, 3.701139e-13,
165 3.800336e-13, 4.248215e-13, 1.571192e-12,
166 2.360837e-12, 3.331525e-12, 4.497152e-12,
167 5.875556e-12, 9.359056e-12, 1.398990e-11,
168 2.000679e-11, 2.762451e-11, 3.691961e-11,
169 5.352249e-11, 7.810201e-11, 9.194762e-11,
170 9.546290e-11, 1.258593e-10, 1.895055e-10,
171 2.539315e-10, 3.194416e-10, 3.863255e-10,
172 4.548506e-10, 5.252990e-10, 5.979231e-10,
173 6.729756e-10, 7.507236e-10, 8.312713e-10,
174 9.150863e-10, 1.002169e-09, 1.092816e-09,
175 1.187250e-09, 1.285694e-09, 1.388296e-09,
176 1.495280e-09, 1.606794e-09, 1.723060e-09,
177 1.844228e-09, 1.970445e-09, 2.101934e-09,
178 2.238770e-09, 2.381175e-09, 2.529225e-09,
179 2.683140e-09, 2.842997e-09, 3.008942e-09, 3.181052e-09};
180
181 // Insist that the size of SLYdat_p is the same as SLYdat_e
182 ((void)sizeof(char[1 - 2*!!(sizeof(SLYdat_p) != sizeof(SLYdat_e))]));
183
184 // Check the ammount of SLy data that will be included
185 size_t limit;
186 // Already checked that p0 > smallest p of crust eos, so start limit at 1
187 for (limit = 1; limit < SLYdat_p_size; ++limit)
188 if (psec[0] < SLYdat_p[limit])
189 break;
190
191 // 100 points is arbitrarily chosen to resolve high-density eos
192 size_t ndat = 100 + limit;
193
194 // Declaring array and allocating memory space
195 double *edat;
196 double *pdat;
197
198 pdat = XLALCalloc(ndat, sizeof(*pdat));
199 edat = XLALCalloc(ndat, sizeof(*edat));
200 if (pdat == NULL || edat == NULL) {
201 XLALFree(pdat);
202 XLALFree(edat);
204 }
205
206 double logpmax = log(pmax);
207 double logp0 = log(psec[0]);
208 double dlogp = (logpmax-logp0)/(ndat-limit);
209
210 // Add SLy data for crust
211 for (int i = 0; i < (int)limit; i++){
212 pdat[i] = SLYdat_p[i];
213 edat[i] = SLYdat_e[i];
214 }
215
216 // Find energy density at p0
217 double b = SLYdat_e[limit-1];
218 double dedp = (SLYdat_e[limit]-SLYdat_e[limit-1])/(SLYdat_p[limit]-SLYdat_p[limit-1]);
219 double x = psec[0]-SLYdat_p[limit-1];
220 double e0 = (dedp*x) + b;
221
222 // Find starting energy's of each section
223 double esec[nsec];
224 esec[0] = e0;
225
226 if (causal == 1){
227 double vsec[nsec+1];
228 double usec[nsec];
229 // Solving Eq. (11) of PRD 97, 123019 (2018) for Y0
230 usec[0] = dedp-1;
231 // Solving Y(p0) = e^v0 for v0 = ln(Y0)
232 vsec[0] = log(usec[0]);
233 // Fill the rest of the v array
234 vsec[1] = parameters[0];
235 for (int i = 1; i < (int)nsec; i++)
236 // Even indices
237 vsec[i+1] = parameters[i*2];
238 for (int k=1; k < (int)nsec; ++k){
239 // Eq. (15) of PRD 97, 123019 (2018)
240 usec[k] = usec[k-1] * pow(psec[k] / psec[k-1],vsec[k]);
241 // Eq. (16) of PRD 97, 123019 (2018)
242 esec[k] = esec[k-1] + psec[k] - psec[k-1] + ( psec[k-1] * usec[k-1] / (1 + vsec[k])) * (pow(psec[k] / psec[k-1], 1 + vsec[k]) - 1);
243 }
244 // Compute polytrope data beyond the crust
245 for (int i = limit; i < (int)ndat; i++){
246 pdat[i] = exp(logp0 + (dlogp*(i-limit)));
247 edat[i] = causal_Nparams(pdat[i],esec,psec,usec,vsec,nsec);
248 }
249 }else{
250 double gsec[nsec];
251 gsec[0]=parameters[0];
252 for (int i = 1; i < (int)nsec; i++)
253 // Even indices
254 gsec[i] = parameters[i*2];
255 for (int k = 0; k < (int)nsec-1; ++k)
256 // Eq. (6) of PRD 97, 123019 (2018)
257 esec[k+1] = (esec[k] - psec[k] / (gsec[k] - 1)) * pow(psec[k+1] / psec[k], 1 / gsec[k]) + psec[k+1] / (gsec[k] - 1);
258 // Compute polytrope data beyond the crust
259 for (int i = limit; i < (int)ndat; i++){
260 pdat[i] = exp(logp0 + (dlogp*(i-limit)));
261 edat[i] = non_causal_Nparams(pdat[i],esec,psec,gsec,nsec);
262 }
263 }
264
265 // Updating eos structure
267 double *nbdat = NULL;
268 double *mubdat = NULL;
269 double *muedat = NULL;
270 double *yedat = NULL;
271 double *cs2dat = NULL;
272 double *hdat = NULL;
273 size_t ncol = 2;
274 /* Updating eos structure */
275 eos = eos_alloc_tabular(nbdat, edat, pdat, mubdat, muedat, hdat, yedat, cs2dat, ndat, ncol);
276
277
278 XLALFree(edat);
279 XLALFree(pdat);
280
281 return eos;
282}
283
284/**
285 * @brief Reads 5 dynamic polytrope eos parameters to make an eos.
286 * @details Reads 5 dynamic polytrope eos parameters to construct a 3-piece
287 * dynamic polytrope eos, generically outlined in PRD 97, 123019 (2018), and
288 * stitched to a low-density SLy eos crust.
289 * @param[in] g0 The adiabatic index of the first polytrope.
290 * @param[in] log10p1_si The log10 of the first dividing pressure in SI units.
291 * @param[in] g1 The adiabatic index of the second polytrope.
292 * @param[in] log10p2_si The log10 of the second dividing pressure in SI units.
293 * @param[in] g2 The adiabatic index of the third polytrope.
294 * @return A pointer to neutron star equation of state structure.
295 */
296LALSimNeutronStarEOS *XLALSimNeutronStarEOS3PieceDynamicPolytrope(double g0, double log10p1_si, double g1, double log10p2_si, double g2){
297 double params[]={g0,log10p1_si,g1,log10p2_si,g2};
299 // 3-piece (non-causal) dynamic polytrope
301 return eos;
302}
303
304/**
305 * @brief Reads 5 causal analytic eos parameters to make an eos.
306 * @details Reads 5 causal analytic eos parameters to construct a 3-piece
307 * causal eos, generically outlined in PRD 97, 123019 (2018), and stitched to
308 * a low-density SLy eos crust.
309 * @param[in] v1 The first sound function exponent.
310 * @param[in] log10p1_si The log10 of the first dividing pressure in SI units.
311 * @param[in] v2 The second sound function exponent.
312 * @param[in] log10p2_si The log10 of the second dividing pressure in SI units.
313 * @param[in] v3 The third sound function exponent.
314 * @return A pointer to neutron star equation of state structure.
315 */
316LALSimNeutronStarEOS *XLALSimNeutronStarEOS3PieceCausalAnalytic(double v1, double log10p1_si, double v2, double log10p2_si, double v3){
317 double params[]={v1,log10p1_si,v2,log10p2_si,v3};
319 // 3-piece causal analytic eos
321 return eos;
322}
323
324/**
325 * @brief Check that EOS has enough points (>4) in M-R space to interpolate.
326 * As the TOV equations are integrated from pmin to pmax, masses are
327 * calculated. Once the mass turns over (i.e. m(p_i) > m(p_{i+1})), the
328 * integration is terminated. It is possible therefore to have less than 4
329 * points in M-R space. We demand, then, that in the interval [pmin,pmax],
330 * m(pmin) = m(p_0) < m(p_1) < m(p_2) < m(p_3).
331 * @details Reads 3-piece dynamic polytrope (non-causal) or analytic (causal)
332 * eos parameters and checks that the eos has at least 4 data points before
333 * turning over in M-R space, which abruptly terminates the eos.
334 * @param[in] p0 First model param, either g0 (non-causal) or v1 (causal).
335 * @param[in] log10p1_si The log10 of the first dividing pressure in SI units.
336 * @param[in] p1 Second model param, either g1 (non-causal) or v2 (causal).
337 * @param[in] log10p2_si The log10 of the second dividing pressure in SI units.
338 * @param[in] p2 Third model param, either g2 (non-causal) or v3 (causal).
339 * @param[in] causal Option to use causal version (0=non-causal, 1=causal).
340 * @return XLAL_SUCCESS or XLAL_FAILURE.
341 */
342int XLALSimNeutronStarEOS3PDViableFamilyCheck(double p0, double log10p1_si, double p1, double log10p2_si, double p2, int causal){
343 // Check that causal flag appropriately assigned
344 if (causal!=0 && causal!=1)
345 XLAL_ERROR(XLAL_EINVAL,"Did not specify which approach to take, Causal or Non-Causal");
346 double pdat;
347 double mdat;
348 double mdat_prev;
349 double rdat;
350 double kdat;
351
352 LALSimNeutronStarEOS *eos=NULL;
353 if (causal == 1)
354 eos = XLALSimNeutronStarEOS3PieceCausalAnalytic(p0, log10p1_si, p1, log10p2_si, p2);
355 else
356 eos = XLALSimNeutronStarEOS3PieceDynamicPolytrope(p0, log10p1_si, p1, log10p2_si, p2);
357
358 // Initialize previous value for mdat comparison
359 mdat_prev = 0.0;
360
361 // Ensure mass turnover does not happen too soon
362 const double logpmin = 75.5;
363 double logpmax = log(XLALSimNeutronStarEOSMaxPressure(eos));
364 double dlogp = (logpmax - logpmin) / 100.;
365 // Need at least four points
366 for (int i = 0; i < 4; ++i) {
367 pdat = exp(logpmin + i * dlogp);
368 XLALSimNeutronStarTOVODEIntegrate(&rdat, &mdat, &kdat, pdat, eos);
369 // Determine if maximum mass has been found
370 if (mdat <= mdat_prev){
371 // EOS has too few points to create family
372 // Clean up
374 return XLAL_FAILURE;
375 }
376 mdat_prev = mdat;
377 }
378
380
381 return XLAL_SUCCESS;
382}
383
384/** @} */
385/** @} */
const double g2
const double g0
const double g1
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
double e
Definition: bh_ringdown.c:117
void * XLALCalloc(size_t m, size_t n)
void XLALFree(void *p)
LALSimNeutronStarEOS * XLALSimNeutronStarEOSDynamicAnalytic(double parameters[], size_t nsec, int causal)
Reads dynamic analytic eos parameters to make an eos.
int XLALSimNeutronStarEOS3PDViableFamilyCheck(double p0, double log10p1_si, double p1, double log10p2_si, double p2, int causal)
Check that EOS has enough points (>4) in M-R space to interpolate.
LALSimNeutronStarEOS * XLALSimNeutronStarEOS3PieceCausalAnalytic(double v1, double log10p1_si, double v2, double log10p2_si, double v3)
Reads 5 causal analytic eos parameters to make an eos.
double XLALSimNeutronStarEOSMaxPressure(LALSimNeutronStarEOS *eos)
Returns the maximum pressure of the EOS in Pa.
LALSimNeutronStarEOS * XLALSimNeutronStarEOS3PieceDynamicPolytrope(double g0, double log10p1_si, double g1, double log10p2_si, double g2)
Reads 5 dynamic polytrope eos parameters to make an eos.
void XLALDestroySimNeutronStarEOS(LALSimNeutronStarEOS *eos)
Frees the memory associated with a pointer to an EOS structure.
int XLALSimNeutronStarTOVODEIntegrate(double *radius, double *mass, double *love_number_k2, double central_pressure_si, LALSimNeutronStarEOS *eos)
#define XLAL_ERROR_NULL(...)
#define XLAL_ERROR(...)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EINVAL
XLAL_FAILURE
p
x
Definition: burst.c:245