diff --git a/src/eos/private/helmholtz.cpp b/src/eos/private/helmholtz.cpp new file mode 100644 index 0000000..54dbf65 --- /dev/null +++ b/src/eos/private/helmholtz.cpp @@ -0,0 +1,865 @@ +// this file contains a C++ conversion of Frank Timmes' fortran code +// helmholtz.f90, which implements the Helmholtz Free Energy EOS described +// by Timmes & Swesty (2000) doi:10.1086/313304 -- Aaron Dotter 2025 + +#include +#include +#include +#include +#include + +using namespace std; + +// interpolating polynomila function definitions +double psi0(double z) {return z*z*z * (z * (-6.0 * z + 15.0) - 10.0) + 1.0;} + +double dpsi0(double z) {return z*z * ( z * (-30.0 * z + 60.0) - 30.0);} + +double ddpsi0(double z) {return z * ( z * (-120.0 * z + 180.0) - 60.0);} + +double psi1(double z) {return z * ( z*z * ( z * (-3.0*z + 8.0) - 6.0) + 1.0);} + +double dpsi1(double z) {return z*z * ( z * (-15.0*z + 32.0) - 18.0) +1.0;} + +double ddpsi1(double z) {return z * (z * (-60.0*z + 96.0) - 36.0);} + +double psi2(double z) {return 0.5 * z*z * ( z* ( z * (-z + 3.0) - 3.0) + 1.0);} + +double dpsi2(double z) {return 0.5 * z * ( z * (z * (-5.0*z + 12.0) - 9.0) + 2.0);} + +double ddpsi2(double z) {return 0.5*(z*( z * (-20.*z + 36.) - 18.) + 2.);} + +double xpsi0(double z) {return z * z * (2.0 * z - 3.0) + 1.0;} + +double xdpsi0(double z) {return z * (6.0*z - 6.0);} + +double xpsi1(double z) {return z * ( z * (z - 2.0) + 1.0);} + +double xdpsi1(double z) {return z * (3.0 * z - 4.0) + 1.0;} + +double h3(double fi[36], double w0t, double w1t, double w0mt, double w1mt, + double w0d, double w1d, double w0md, double w1md) { + return fi[0] * w0d * w0t + fi[1] * w0md * w0t + + fi[2] * w0d * w0mt + fi[3] * w0md * w0mt + + fi[4] * w0d * w1t + fi[5] * w0md * w1t + + fi[6] * w0d * w1mt + fi[7] * w0md * w1mt + + fi[8] * w1d * w0t + fi[9] * w1md * w0t + + fi[10] * w1d * w0mt + fi[11] * w1md * w0mt + + fi[12] * w1d * w1t + fi[13] * w1md * w1t + + fi[14] * w1d * w1mt + fi[15] * w1md * w1mt; + } + +double h5(double fi[36], double w0t, double w1t, double w2t,double w0mt, + double w1mt, double w2mt, double w0d, double w1d, double w2d, + double w0md, double w1md, double w2md) { + return fi[0] * w0d * w0t + fi[1] * w0md * w0t + + fi[2] * w0d * w0mt + fi[3] * w0md * w0mt + + fi[4] * w0d * w1t + fi[5] * w0md * w1t + + fi[6] * w0d * w1mt + fi[7] * w0md * w1mt + + fi[8] * w0d * w2t + fi[ 9] * w0md * w2t + + fi[10] * w0d * w2mt + fi[11] * w0md * w2mt + + fi[12] * w1d * w0t + fi[13] * w1md * w0t + + fi[14] * w1d * w0mt + fi[15] * w1md * w0mt + + fi[16] * w2d * w0t + fi[17] * w2md * w0t + + fi[18] * w2d * w0mt + fi[19] * w2md * w0mt + + fi[20] * w1d * w1t + fi[21] * w1md * w1t + + fi[22] * w1d * w1mt + fi[23] * w1md * w1mt + + fi[24] * w2d * w1t + fi[25] * w2md * w1t + + fi[26] * w2d * w1mt + fi[27] * w2md * w1mt + + fi[28] * w1d * w2t + fi[29] * w1md * w2t + + fi[30] * w1d * w2mt + fi[31] * w1md * w2mt + + fi[32] * w2d * w2t + fi[33] * w2md * w2t + + fi[34] * w2d * w2mt + fi[35] * w2md * w2mt; + } + +// some global quantities including table size, limits, and deltas +const int IMAX=541, JMAX=201; +const double tlo = 3.0, thi = 13.0; +const double dlo = -12.0, dhi = 15.0; +const double tstp = (thi - tlo)/(JMAX-1), tstpi=1/tstp; +const double dstp = (dhi-dlo)/(IMAX-1), dstpi = 1/dstp; +double t[JMAX], d[IMAX]; +double f[IMAX][JMAX], fd[IMAX][JMAX], ft[IMAX][JMAX]; +double fdd[IMAX][JMAX], ftt[IMAX][JMAX], fdt[IMAX][JMAX]; +double fddt[IMAX][JMAX], fdtt[IMAX][JMAX], fddtt[IMAX][JMAX]; +double dpdf[IMAX][JMAX], dpdfd[IMAX][JMAX], dpdft[IMAX][JMAX]; +double dpdfdt[IMAX][JMAX], ef[IMAX][JMAX], efd[IMAX][JMAX]; +double eft[IMAX][JMAX], efdt[IMAX][JMAX], xf[IMAX][JMAX]; +double xfd[IMAX][JMAX], xft[IMAX][JMAX], xfdt[IMAX][JMAX]; +double dt_sav[JMAX], dt2_sav[JMAX], dti_sav[JMAX], dt2i_sav[JMAX]; +double dd_sav[IMAX], dd2_sav[IMAX], ddi_sav[IMAX]; + +// this function reads in the HELM table and stores in the above arrays +void read_helm_table() { + string data; + int i, j; + + //set T and Rho (d) arrays + for (j=0; j> f[i][j]; + id >> fd[i][j]; + id >> ft[i][j]; + id >> fdd[i][j]; + id >> ftt[i][j]; + id >> fdt[i][j]; + id >> fddt[i][j]; + id >> fdtt[i][j]; + id >> fddtt[i][j]; + } + } + + //read the pressure derivative with density + for (j=0; j> dpdf[i][j]; + id >> dpdfd[i][j]; + id >> dpdft[i][j]; + id >> dpdfdt[i][j]; + } + } + + //read the electron chemical potential + for (j=0; j> ef[i][j]; + id >> efd[i][j]; + id >> eft[i][j]; + id >> efdt[i][j]; + } + } + + //read the number density + for (j=0; j> xf[i][j]; + id >> xfd[i][j]; + id >> xft[i][j]; + id >> xfdt[i][j]; + } + } + + helm_table.close(); //done reading + + // construct the temperature and density deltas and their inverses + for (j=0; j