LORENE
eos_tabul.C
1 /*
2  * Methods of class Eos_tabul
3  *
4  * (see file eos.h for documentation).
5  *
6  */
7 
8 /*
9  * Copyright (c) 2000-2001 Eric Gourgoulhon
10  *
11  * This file is part of LORENE.
12  *
13  * LORENE is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * LORENE is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with LORENE; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  */
28 
29 
30 
31 
32 /*
33  * $Id: eos_tabul.C,v 1.25 2022/03/22 13:36:00 j_novak Exp $
34  * $Log: eos_tabul.C,v $
35  * Revision 1.25 2022/03/22 13:36:00 j_novak
36  * Added declaration of compute_derivative to utilitaires.h
37  *
38  * Revision 1.24 2022/03/22 13:18:47 g_servignat
39  * Corrected treatment for h<hmin
40  *
41  * Revision 1.23 2022/03/10 16:38:39 j_novak
42  * log(cs^2) is tabulated instead of cs^2.
43  *
44  * Revision 1.22 2021/05/31 11:31:23 g_servignat
45  * Added csound_square_ent routine to calculate the sound speed from enthalpy to Eos_consistent and corrected error outputs
46  *
47  * Revision 1.21 2021/05/14 15:39:22 g_servignat
48  * Added sound speed computation from enthalpy to Eos class and tabulated+polytropic derived classes
49  *
50  * Revision 1.20 2019/12/02 14:51:36 j_novak
51  * Moved piecewise parabolic computation of dpdnb to a separate function.
52  *
53  * Revision 1.19 2019/03/28 13:41:02 j_novak
54  * Improved managed of saved EoS (functions sauve and constructor form FILE*)
55  *
56  * Revision 1.18 2017/12/15 15:36:38 j_novak
57  * Improvement of the MEos class. Implementation of automatic offset computation accross different EoSs/domains.
58  *
59  * Revision 1.17 2016/12/05 16:17:52 j_novak
60  * Suppression of some global variables (file names, loch, ...) to prevent redefinitions
61  *
62  * Revision 1.16 2015/08/04 14:41:29 j_novak
63  * Back to previous version for Eos_CompOSE. Enthalpy-consistent EoS can be accessed using Eos_consistent class (derived from Eos_CompOSE).
64  *
65  * Revision 1.15 2015/01/27 14:22:38 j_novak
66  * New methods in Eos_tabul to correct for EoS themro consistency (optional).
67  *
68  * Revision 1.14 2014/10/13 08:52:54 j_novak
69  * Lorene classes and functions now belong to the namespace Lorene.
70  *
71  * Revision 1.13 2014/06/30 16:13:18 j_novak
72  * New methods for reading directly from CompOSE files.
73  *
74  * Revision 1.12 2014/03/06 15:53:35 j_novak
75  * Eos_compstar is now Eos_compOSE. Eos_tabul uses strings and contains informations about authors.
76  *
77  * Revision 1.11 2012/11/09 10:32:44 m_bejger
78  * Implementing der_ener_ent_p
79  *
80  * Revision 1.10 2010/02/16 11:14:50 j_novak
81  * More verbose opeining of the file.
82  *
83  * Revision 1.9 2010/02/02 13:22:16 j_novak
84  * New class Eos_Compstar.
85  *
86  * Revision 1.8 2004/03/25 10:29:02 j_novak
87  * All LORENE's units are now defined in the namespace Unites (in file unites.h).
88  *
89  * Revision 1.7 2003/11/25 13:42:50 m_bejger
90  * read_table written in more ordered way
91  *
92  * Revision 1.6 2003/11/21 16:11:16 m_bejger
93  * added the computation dlnp/dlnn_b, dlnn/dlnH
94  *
95  * Revision 1.5 2003/05/30 07:50:06 e_gourgoulhon
96  *
97  * Reformulate the computation of der_nbar_ent
98  * Added computation of der_press_ent_p.
99  *
100  * Revision 1.4 2003/05/15 09:42:47 e_gourgoulhon
101  *
102  * Now computes d ln / dln H.
103  *
104  * Revision 1.3 2002/10/16 14:36:35 j_novak
105  * Reorganization of #include instructions of standard C++, in order to
106  * use experimental version 3 of gcc.
107  *
108  * Revision 1.2 2002/04/09 14:32:15 e_gourgoulhon
109  * 1/ Added extra parameters in EOS computational functions (argument par)
110  * 2/ New class MEos for multi-domain EOS
111  *
112  * Revision 1.1.1.1 2001/11/20 15:19:27 e_gourgoulhon
113  * LORENE
114  *
115  * Revision 2.3 2001/09/13 13:35:49 eric
116  * Suppression des affichages dans read_table().
117  *
118  * Revision 2.2 2001/02/07 09:48:05 eric
119  * Suppression de la fonction derent_ent_p.
120  * Ajout des fonctions donnant les derivees de l'EOS:
121  * der_nbar_ent_p
122  * der_ener_ent_p
123  * der_press_ent_p
124  *
125  * Revision 2.1 2000/11/23 00:10:20 eric
126  * Enthalpie minimale fixee a 1e-14.
127  *
128  * Revision 2.0 2000/11/22 19:31:30 eric
129  * *** empty log message ***
130  *
131  *
132  * $Header: /cvsroot/Lorene/C++/Source/Eos/eos_tabul.C,v 1.25 2022/03/22 13:36:00 j_novak Exp $
133  *
134  */
135 
136 // headers C
137 #include <cstdlib>
138 #include <cstring>
139 #include <cmath>
140 
141 // Headers Lorene
142 #include "eos.h"
143 #include "tbl.h"
144 #include "utilitaires.h"
145 #include "unites.h"
146 
147 
148 namespace Lorene {
149  void interpol_herm(const Tbl& , const Tbl&, const Tbl&, double, int&,
150  double&, double& ) ;
151 
152  void interpol_linear(const Tbl&, const Tbl&, double, int&, double&) ;
153 
154  void interpol_quad(const Tbl&, const Tbl&, double, int&, double&) ;
155 
156 
157 
158  //----------------------------//
159  // Constructors //
160  //----------------------------//
161 
162 // Standard constructor
163 // --------------------
164 Eos_tabul::Eos_tabul(const char* name_i, const char* table,
165  const char* path) : Eos(name_i)
166 {
167  tablename = path ;
168  tablename += "/" ;
169  tablename += table ;
170 
171  read_table() ;
172 }
173 
174 // Standard constructor with full filename
175 // ---------------------------------------
176  Eos_tabul::Eos_tabul(const char* name_i, const char* file_name)
177  : Eos(name_i) {
178 
179  tablename = file_name ;
180 
181  read_table() ;
182 
183 }
184 
185 
186 // Constructor from binary file
187 // ----------------------------
188  Eos_tabul::Eos_tabul(FILE* fich) : Eos(fich) {
189 
190  char tmp_string[160] ;
191  fread(tmp_string, sizeof(char), 160, fich) ;
192  tablename = tmp_string ;
193 
194  read_table() ;
195 
196 }
197 
198 
199 
200 // Constructor from a formatted file
201 // ---------------------------------
202  Eos_tabul::Eos_tabul(ifstream& fich, const char* table) :
203  Eos(fich) {
204 
205  fich >> tablename ;
206  tablename += "/" ;
207  tablename += table ;
208 
209  read_table() ;
210 
211 }
212 
213  Eos_tabul::Eos_tabul(ifstream& fich) : Eos(fich)
214 {
215  fich >> tablename ;
216 
217  read_table() ;
218 }
219 
220 // Standard constructor with a name
221 // ---------------------------------
222  Eos_tabul::Eos_tabul(const char* name_i) : Eos(name_i),
223  logh(0x0), logp(0x0), dlpsdlh(0x0),
224  lognb(0x0), dlpsdlnb(0x0), log_cs2(0x0)
225 {}
226 
227 
228  //--------------//
229  // Destructor //
230  //--------------//
231 
233  if (logh != 0x0) delete logh ;
234  if (logp != 0x0) delete logp ;
235  if (dlpsdlh != 0x0) delete dlpsdlh ;
236  if (lognb != 0x0) delete lognb ;
237  if (dlpsdlnb != 0x0) delete dlpsdlnb ;
238  if (log_cs2 != 0x0) delete log_cs2 ;
239 }
240 
241  //------------//
242  // Outputs //
243  //------------//
244 
245 void Eos_tabul::sauve(FILE* fich) const {
246 
247  Eos::sauve(fich) ;
248 
249  char tmp_string[160] ;
250  strcpy(tmp_string, tablename.c_str()) ;
251  fwrite(tmp_string, sizeof(char), 160, fich) ;
252 }
253 
254  //------------------------//
255  // Reading of the table //
256  //------------------------//
257 
259 
260  using namespace Unites ;
261 
262  ifstream is_meos("meos_is_being_built.d") ;
263 
264  ifstream fich(tablename.data()) ;
265 
266  if (!fich) {
267  cerr << "Eos_tabul::read_table(): " << endl ;
268  cerr << "Problem in opening the EOS file!" << endl ;
269  cerr << "While trying to open " << tablename << endl ;
270  cerr << "Aborting..." << endl ;
271  abort() ;
272  }
273 
274  fich.ignore(1000, '\n') ; // Jump over the first header
275  fich.ignore(1) ;
276  getline(fich, authors, '\n') ;
277  for (int i=0; i<3; i++) { // jump over the file
278  fich.ignore(1000, '\n') ; // header
279  } //
280 
281  int nbp ;
282  fich >> nbp ; fich.ignore(1000, '\n') ; // number of data
283  if (nbp<=0) {
284  cerr << "Eos_tabul::read_table(): " << endl ;
285  cerr << "Wrong value for the number of lines!" << endl ;
286  cerr << "nbp = " << nbp << endl ;
287  cerr << "Aborting..." << endl ;
288  abort() ;
289  }
290 
291  for (int i=0; i<3; i++) { // jump over the table
292  fich.ignore(1000, '\n') ; // description
293  }
294 
295  press = new double[nbp] ;
296  nb = new double[nbp] ;
297  ro = new double[nbp] ;
298 
299  Tbl press_tbl(nbp) ; press_tbl.set_etat_qcq() ;
300  Tbl nb_tbl(nbp) ; nb_tbl.set_etat_qcq() ;
301  Tbl ro_tbl(nbp) ; ro_tbl.set_etat_qcq() ;
302 
303  logh = new Tbl(nbp) ;
304  logp = new Tbl(nbp) ;
305  dlpsdlh = new Tbl(nbp) ;
306  lognb = new Tbl(nbp) ;
307  dlpsdlnb = new Tbl(nbp) ;
308 
309  logh->set_etat_qcq() ;
310  logp->set_etat_qcq() ;
311  dlpsdlh->set_etat_qcq() ;
312  lognb->set_etat_qcq() ;
313  dlpsdlnb->set_etat_qcq() ;
314 
315  double rhonuc_cgs = rhonuc_si * 1e-3 ;
316  double c2_cgs = c_si * c_si * 1e4 ;
317 
318  int no ;
319  double nb_fm3, rho_cgs, p_cgs ;
320 
321  for (int i=0; i<nbp; i++) {
322 
323  fich >> no ;
324  fich >> nb_fm3 ;
325  fich >> rho_cgs ;
326  fich >> p_cgs ; fich.ignore(1000,'\n') ;
327  if ( (nb_fm3<0) || (rho_cgs<0) || (p_cgs < 0) ){
328  cout << "Eos_tabul::read_table(): " << endl ;
329  cout << "Negative value in table!" << endl ;
330  cout << "nb = " << nb_fm3 << ", rho = " << rho_cgs <<
331  ", p = " << p_cgs << endl ;
332  cout << "Aborting..." << endl ;
333  abort() ;
334  }
335 
336  press[i] = p_cgs / c2_cgs ;
337  nb[i] = nb_fm3 ;
338  ro[i] = rho_cgs ;
339 
340  press_tbl.set(i) = press[i] ;
341  nb_tbl.set(i) = nb[i] ;
342  ro_tbl.set(i) = ro[i] ;
343  }
344 
345  double ww = 0. ;
346  bool store_offset = false ;
347  bool compute_offset = true ;
348  if (is_meos) {
349  string temp ;
350  string ok("ok") ;
351  is_meos >> temp ;
352  if (temp.find(ok) != string::npos) {
353  is_meos >> ww ;
354  compute_offset = false ;
355  }
356  else {
357  is_meos.close() ;
358  store_offset = true ;
359  }
360  }
361 
362  for (int i=0; i<nbp; i++) {
363  double h = log( (ro[i] + press[i]) /
364  (10 * nb[i] * rhonuc_cgs) ) ;
365 
366  if ((i==0) && compute_offset) { ww = h ; }
367  h = h - ww + 1.e-14 ;
368 
369  logh->set(i) = log10( h ) ;
370  logp->set(i) = log10( press[i] / rhonuc_cgs ) ;
371  dlpsdlh->set(i) = h * (ro[i] + press[i]) / press[i] ;
372  lognb->set(i) = log10(nb[i]) ;
373  }
374 
375  if (store_offset == true) {
376  ofstream write_meos("meos_is_being_built.d", ios_base::app) ;
377  write_meos << "ok" << endl ;
378  write_meos << setprecision(16) << ww << endl ;
379  }
380 
381  // Computation of dpdnb
382  //---------------------
383  Tbl logn0 = *lognb * log(10.) ;
384  Tbl logp0 = ((*logp) + log10(rhonuc_cgs)) * log(10.) ;
385  compute_derivative(logn0, logp0, *dlpsdlnb) ;
386 
387  // Computation of the sound speed
388  //-------------------------------
389  Tbl tmp(nbp) ; tmp.set_etat_qcq() ;
390  compute_derivative(ro_tbl,press_tbl,tmp) ; // tmp = c_s^2 = dp/de
391  for (int i=0; i<nbp; i++) {
392  if (tmp(i) < 0.) {
393  tmp.set(i) = - tmp(i) ;
394  }
395  }
396  log_cs2 = new Tbl(log10(tmp)) ;
397 
398  hmin = pow( double(10), (*logh)(0) ) ;
399  hmax = pow( double(10), (*logh)(nbp-1) ) ;
400  cout << "hmin, hmax : " << hmin << " " << hmax << endl ;
401 
402  fich.close();
403 
404  delete [] press ;
405  delete [] nb ;
406  delete [] ro ;
407 
408 
409 }
410 
411 
412  //------------------------------//
413  // Computational routines //
414  //------------------------------//
415 
416 // Baryon density from enthalpy
417 //------------------------------
418 
419 double Eos_tabul::nbar_ent_p(double ent, const Param* ) const {
420 
421  static int i_near = logh->get_taille() / 2 ;
422 
423  if ( ent > hmin ) {
424  if (ent > hmax) {
425  cout << "Eos_tabul::nbar_ent_p : ent > hmax !" << endl ;
426  abort() ;
427  }
428  double logh0 = log10( ent ) ;
429  double logp0 ;
430  double dlpsdlh0 ;
431  interpol_herm(*logh, *logp, *dlpsdlh, logh0, i_near, logp0,
432  dlpsdlh0) ;
433 
434  double pp = pow(double(10), logp0) ;
435 
436  double resu = pp / ent * dlpsdlh0 * exp(-ent) ;
437  return resu ;
438  }
439  else{
440  return 0 ;
441  }
442 }
443 
444 // Energy density from enthalpy
445 //------------------------------
446 
447 double Eos_tabul::ener_ent_p(double ent, const Param* ) const {
448 
449  static int i_near = logh->get_taille() / 2 ;
450 
451  if ( ent > hmin ) {
452  if (ent > hmax) {
453  cout << "Eos_tabul::ener_ent_p : ent > hmax !" << endl ;
454  abort() ;
455  }
456  double logh0 = log10( ent ) ;
457  double logp0 ;
458  double dlpsdlh0 ;
459  interpol_herm(*logh, *logp, *dlpsdlh, logh0, i_near, logp0,
460  dlpsdlh0) ;
461 
462  double pp = pow(double(10), logp0) ;
463 
464  double resu = pp / ent * dlpsdlh0 - pp ;
465  return resu ;
466  }
467  else{
468  return 0 ;
469  }
470 }
471 
472 // Pressure from enthalpy
473 //------------------------
474 
475 double Eos_tabul::press_ent_p(double ent, const Param* ) const {
476 
477  static int i_near = logh->get_taille() / 2 ;
478 
479  if ( ent > hmin ) {
480  if (ent > hmax) {
481  cout << "Eos_tabul::press_ent_p : ent > hmax !" << endl ;
482  abort() ;
483  }
484 
485  double logh0 = log10( ent ) ;
486  double logp0 ;
487  double dlpsdlh0 ;
488  interpol_herm(*logh, *logp, *dlpsdlh, logh0, i_near, logp0,
489  dlpsdlh0) ;
490  return pow(double(10), logp0) ;
491  }
492  else{
493  return 0 ;
494  }
495 }
496 
497 // dln(n)/ln(H) from enthalpy
498 //---------------------------
499 
500 double Eos_tabul::der_nbar_ent_p(double ent, const Param* ) const {
501 
502  if ( ent > hmin ) {
503  if (ent > hmax) {
504  cout << "Eos_tabul::der_nbar_ent_p : ent > hmax !" << endl ;
505  abort() ;
506  }
507 
508  double zeta = der_press_ent_p(ent) / der_press_nbar_p(ent) ;
509 
510  return zeta ;
511 
512  }
513  else
514 
515  return 1./(der_press_nbar_p(hmin)-1.) ; // to ensure continuity
516 
517 }
518 
519 
520 // dln(e)/ln(H) from enthalpy
521 //---------------------------
522 
523 double Eos_tabul::der_ener_ent_p(double ent, const Param* ) const {
524 
525  if ( ent > hmin ) {
526 
527  if (ent > hmax) {
528  cout << "Eos_tabul::der_ener_ent_p : ent > hmax !" << endl ;
529  abort() ;
530  }
531 
532  return ( der_nbar_ent_p(ent)
533  *( double(1.) + press_ent_p(ent)/ener_ent_p(ent) )) ;
534 
535  } else return der_nbar_ent_p(hmin) ;
536 
537 }
538 
539 
540 // dln(p)/ln(H) from enthalpy
541 //---------------------------
542 
543 double Eos_tabul::der_press_ent_p(double ent, const Param* ) const {
544 
545  static int i_near = logh->get_taille() / 2 ;
546 
547  if ( ent > hmin ) {
548  if (ent > hmax) {
549  cout << "Eos_tabul::der_press_ent_p : ent > hmax !" << endl ;
550  abort() ;
551  }
552 
553  double logh0 = log10( ent ) ;
554  double logp0 ;
555  double dlpsdlh0 ;
556  interpol_herm(*logh, *logp, *dlpsdlh, logh0, i_near, logp0,
557  dlpsdlh0) ;
558 
559  return dlpsdlh0 ;
560 
561  }
562  else{
563 
564  return 0 ;
565  // return der_press_ent_p(hmin) ; // to ensure continuity
566  }
567 }
568 
569 
570 // dln(p)/dln(n) from enthalpy
571 //---------------------------
572 
573 double Eos_tabul::der_press_nbar_p(double ent, const Param*) const {
574 
575  static int i_near = logh->get_taille() / 2 ;
576 
577  if ( ent > hmin ) {
578  if (ent > hmax) {
579  cout << "Eos_tabul::der_press_nbar_p : ent > hmax !" << endl ;
580  abort() ;
581  }
582 
583  double logh0 = log10( ent ) ;
584  double dlpsdlnb0 ;
585 
586  interpol_linear(*logh, *dlpsdlnb, logh0, i_near, dlpsdlnb0) ;
587 
588  return dlpsdlnb0 ;
589 
590  }
591  else{
592 
593  return (*dlpsdlnb)(0) ;
594  // return der_press_nbar_p(hmin) ; // to ensure continuity
595 
596  }
597 }
598 
599 double Eos_tabul::csound_square_ent_p(double ent, const Param*) const {
600  static int i_near = lognb->get_taille() / 2 ;
601 
602  if ( ent > hmin ) {
603  if (ent > hmax) {
604  cout << "Eos_tabul::csound_square_ent_p : ent>hmax !" << endl ;
605  abort() ;
606  }
607  double log_ent0 = log10( ent ) ;
608  double log_csound0 ;
609 
610  interpol_linear(*logh, *log_cs2, log_ent0, i_near, log_csound0) ;
611 
612  return pow(10., log_csound0) ;
613  }
614  else
615  {
616  return pow(10., (*log_cs2)(0)) ;
617  }
618 }
619 }
Cmp log(const Cmp &)
Neperian logarithm.
Definition: cmp_math.C:299
Cmp exp(const Cmp &)
Exponential.
Definition: cmp_math.C:273
Lorene prototypes.
Definition: app_hor.h:67
Standard units of space, time and mass.
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
Tbl * logp
Table of .
Definition: eos_tabul.h:206
Tbl * log_cs2
Table of .
Definition: eos_tabul.h:218
double hmin
Lower boundary of the enthalpy interval.
Definition: eos_tabul.h:197
Tbl * dlpsdlnb
Table of .
Definition: eos_tabul.h:215
Tbl * dlpsdlh
Table of .
Definition: eos_tabul.h:209
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
virtual ~Eos_tabul()
Destructor.
Definition: eos_tabul.C:232
virtual double der_ener_ent_p(double ent, const Param *par=0x0) const
Computes the logarithmic derivative from the log-enthalpy.
Definition: eos_tabul.C:523
string tablename
Name of the file containing the tabulated data.
Definition: eos_tabul.h:192
string authors
Authors - reference for the table.
Definition: eos_tabul.h:194
virtual void sauve(FILE *) const
Save in a file.
Definition: eos_tabul.C:245
virtual double der_press_nbar_p(double ent, const Param *par=0x0) const
Computes the logarithmic derivative from the log-enthalpy.
Definition: eos_tabul.C:573
Tbl * lognb
Table of .
Definition: eos_tabul.h:212
double hmax
Upper boundary of the enthalpy interval.
Definition: eos_tabul.h:200
virtual double der_nbar_ent_p(double ent, const Param *par=0x0) const
Computes the logarithmic derivative from the log-enthalpy.
Definition: eos_tabul.C:500
Parameter storage.
Definition: param.h:125
void compute_derivative(const Tbl &xx, const Tbl &ff, Tbl &dfdx)
Derives a function defined on an unequally-spaced grid, approximating it by piecewise parabolae...
Definition: misc.C:64
Cmp pow(const Cmp &, int)
Power .
Definition: cmp_math.C:351
virtual void read_table()
Reads the file containing the table and initializes in the arrays logh , logp and dlpsdlh ...
Definition: eos_tabul.C:258
Eos_tabul(const char *name_i, const char *table, const char *path)
Standard constructor.
Definition: eos_tabul.C:164
virtual double csound_square_ent_p(double, const Param *) const
Computes the sound speed squared from the enthapy with extra parameters (virtual function implemente...
Definition: eos_tabul.C:599
Cmp log10(const Cmp &)
Basis 10 logarithm.
Definition: cmp_math.C:325
int get_taille() const
Gives the total size (ie dim.taille)
Definition: tbl.h:397
virtual double der_press_ent_p(double ent, const Param *par=0x0) const
Computes the logarithmic derivative from the log-enthalpy.
Definition: eos_tabul.C:543
Basic array class.
Definition: tbl.h:161
virtual double press_ent_p(double ent, const Param *par=0x0) const
Computes the pressure from the log-enthalpy.
Definition: eos_tabul.C:475
Tbl * logh
Table of .
Definition: eos_tabul.h:203
virtual double ener_ent_p(double ent, const Param *par=0x0) const
Computes the total energy density from the log-enthalpy.
Definition: eos_tabul.C:447
virtual double nbar_ent_p(double ent, const Param *par=0x0) const
Computes the baryon density from the log-enthalpy.
Definition: eos_tabul.C:419