Neutron Star Outer Crust¶
The class eos_crust computes the composition and EOS of the outer crust of a neutron star from \(10^{6}~\mathrm{g}/\mathrm{cm}^3\) up to the neutron drip density of \(4 \times 10^{11}~\mathrm{g}/\mathrm{cm}^3\). It uses a simple expression for the lattice energy and works with any nuclear mass formula specified as an object of type nucmass.
Outer crust example¶
This example computes the outer crust EOS from the
eos_crust class and then compares it with the numerical
values from the original paper in [Baym71tg] as stored in the
file examples/ex_bps_input.txt
. Then it computes several
crusts from [Shen11b], [Steiner12], and [Newton13].
/* Example: ex_eos_crust.cpp
-------------------------------------------------------------------
Compute the Baym-Pethick-Sutherland equation of state
*/
#include <fstream>
#include <o2scl/test_mgr.h>
#include <o2scl/lib_settings.h>
#include <o2scl/table_units.h>
#include <o2scl/eos_crust.h>
#include <o2scl/eos_tov.h>
#include <o2scl/hdf_io.h>
using namespace std;
using namespace o2scl;
using namespace o2scl_const;
using namespace o2scl_hdf;
// A simple function to load the BPS data without
// HDF support, in case O2scl was compiled without it.
int bps_load(table_units<> &bps);
int main(void) {
test_mgr t;
t.set_output_level(1);
cout.setf(ios::scientific);
eos_crust be;
// Proton and mass numbers
int Z, A;
// The baryon number density
double barn;
// Energy density from BPS table in units of g/cm^3
double ed_bps;
// Pressure from BPS table in units of dyn/cm^2
double pr_bps;
// Read the original BPS results
table_units<> bps;
bps_load(bps);
// Ensure that this works without GNU units
convert_units<double> &cu=o2scl_settings.get_convert_units();
// Cubic spline interpolation doesn't do very well here, so we use
// linear interpolation to interpolate the BPS table
bps.set_interp_type(itp_linear);
// Tabulate the o2scl results using eos_crust::calc_pressure() and
// compare them to the original table. The energy density
// and pressure are output in MeV/fm^3, the baryon number density
// is given in fm^{-3}. The last two columns are the fractional
// deviations from the original BPS table.
cout << "Default mass formula, using calc_pressure()." << endl;
cout << "eden pres barn A Z ";
cout << "ed_err pr_err" << endl;
// Energy, pressure, etc.
thermo &th=be.def_thermo;
for(double pr=8.9e-4/hc_mev_fm;pr>=2.12e-10/hc_mev_fm;pr/=2.0) {
th.pr=pr;
be.calc_pressure(barn,Z,A);
// Output energy and pressure in MeV/fm^3
cout << th.ed*hc_mev_fm << " " << th.pr*hc_mev_fm
<< " " << barn << " ";
cout.width(3);
cout << A << " ";
cout.width(3);
cout << Z << " ";
// Convert the BPS results from g/cm^3 and dyn/cm^2 to MeV/fm^3
ed_bps=cu.convert("g/cm^3","MeV/fm^3",
bps.interp("nb",barn*1.0e39,"rho"));
pr_bps=cu.convert("dyne/cm^2","MeV/fm^3",
bps.interp("nb",barn*1.0e39,"P"));
cout.setf(ios::showpos);
cout << (ed_bps-th.ed*hc_mev_fm)/ed_bps << " "
<< (pr_bps-th.pr*hc_mev_fm)/pr_bps << endl;
cout.unsetf(ios::showpos);
t.test_rel((ed_bps-th.ed*hc_mev_fm)/ed_bps,0.0,2.0e-3,"Energy");
t.test_rel((pr_bps-th.pr*hc_mev_fm)/pr_bps,0.0,1.5e-1,"Pressure");
}
cout << endl;
// Tabulate the o2scl results using eos_crust::calc_density() and
// compare them to the original table
cout << "Default mass formula, using calc_density()." << endl;
cout << "eden pres barn A Z ";
cout << "ed_err pr_err" << endl;
for(barn=4.19e-4;barn>=6.39e-9;barn/=2.0) {
be.calc_density(barn,Z,A);
ed_bps=cu.convert("g/cm^3","MeV/fm^3",
bps.interp("nb",barn*1.0e39,"rho"));
pr_bps=cu.convert("dyne/cm^2","MeV/fm^3",
bps.interp("nb",barn*1.0e39,"P"));
cout << th.ed*hc_mev_fm << " " << th.pr*hc_mev_fm
<< " " << barn << " ";
cout.width(3);
cout << A << " ";
cout.width(3);
cout << Z << " ";
cout.setf(ios::showpos);
cout << (ed_bps-th.ed*hc_mev_fm)/ed_bps << " "
<< (pr_bps-th.pr*hc_mev_fm)/pr_bps << endl;
cout.unsetf(ios::showpos);
t.test_rel((ed_bps-th.ed*hc_mev_fm)/ed_bps,0.0,2.0e-3,"Energy");
t.test_rel((pr_bps-th.pr*hc_mev_fm)/pr_bps,0.0,1.5e-1,"Pressure");
}
cout << endl;
// ---------------------------------------------------------
// Create a table comparing the crust EOSs from eos_tov_interp
// Read the APR EOS table
table_units<> tab;
hdf_file hf;
string name;
hf.open("ex_eos_had_apr_nstar.o2");
hdf_input(hf,tab,name);
hf.close();
// Send the EOS to the eos_tov_interp object
eos_tov_interp te;
te.read_table(tab,"ed","pr","nb");
// Define a grid of pressures over which to evaluate the EOS
size_t ngrid=200;
uniform_grid_log_end<double> pr_grid(2.0e-14,4.0e-3,ngrid-1);
// Create a table to store the data
table_units<> crust_comp;
crust_comp.line_of_names("pr ed_NVBPS ed_SHO ed_PNM_L40 ed_PNM_L100");
crust_comp.line_of_names("ed_J35_L40 ed_J35_L100 ed_SLy4 ed_APR ed_Rs");
crust_comp.line_of_names("nb_NVBPS nb_SHO nb_PNM_L40 nb_PNM_L100");
crust_comp.line_of_names("nb_J35_L40 nb_J35_L100 nb_SLy4 nb_APR nb_Rs");
crust_comp.set_unit("pr","1/fm^4");
crust_comp.set_unit("ed_NVBPS","1/fm^4");
crust_comp.set_unit("ed_SHO","1/fm^4");
crust_comp.set_unit("ed_PNM_L40","1/fm^4");
crust_comp.set_unit("ed_PNM_L100","1/fm^4");
crust_comp.set_unit("ed_J35_L40","1/fm^4");
crust_comp.set_unit("ed_J35_L100","1/fm^4");
crust_comp.set_unit("ed_APR","1/fm^4");
crust_comp.set_unit("ed_SLy4","1/fm^4");
crust_comp.set_unit("ed_Rs","1/fm^4");
crust_comp.set_unit("nb_NVBPS","1/fm^3");
crust_comp.set_unit("nb_SHO","1/fm^3");
crust_comp.set_unit("nb_PNM_L40","1/fm^3");
crust_comp.set_unit("nb_PNM_L100","1/fm^3");
crust_comp.set_unit("nb_J35_L40","1/fm^3");
crust_comp.set_unit("nb_J35_L100","1/fm^3");
crust_comp.set_unit("nb_APR","1/fm^3");
crust_comp.set_unit("nb_SLy4","1/fm^3");
crust_comp.set_unit("nb_Rs","1/fm^3");
// Energy density and baryon density
double ed, nb;
cout << "NVBPS crust." << endl;
crust_comp.set_nlines(200);
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_NVBPS",i,ed);
crust_comp.set("nb_NVBPS",i,nb);
if (i==199) {
cout << pr_grid[i] << " " << ed << " " << nb << endl;
}
}
cout << "SHO crust." << endl;
te.sho11_low_dens_eos();
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_SHO",i,ed);
crust_comp.set("nb_SHO",i,nb);
if (i==199) {
cout << pr_grid[i] << " " << ed << " " << nb << endl;
}
}
cout << "NGL13, L=40 crust." << endl;
te.ngl13_low_dens_eos(40.0);
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_PNM_L40",i,ed);
crust_comp.set("nb_PNM_L40",i,nb);
}
cout << "NGL13, L=100 crust." << endl;
te.ngl13_low_dens_eos(100.0);
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_PNM_L100",i,ed);
crust_comp.set("nb_PNM_L100",i,nb);
}
cout << "NGL13, L=40 crust." << endl;
te.ngl13_low_dens_eos(40.0,"J35");
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_J35_L40",i,ed);
crust_comp.set("nb_J35_L40",i,nb);
}
cout << "NGL13, L=100 crust." << endl;
te.ngl13_low_dens_eos(100.0,"J35");
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_J35_L100",i,ed);
crust_comp.set("nb_J35_L100",i,nb);
}
cout << "S12, SLy4 crust." << endl;
te.s12_low_dens_eos("SLy4");
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_SLy4",i,ed);
crust_comp.set("nb_SLy4",i,nb);
}
cout << "S12, APR crust." << endl;
te.s12_low_dens_eos("APR");
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_APR",i,ed);
crust_comp.set("nb_APR",i,nb);
}
cout << "S12, Rs crust." << endl;
te.s12_low_dens_eos("Rs");
for(size_t i=0;i<200;i++) {
crust_comp.set("pr",i,pr_grid[i]);
te.ed_nb_from_pr(cu.convert("1/fm^4","Msun/km^3",pr_grid[i]),ed,nb);
ed=cu.convert("Msun/km^3","1/fm^4",ed);
crust_comp.set("ed_Rs",i,ed);
crust_comp.set("nb_Rs",i,nb);
}
cout << endl;
hf.open_or_create("ex_crust_comp.o2");
hdf_output(hf,crust_comp,"crust_comp");
hf.close();
t.report();
return 0;
}
// End of example
int bps_load(table_units<> &bps) {
bps.line_of_names("rho P nb");
ifstream fin;
fin.open("ex_bps_input.txt");
string tmp;
fin >> tmp >> tmp >> tmp;
for(size_t i=0;i<43;i++) {
double line[3];
fin >> line[0] >> line[1] >> line[2];
bps.line_of_data(3,line);
}
fin.close();
return 0;
}