LORENE
pseudopolytrope_1D.C
1 /*
2  * Methods of the class Pseudo_polytrope_1D.
3  *
4  * (see file eos.h for documentation).
5  */
6 
7 /*
8  * Copyright (c) 2023 GaĆ«l Servignat
9  *
10  * This file is part of LORENE.
11  *
12  * LORENE is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * LORENE is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with LORENE; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  *
26  */
27 
28 
29 
30 
31 /*
32 
33  */
34 
35 // Headers C
36 #include <cstdlib>
37 #include <cstring>
38 #include <cmath>
39 
40 // Headers Lorene
41 #include "eos.h"
42 #include "cmp.h"
43 #include "unites.h"
44 
45  //--------------//
46  // Constructors //
47  //--------------//
48 
49 // Standard constructor
50 // --------------------
51 namespace Lorene {
52 Pseudo_polytrope_1D::Pseudo_polytrope_1D(const Tbl& coefs0, double n_lim0, double m_n0):
53  n_lim(n_lim0), m_n(m_n0) {
54 
55  cerr << "Deprecated constructor, please do not use ! Aborting..." << endl; abort() ;
56  set_name("Pseudo-polytropic fit of cold, beta-equilibrated EoS") ;
57 
58  assert(coefs0.get_ndim() == 1) ;
59  coefs = new Tbl(coefs0) ;
60  n_coefs = coefs->get_taille() ;
61 
62  double x_lim = log(n_lim*0.1) ;
63  double alpha = (*coefs)(n_coefs-1) ;
64  double sum_poly = 0., sum_der_poly = 0. ;
65  for (int i=0; i<n_coefs-1; i++){
66  sum_poly += (*coefs)(i)*pow(x_lim, double(i)) ;
67  sum_der_poly += (i == 0) ? 0. : (*coefs)(i)*double(i)*pow(x_lim, double(i-1)) ;
68  }
69  ent_lim = log1p(mu_0 + exp(alpha*x_lim)*((alpha+1)*sum_poly + sum_der_poly)) ;
70 
71 }
72 
73 
74 // Copy constructor
75 // ----------------
76 Pseudo_polytrope_1D::Pseudo_polytrope_1D(const Pseudo_polytrope_1D& eosi): Eos(eosi), coefs(eosi.coefs), gamma_low(eosi.gamma_low), kappa_low(eosi.kappa_low),
77  n_lim(eosi.n_lim), ent_lim(eosi.ent_lim), m_n(eosi.m_n), mu_0(eosi.mu_0), n_coefs(eosi.n_coefs) {}
78 
79 
80 // Constructor from a binary file
81 // ------------------------------
83 
84  fread_be(&n_coefs, sizeof(int), 1, fich) ;
85  coefs = new Tbl(fich) ;
86  fread_be(&kappa_low, sizeof(double), 1, fich) ;
87  fread_be(&gamma_low, sizeof(double), 1, fich) ;
88  fread_be(&n_lim, sizeof(double), 1, fich) ;
89  fread_be(&ent_lim, sizeof(double), 1, fich) ;
90  fread_be(&m_n, sizeof(double), 1, fich) ;
91  fread_be(&mu_0, sizeof(double), 1, fich) ;
92  fread_be(&Lambda, sizeof(double), 1, fich) ;
93 
94  eos_low = new Eos_poly(gamma_low, kappa_low) ;
95 }
96 
97 // Constructor from a formatted file
98 // ---------------------------------
100 
101  fich >> n_coefs ; fich.ignore(1000, '\n') ;
102  coefs = new Tbl(n_coefs) ; coefs->set_etat_qcq() ;
103 
104  for (int i=0; i < n_coefs; i++)
105  fich >> coefs->set(i) ;
106  fich.ignore(1000, '\n') ;
107 
108  fich >> n_lim ; fich.ignore(1000, '\n') ;
109 
110  fich >> kappa_low ; fich.ignore(1000, '\n') ;
111 
112  fich >> gamma_low ; fich.ignore(1000, '\n') ;
113 
114  fich >> m_n ; fich.ignore(1000, '\n') ;
115 
116  fich >> mu_0 ; fich.ignore(1000, '\n') ;
117 
118  fich >> Lambda ; fich.ignore(1000, '\n') ;
119 
120  double x_lim = log(n_lim*0.1) ;
121  double alpha = (*coefs)(n_coefs-1) ;
122  double sum_poly = 0., sum_der_poly = 0. ;
123  for (int i=0; i<n_coefs-1; i++){
124  sum_poly += (*coefs)(i)*pow(x_lim, double(i)) ;
125  sum_der_poly += (i == 0) ? 0. : (*coefs)(i)*double(i)*pow(x_lim, double(i-1)) ;
126  }
127  ent_lim = log1p(mu_0 + exp(alpha*x_lim)*((alpha+1)*sum_poly + sum_der_poly)) ;
128 
129 
130  eos_low = new Eos_poly(gamma_low, kappa_low) ;
131 
132 }
133 
134 
135  //--------------//
136  // Destructor //
137  //--------------//
138 
140 
141  if (coefs != 0x0) delete coefs ;
142  if (eos_low != 0x0) delete eos_low ;
143 
144 }
145  //--------------//
146  // Assignment //
147  //--------------//
148 
150 
151  set_name(eosi.name) ;
152 
153  coefs = eosi.coefs ;
154  n_lim = eosi.n_lim ;
155  n_coefs = eosi.n_coefs ;
156  gamma_low = eosi.gamma_low ;
157  kappa_low = eosi.kappa_low ;
158  m_n = eosi.m_n ;
159  ent_lim = eosi.ent_lim ;
160  mu_0 = eosi.mu_0 ;
161  Lambda = eosi.Lambda ;
162  eos_low = eosi.eos_low ;
163 
164 }
165  //------------------------//
166  // Comparison operators //
167  //------------------------//
168 
169 bool Pseudo_polytrope_1D::operator==(const Eos& eos_i) const {
170 
171  bool resu = true ;
172 
173  if ( eos_i.identify() != identify() ) {
174  cout << "The second EOS is not of type Pseudo_polytrope_1D !" << endl ;
175  resu = false ;
176  }
177  else{
178 
179  const Pseudo_polytrope_1D& eos = dynamic_cast<const Pseudo_polytrope_1D&>( eos_i ) ;
180 
181  for (int i=0; i < n_coefs; i++)
182  if ((*eos.coefs)(i) != (*coefs)(i)) {
183  cout
184  << "The two Pseudo_polytrope_1D have different coefficients: " << (*coefs)(i) << " <-> "
185  << (*eos.coefs)(i) << endl ;
186  resu = false ;
187  }
188 
189  if (eos.n_lim != n_lim) {
190  cout
191  << "The two Pseudo_polytrope_1D have different limiting densities n_lim: " << n_lim << " <-> "
192  << eos.n_lim << endl ;
193  resu = false ;
194  }
195 
196  if (eos.ent_lim != ent_lim) {
197  cout
198  << "The two Pseudo_polytrope_1D have different limiting enthalpies ent_lim: " << ent_lim << " <-> "
199  << eos.ent_lim << endl ;
200  resu = false ;
201  }
202 
203  if (eos.n_coefs != n_coefs) {
204  cout
205  << "The two Pseudo_polytrope_1D have different number of coefficients: " << n_coefs << " <-> "
206  << eos.n_coefs << endl ;
207  resu = false ;
208  }
209 
210  if (eos.kappa_low != kappa_low) {
211  cout
212  << "The two Pseudo_polytrope_1D have different kappa in low polytrope: " << kappa_low << " <-> "
213  << eos.kappa_low << endl ;
214  resu = false ;
215  }
216 
217  if (eos.gamma_low != gamma_low) {
218  cout
219  << "The two Pseudo_polytrope_1D have different kappa in low polytrope: " << gamma_low << " <-> "
220  << eos.gamma_low << endl ;
221  resu = false ;
222  }
223 
224  if (eos.mu_0!= mu_0) {
225  cout
226  << "The two Pseudo_polytrope_1D have different mu_0 in low polytrope: " << mu_0 << " <-> "
227  << eos.mu_0 << endl ;
228  resu = false ;
229  }
230 
231  }
232 
233  return resu ;
234 
235 }
236 
237 bool Pseudo_polytrope_1D::operator!=(const Eos& eos_i) const {
238 
239  return !(operator==(eos_i)) ;
240 
241 }
242 
243 
244  //------------//
245  // Outputs //
246  //------------//
247 
248 void Pseudo_polytrope_1D::sauve(FILE* fich) const {
249 
250  Eos::sauve(fich) ;
251 
252  fwrite_be(&n_coefs, sizeof(int), 1, fich) ;
253  coefs->sauve(fich) ;
254  fwrite_be(&kappa_low, sizeof(double), 1, fich) ;
255  fwrite_be(&gamma_low, sizeof(double), 1, fich) ;
256  fwrite_be(&n_lim, sizeof(double), 1, fich) ;
257  fwrite_be(&ent_lim, sizeof(double), 1, fich) ;
258  fwrite_be(&m_n, sizeof(double), 1, fich) ;
259  fwrite_be(&mu_0, sizeof(double), 1, fich) ;
260  fwrite_be(&Lambda, sizeof(double), 1, fich) ;
261 
262 
263 }
264 
265 ostream& Pseudo_polytrope_1D::operator>>(ostream & ost) const {
266 
267  ost << setprecision(16) << "EOS of class Pseudo_polytrope_1D (analytical fit of cold EoS): " << '\n' ;
268  ost << " Coefficients: " << *coefs << '\n' ;
269  ost << setprecision(16) << " Baryon mass: " << m_n << " [MeV]" << '\n' ;
270  ost << setprecision(16) << " mu_0-1: " << mu_0 << " and Lambda: " << Lambda << '\n' ;
271  ost << "Low densities polytrope :" << '\n' ;
272  cout << *eos_low << '\n' ;
273  ost << setprecision(16) << " Limiting density n_lim: " << 0.1*n_lim << " [fm^-3]" << '\n' ;
274  ost << setprecision(16) << " Limiting enthalpy h_lim: " << ent_lim << " [c^2]" << endl;
275 
276  return ost ;
277 
278 }
279 
280 
281  //------------------------------//
282  // Computational routines //
283  //------------------------------//
284 
285 // Baryon density from enthalpy
286 //------------------------------
287 
288 double Pseudo_polytrope_1D::nbar_ent_p(double ent, const Param* ) const {
289 
290  if (ent > ent_lim ) {
291 
292  auto ent_nb_p = [&](double nbar) {
293  double xx = log(nbar*0.1) ;
294  double alpha = (*coefs)(n_coefs-1) ;
295  double sum_poly = 0.;
296  for (int i=0; i < n_coefs-1; i++){
297  double cc1 = (alpha+1.)*(*coefs)(i) ;
298  double cc2 = (i == n_coefs - 2) ? 0. : double(i+1)*(*coefs)(i+1) ;
299  sum_poly += (cc1 + cc2)*pow(xx, double(i));
300  }
301  double arg = exp(alpha*xx)*sum_poly + mu_0 ;
302  return log1p(arg) - ent ;
303  } ;
304 
305  double a = n_lim/2., b = max(100.*ent, 50.*n_lim) ;
306  double f0 = ent_nb_p(a), f1 = ent_nb_p(b) ;
307  double c=1., c_old=2., f2 ;
308  double eps = 5e-16 ;
309  assert( f0 * f1 < 0.) ;
310  while(fabs((c-c_old)/c)>eps) {
311  c_old = c ;
312  c = (b*f0 - a*f1)/(f0 - f1) ;
313  f2 = ent_nb_p(c) ;
314 
315  if (f2*f0 < 0.){
316  b = c ;
317  f1 = f2 ;
318  }
319  else{
320  a = c ;
321  f0 = f2 ;
322  }
323  }
324  return c ;
325  }
326  else if ( (0 < ent) && (ent < ent_lim)){
327 
328  return eos_low->nbar_ent_p(ent) ;
329  }
330  else{
331  return 0 ;
332  }
333 }
334 
335 // Energy density from enthalpy
336 //------------------------------
337 
338 double Pseudo_polytrope_1D::ener_ent_p(double ent, const Param* ) const {
339  if (ent > ent_lim ) {
340 
341  double nbar = nbar_ent_p(ent) ;
342  double xx = log(nbar*0.1) ;
343 
344  double alpha = (*coefs)(n_coefs-1) ;
345  double sum_poly = 0.;
346  for (int i=0; i < n_coefs-1; i++)
347  sum_poly += (*coefs)(i)*pow(xx, double(i));
348  return m_n*Unites::mevpfm3*(exp(xx)*(1.+mu_0) + exp((alpha+1) * xx)*sum_poly) - Lambda ;
349  }
350  else if ( (0 < ent) && (ent < ent_lim)){
351 
352  return eos_low->ener_ent_p(ent) ;
353  }
354  else{
355  return 0 ;
356  }
357 }
358 
359 // Pressure from enthalpy
360 //------------------------
361 
362 double Pseudo_polytrope_1D::press_ent_p(double ent, const Param* ) const {
363  if (ent > ent_lim ) {
364 
365  double nbar = nbar_ent_p(ent) ;
366 
367  double xx = log(nbar*0.1) ;
368 
369  double alpha = (*coefs)(n_coefs-1) ;
370  double sum_poly = 0.;
371  for (int i=0; i < n_coefs-1; i++){
372  double cc1 = alpha*(*coefs)(i) ;
373  double cc2 = (i == n_coefs - 2) ? 0. : double(i+1)*(*coefs)(i+1) ;
374  sum_poly += (cc1 + cc2)*pow(xx, double(i));
375  }
376 
377  return m_n*Unites::mevpfm3*(exp((alpha+1.)*xx) * sum_poly) + Lambda;
378  }
379  else if ( (0 < ent) && (ent < ent_lim)){
380  return eos_low->press_ent_p(ent) ;
381  }
382  else{
383  return 0 ;
384  }
385 }
386 
387 // dln(n)/ln(h) from enthalpy
388 //---------------------------
389 
390 double Pseudo_polytrope_1D::der_nbar_ent_p(double , const Param* ) const {
391  c_est_pas_fait("Pseudo_polytrope_1D::der_nbar_ent_p") ;
392  return 0.;
393 }
394 
395 // dln(e)/ln(h) from enthalpy
396 //---------------------------
397 
398 double Pseudo_polytrope_1D::der_ener_ent_p(double, const Param* ) const {
399  c_est_pas_fait("Pseudo_polytrope_1D::der_ener_ent_p") ;
400  return 0.;
401 }
402 
403 // dln(p)/ln(h) from enthalpy
404 //---------------------------
405 
406 double Pseudo_polytrope_1D::der_press_ent_p(double, const Param* ) const {
407  c_est_pas_fait("Pseudo_polytrope_1D::der_press_ent_p") ;
408  return 0. ;
409 }
410 
411 double Pseudo_polytrope_1D::csound_square_ent_p(double ent, const Param*) const {
412  if (ent > ent_lim ) {
413  double nbar = nbar_ent_p(ent) ;
414  double xx = log(nbar*0.1) ;
415 
416  double alpha = (*coefs)(n_coefs-1) ;
417  double sum_poly = 0., sum_der_poly = 0., sum_der2_poly = 0.;
418  for (int i=0; i < n_coefs-1; i++){
419  sum_poly += (*coefs)(i)*pow(xx, double(i));
420  sum_der_poly += (i == 0) ? 0. : double(i) * (*coefs)(i) * pow(xx, double(i-1)) ;
421  sum_der2_poly += (i < 2) ? 0. : double(i) * double(i-1) * (*coefs)(i) * pow(xx, double(i-2)) ;
422  }
423  double num = (alpha*(alpha+1.) * sum_poly + (2.*alpha+1.) * sum_der_poly + sum_der2_poly)*exp(alpha*xx) ;
424  double denom = 1. + mu_0 + ((alpha+1.) * sum_poly + sum_der_poly)*exp(alpha*xx) ;
425 
426  return num/denom ;
427  }
428  else if ( (0 < ent) && (ent < ent_lim)){
429 
430  return eos_low->csound_square_ent_p(ent) ;
431  }
432  else{
433  return 0 ;
434  }
435 }
436 
437 }
virtual double ener_ent_p(double ent, const Param *par=0x0) const
Computes the total energy density from the log-enthalpy.
Definition: eos_poly.C:398
Cmp log(const Cmp &)
Neperian logarithm.
Definition: cmp_math.C:299
Cmp exp(const Cmp &)
Exponential.
Definition: cmp_math.C:273
virtual int identify() const
Returns a number to identify the sub-classe of Eos the object belongs to.
Lorene prototypes.
Definition: app_hor.h:67
Equation of state base class.
Definition: eos.h:206
double & set(int i)
Read/write of a particular element (index i) (1D case)
Definition: tbl.h:281
virtual int identify() const =0
Returns a number to identify the sub-classe of Eos the object belongs to.
virtual double nbar_ent_p(double ent, const Param *par=0x0) const
Computes the baryon density from the specific enthalpy.
virtual double csound_square_ent_p(double, const Param *) const
Computes the sound speed squared from the enthapy with extra parameters (virtual function implemente...
virtual void sauve(FILE *) const
Save in a file.
Definition: eos.C:189
void set_etat_qcq()
Sets the logical state to ETATQCQ (ordinary state).
Definition: tbl.C:364
int get_ndim() const
Gives the number of dimensions (ie dim.ndim)
Definition: tbl.h:400
virtual bool operator==(const Eos &) const
Comparison operator (egality)
virtual double ener_ent_p(double ent, const Param *par=0x0) const
Computes the total energy density from the specific enthalpy.
Pseudo_polytrope_1D(const Tbl &, double, double)
Standard constructor.
virtual double nbar_ent_p(double ent, const Param *par=0x0) const
Computes the baryon density from the log-enthalpy.
Definition: eos_poly.C:383
virtual double press_ent_p(double ent, const Param *par=0x0) const
Computes the pressure from the specific enthalpy.
Parameter storage.
Definition: param.h:125
Polytropic equation of state (relativistic case).
Definition: eos.h:809
Tbl max(const Cmp &)
Maximum values of a Cmp in each domain.
Definition: cmp_math.C:438
virtual double csound_square_ent_p(double ent, const Param *par=0x0) const
Computes the sound speed squared from the enthapy with extra parameters (virtual function implemente...
Definition: eos_poly.C:469
int fwrite_be(const int *aa, int size, int nb, FILE *fich)
Writes integer(s) into a binary file according to the big endian convention.
Definition: fwrite_be.C:73
virtual double press_ent_p(double ent, const Param *par=0x0) const
Computes the pressure from the log-enthalpy.
Definition: eos_poly.C:410
Cmp pow(const Cmp &, int)
Power .
Definition: cmp_math.C:351
int fread_be(int *aa, int size, int nb, FILE *fich)
Reads integer(s) from a binary file according to the big endian convention.
Definition: fread_be.C:72
void operator=(const Pseudo_polytrope_1D &)
Assignment to another Pseudo_polytrope_1D.
virtual ostream & operator>>(ostream &) const
Operator >>
virtual double der_press_ent_p(double ent, const Param *par=0x0) const
Computes the logarithmic derivative from the specific enthalpy.
void c_est_pas_fait(const char *)
Helpful function to say something is not implemented yet.
void set_name(const char *name_i)
Sets the EOS name.
Definition: eos.C:173
char name[100]
EOS name.
Definition: eos.h:212
void sauve(FILE *) const
Save in a file.
Definition: tbl.C:329
Basic array class.
Definition: tbl.h:161
virtual ~Pseudo_polytrope_1D()
Destructor.
virtual double der_nbar_ent_p(double ent, const Param *par=0x0) const
Computes the logarithmic derivative from the specific enthalpy.
virtual double der_ener_ent_p(double ent, const Param *par=0x0) const
Computes the logarithmic derivative from the specific enthalpy.
virtual bool operator!=(const Eos &) const
Comparison operator (difference)
virtual void sauve(FILE *) const
Save in a file.