aboutsummaryrefslogtreecommitdiff
path: root/src/tov.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tov.c')
-rw-r--r--src/tov.c994
1 files changed, 994 insertions, 0 deletions
diff --git a/src/tov.c b/src/tov.c
new file mode 100644
index 0000000..17e37d3
--- /dev/null
+++ b/src/tov.c
@@ -0,0 +1,994 @@
+/* file tov.c
+ * author Frank Loeffler, converted from fortran thorn by Ian Hawke
+ * date 2002/10/21
+ * desc TOV initial data
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+
+#include <cctk.h>
+#include <cctk_Arguments.h>
+#include <cctk_Parameters.h>
+
+#include "AEIThorns/Constants/src/constants.h"
+
+#include "tov.h"
+
+#define velx (&vel[0*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define vely (&vel[1*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define velz (&vel[2*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define velx_p (&vel_p[0*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define vely_p (&vel_p[1*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define velz_p (&vel_p[2*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define velx_p_p (&vel_p_p[0*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define vely_p_p (&vel_p_p[1*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define velz_p_p (&vel_p_p[2*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+
+#define sx (&scon[0*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sy (&scon[1*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sz (&scon[2*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sx_p (&scon_p[0*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sy_p (&scon_p[1*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sz_p (&scon_p[2*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sx_p_p (&scon_p_p[0*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sy_p_p (&scon_p_p[1*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+#define sz_p_p (&scon_p_p[2*cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]])
+
+CCTK_REAL * TOV_Surface=0;
+CCTK_REAL * TOV_R_Surface=0;
+CCTK_REAL * TOV_Atmosphere=0;
+
+CCTK_REAL * TOV_r_1d=0;
+CCTK_REAL * TOV_rbar_1d=0;
+CCTK_REAL * TOV_press_1d=0;
+CCTK_REAL * TOV_phi_1d=0;
+CCTK_REAL * TOV_m_1d=0;
+
+#include "utils.inc"
+
+void TOV_C_ParamCheck(CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ if (TOV_Solve_for_TOVs != 3)
+ {
+ if (TOV_Solve_for_TOVs == 2)
+ {
+ CCTK_WARN(1, "TOV_Solve_for_TOVs is depreciated. "
+ "Use TOV_Enforce_Interpolation=\"yes\" instead.\n");
+ if (CCTK_ParameterSet("TOV_Enforce_Interpolation",
+ "Whisky_TOVSolverC",
+ "true"))
+ CCTK_WARN(0, "Error while steering this parameter.\n");
+ else
+ CCTK_WARN(1, "Steered this parameter for now accordingly.\n");
+ }
+ else
+ CCTK_WARN(1, "TOV_Solve_for_TOVs is depreciated. "
+ "Use TOV_Enforce_Interpolation instead.\n");
+ }
+}
+
+/* centered differencing with one-sided differencing at the boundary */
+#define DIFF_X(a) (((i==0)?(a[CCTK_GFINDEX3D(cctkGH, i+1, j, k)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i , j, k)]): \
+ (i==(cctk_lsh[0]-1))? \
+ (a[CCTK_GFINDEX3D(cctkGH, i , j, k)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i-1, j, k)]): \
+ 0.5*(a[CCTK_GFINDEX3D(cctkGH, i+1, j, k)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i-1, j, k)]))/\
+ CCTK_DELTA_SPACE(0))
+#define DIFF_Y(a) (((j==0)?(a[CCTK_GFINDEX3D(cctkGH, i, j+1, k)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i, j , k)]): \
+ (j==(cctk_lsh[1]-1))? \
+ (a[CCTK_GFINDEX3D(cctkGH, i, j , k)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i, j-1, k)]): \
+ 0.5*(a[CCTK_GFINDEX3D(cctkGH, i, j+1, k)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i, j-1, k)]))/\
+ CCTK_DELTA_SPACE(1))
+#define DIFF_Z(a) (((k==0)?(a[CCTK_GFINDEX3D(cctkGH, i, j, k+1)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i, j, k )]): \
+ (k==(cctk_lsh[2]-1))? \
+ (a[CCTK_GFINDEX3D(cctkGH, i, j, k )] - \
+ a[CCTK_GFINDEX3D(cctkGH, i, j, k-1)]): \
+ 0.5*(a[CCTK_GFINDEX3D(cctkGH, i, j, k+1)] - \
+ a[CCTK_GFINDEX3D(cctkGH, i, j, k-1)]))/\
+ CCTK_DELTA_SPACE(2))
+
+
+/*@@
+ @routine TOV_Source_RHS
+ @date Thu Oct 24 14:30:00 2002
+ @author Frank Loeffler - converted fortran routine by Ian Hawke
+ @desc
+ The source terms for the ODEs. These are equations (2), (3), (4)
+ and (18) from the Baumgarte notes.
+ That is the vector in order is (P, m, phi, rbar).
+ @enddesc
+ @calls
+ @calledby
+ @history
+ @endhistory
+@@*/
+void TOV_C_Source_RHS(CCTK_REAL r, CCTK_REAL K, CCTK_REAL Gamma,
+ CCTK_REAL old_data[4], CCTK_REAL source_data[4])
+{
+ CCTK_REAL LOCAL_TINY, PI;
+ CCTK_REAL press, rho, eps, mu, m, phi;
+ CCTK_REAL log_rbar_over_r, r_minus_two_m;
+
+ LOCAL_TINY = 1.0e-35;
+ PI=4.0*atan(1.0);
+
+ press = old_data[0];
+ if (press < LOCAL_TINY)
+ press = LOCAL_TINY;
+ m = old_data[1];
+ phi = old_data[2];
+ log_rbar_over_r = old_data[3];
+
+ rho = pow(press / K, 1.0 / Gamma);
+ eps = press / (Gamma - 1.0) / rho;
+ mu = rho * (1.0 + eps);
+
+ r_minus_two_m = r - 2.0 * m;
+
+ if ((r==0.0) && (m==0.0))
+ {
+ /* source_data[0] = 0.0; */
+ source_data[1] = 0.0;
+ source_data[2] = 0.0;
+ source_data[3] = 0.0;
+ }
+ else
+ {
+ source_data[2] = (m + 4*PI * r*r*r * press) / r_minus_two_m / r;
+ /* source_data[0] = -(press + mu) * source_data[2]; */
+ source_data[0] = -(press + mu) *
+ (m + 4*PI * r*r*r * press) / r_minus_two_m / r;
+ source_data[1] = 4*PI * r*r * mu;
+ source_data[3] = (sqrt(r) - sqrt(r_minus_two_m)) / r / sqrt(r_minus_two_m);
+ }
+}
+
+/*@@
+ @routine TOV_Integrate_RHS
+ @date Thu Oct 24 14:30:00 2002
+ @author Frank Loeffler, converted fortran routine by Ian Hawke
+ @desc
+ Integrates the ODEs using RK4.
+ We rescale at the end to match to a Schwarzschild exterior.
+ @enddesc
+ @calls
+ @calledby
+ @history
+ @endhistory
+@@*/
+
+void TOV_C_Integrate_RHS(CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL LOCAL_TINY;
+
+ CCTK_INT star, star_i, i, TOV_Surface_Index;
+ CCTK_REAL old_data[4], source_data[4], in_data[4], new_data[4],
+ k1[4], k2[4], k3[4], k4[4];
+ CCTK_REAL Surface_Mass, factor, local_rho;
+ CCTK_REAL rho_central;
+
+ LOCAL_TINY = 1.0e-20;
+
+ assert(TOV_Surface!=0);
+ assert(TOV_R_Surface!=0);
+ assert(TOV_Atmosphere!=0);
+
+ assert(TOV_r_1d!=0);
+ assert(TOV_rbar_1d!=0);
+ assert(TOV_press_1d!=0);
+ assert(TOV_phi_1d!=0);
+ assert(TOV_m_1d!=0);
+
+ /* do it for all stars */
+ for (star=0; star < TOV_Num_TOVs; star++)
+ {
+ /* remember array index */
+ star_i = star * TOV_Num_Radial;
+
+ /* check for parameters */
+ if ((TOV_Rho_Central[star]==0.0) && (whisky_rho_central>0.0))
+ rho_central=whisky_rho_central;
+ else
+ rho_central=TOV_Rho_Central[star];
+
+ if (rho_abs_min > 0.0)
+ TOV_Atmosphere[star] = rho_abs_min;
+ else
+ TOV_Atmosphere[star] = rho_central * rho_rel_min;
+
+ if (initial_rho_abs_min > 0.0)
+ TOV_Atmosphere[star] = initial_rho_abs_min;
+ else
+ if (initial_rho_rel_min > 0.0)
+ TOV_Atmosphere[star] = rho_central * initial_rho_rel_min;
+
+ if (initial_atmosphere_factor > 0.0)
+ TOV_Atmosphere[star] *= initial_atmosphere_factor;
+
+ /* Set conformal state like set in parameter file if we do not use
+ * the old initial data. In this case we have to use what we get */
+ if (!TOV_Use_Old_Initial_Data)
+ if(CCTK_EQUALS(metric_type, "static conformal"))
+ {
+ *conformal_state=1;
+ if (CCTK_EQUALS(conformal_storage,"factor+derivs"))
+ *conformal_state = 2;
+ else if (CCTK_EQUALS(conformal_storage,"factor+derivs+2nd derivs"))
+ *conformal_state = 3;
+ CCTK_VInfo(CCTK_THORNSTRING, "conformal_state set to %d",
+ *conformal_state);
+ }
+
+ /* clear arrays first */
+ TOV_C_fill(&(TOV_press_1d[star_i]), TOV_Num_Radial, 0.0);
+ TOV_C_fill(&(TOV_m_1d [star_i]), TOV_Num_Radial, 0.0);
+ TOV_C_fill(&(TOV_phi_1d [star_i]), TOV_Num_Radial, 0.0);
+ TOV_C_fill(&(TOV_rbar_1d [star_i]), TOV_Num_Radial, 0.0);
+ TOV_C_fill(&(TOV_r_1d [star_i]), TOV_Num_Radial, 0.0);
+
+ /* set start values */
+ TOV_press_1d[star_i] = TOV_K[star] *
+ pow(rho_central, TOV_Gamma[star]);
+ /* TOV_r_1d [star_i] = LOCAL_TINY;
+ TOV_rbar_1d [star_i] = LOCAL_TINY;*/
+
+ /* build TOV_r_1d[] */
+ for (i=star_i+1; i < star_i+TOV_Num_Radial; i++)
+ TOV_r_1d[i] = TOV_r_1d[i-1] + TOV_dr[star];
+
+ TOV_Surface[star] = -1.0;
+ TOV_Surface_Index = -1.0;
+
+ /* loop over all radii */
+ for (i=star_i; (i < star_i+TOV_Num_Radial-1) &&
+ (TOV_Surface[star] < 0.0); i++)
+ {
+ old_data[0] = TOV_press_1d[i];
+ old_data[1] = TOV_m_1d[i];
+ old_data[2] = TOV_phi_1d[i];
+ if (TOV_rbar_1d[i]==TOV_r_1d[i])
+ old_data[3] = 0.0;
+ else
+ old_data[3] = log(TOV_rbar_1d[i] / TOV_r_1d[i]);
+
+ in_data[0] = old_data[0];
+ in_data[1] = old_data[1];
+ in_data[2] = old_data[2];
+ in_data[3] = old_data[3];
+
+ TOV_C_fill(source_data, 4, 0.0);
+
+ TOV_C_Source_RHS(TOV_r_1d[i],
+ TOV_K[star], TOV_Gamma[star],
+ in_data, source_data);
+ k1[0] = TOV_dr[star] * source_data[0];
+ k1[1] = TOV_dr[star] * source_data[1];
+ k1[2] = TOV_dr[star] * source_data[2];
+ k1[3] = TOV_dr[star] * source_data[3];
+ in_data[0] = old_data[0] + 0.5 * k1[0];
+ in_data[1] = old_data[1] + 0.5 * k1[1];
+ in_data[2] = old_data[2] + 0.5 * k1[2];
+ in_data[3] = old_data[3] + 0.5 * k1[3];
+
+ TOV_C_Source_RHS(TOV_r_1d[i]+ 0.5 * TOV_dr[star],
+ TOV_K[star], TOV_Gamma[star],
+ in_data, source_data);
+ k2[0] = TOV_dr[star] * source_data[0];
+ k2[1] = TOV_dr[star] * source_data[1];
+ k2[2] = TOV_dr[star] * source_data[2];
+ k2[3] = TOV_dr[star] * source_data[3];
+ in_data[0] = old_data[0] + 0.5 * k2[0];
+ in_data[1] = old_data[1] + 0.5 * k2[1];
+ in_data[2] = old_data[2] + 0.5 * k2[2];
+ in_data[3] = old_data[3] + 0.5 * k2[3];
+
+ TOV_C_Source_RHS(TOV_r_1d[i]+ 0.5 * TOV_dr[star],
+ TOV_K[star], TOV_Gamma[star],
+ in_data, source_data);
+ k3[0] = TOV_dr[star] * source_data[0];
+ k3[1] = TOV_dr[star] * source_data[1];
+ k3[2] = TOV_dr[star] * source_data[2];
+ k3[3] = TOV_dr[star] * source_data[3];
+ in_data[0] = old_data[0] + k3[0];
+ in_data[1] = old_data[1] + k3[1];
+ in_data[2] = old_data[2] + k3[2];
+ in_data[3] = old_data[3] + k3[3];
+
+ TOV_C_Source_RHS(TOV_r_1d[i]+ TOV_dr[star],
+ TOV_K[star], TOV_Gamma[star],
+ in_data, source_data);
+ k4[0] = TOV_dr[star] * source_data[0];
+ k4[1] = TOV_dr[star] * source_data[1];
+ k4[2] = TOV_dr[star] * source_data[2];
+ k4[3] = TOV_dr[star] * source_data[3];
+
+ new_data[0] = old_data[0] + (k1[0] + k4[0] + 2.0 * (k2[0] + k3[0])) /6.0;
+ new_data[1] = old_data[1] + (k1[1] + k4[1] + 2.0 * (k2[1] + k3[1])) /6.0;
+ new_data[2] = old_data[2] + (k1[2] + k4[2] + 2.0 * (k2[2] + k3[2])) /6.0;
+ new_data[3] = old_data[3] + (k1[3] + k4[3] + 2.0 * (k2[3] + k3[3])) /6.0;
+
+ TOV_press_1d[i+1] = new_data[0];
+ TOV_m_1d [i+1] = new_data[1];
+ TOV_phi_1d [i+1] = new_data[2];
+ TOV_rbar_1d [i+1] = TOV_r_1d[i+1] * exp(new_data[3]);
+
+ /* otherwise the code crashes later */
+ if (TOV_press_1d[i+1] < 0.0)
+ TOV_press_1d[i+1] = 0.0;
+
+ local_rho = pow(TOV_press_1d[i+1] / TOV_K[star], 1.0 / TOV_Gamma[star]);
+
+ /* scan for the surface */
+ /* if ( (local_rho <= TOV_Atmosphere[star]) ||*/
+ if ( (local_rho <= 0.0) ||
+ (TOV_press_1d[i+1] <= 0.0) )
+ {
+ TOV_Surface[star] = TOV_r_1d[i];
+ TOV_R_Surface[star] = TOV_rbar_1d[i];
+ TOV_Surface_Index = i;
+ }
+ }
+ if (TOV_Surface[star] < 0.0)
+ CCTK_WARN(0, "Did not integrate out to surface of the star! "
+ "Increase TOV_dr or TOV_Num_Radial and rerun");
+
+ Surface_Mass = TOV_m_1d[TOV_Surface_Index];
+ factor = 0.5 * (sqrt(TOV_Surface[star] *
+ (TOV_Surface[star] - 2.00 * Surface_Mass)) +
+ TOV_Surface[star] - Surface_Mass) /
+ TOV_rbar_1d[TOV_Surface_Index];
+
+ TOV_R_Surface[star] *= factor;
+ for (i=star_i; i < star_i+TOV_Num_Radial; i++)
+ {
+ TOV_rbar_1d[i] *= factor;
+ TOV_phi_1d[i] -= TOV_phi_1d[TOV_Surface_Index] -
+ 0.5 * log(1.0 - 2.0 * Surface_Mass / TOV_Surface[star]);
+ /* match to Schwarzschield */
+ if (i > TOV_Surface_Index)
+ {
+ TOV_press_1d[i] = TOV_K[star] * pow(TOV_Atmosphere[star],
+ TOV_Gamma[star]);
+ TOV_rbar_1d [i] = 0.5 *
+ (sqrt(TOV_r_1d[i]*(TOV_r_1d[i] - 2.0*Surface_Mass)) +
+ TOV_r_1d[i] - Surface_Mass);
+ TOV_m_1d[i] = Surface_Mass;
+ TOV_phi_1d[i] = 0.5 * log( 1.0 - 2.0 * Surface_Mass / TOV_r_1d[i]);
+ }
+ }
+ }
+ CCTK_INFO("Integrated TOV equation");
+ /* do some info */
+ CCTK_VInfo(CCTK_THORNSTRING, "Information about the TOVs used:");
+ CCTK_VInfo("", "TOV radius mass mass(g) cent.rho rho(cgi) K K(cgi) Gamma");
+ for (i=0; i<TOV_Num_TOVs; i++)
+ if (TOV_Gamma[i]==2.0)
+ CCTK_VInfo(""," %d %8g %8g %8.3g %8g %8.3g %8g %8.3g %8g",
+ i+1, TOV_R_Surface[i],
+ TOV_m_1d[(i+1)*TOV_Num_Radial-1],
+ TOV_m_1d[(i+1)*TOV_Num_Radial-1]*CONSTANT_Msolar_cgi,
+ TOV_Rho_Central[i],
+ TOV_Rho_Central[i]/pow(CONSTANT_G_cgi,3.0)/
+ pow(CONSTANT_Msolar_cgi,2.0)*
+ pow(CONSTANT_c_cgi,6.0),
+ TOV_K[i],
+ TOV_K[i]*pow(CONSTANT_G_cgi,3.0)*
+ pow(CONSTANT_Msolar_cgi,2.0)/
+ pow(CONSTANT_c_cgi,4.0),
+ TOV_Gamma[i]);
+ else
+ CCTK_VInfo(""," %d %8g %8g %8.3g %8g %8.3g %8g %8g",
+ i+1, TOV_R_Surface[i],
+ TOV_m_1d[(i+1)*TOV_Num_Radial-1],
+ TOV_m_1d[(i+1)*TOV_Num_Radial-1]*CONSTANT_Msolar_cgi,
+ TOV_Rho_Central[i],
+ TOV_Rho_Central[i]/pow(CONSTANT_G_cgi,3.0)/
+ pow(CONSTANT_Msolar_cgi,2.0)*
+ pow(CONSTANT_c_cgi,6.0),
+ TOV_K[i], TOV_Gamma[i]);
+
+}
+
+/*----------------------------------------------------------------------------*/
+
+/* utility routine
+ * recursive search-routine for arrays
+ * here used to look for the last index in an ordered array with its
+ * value < goal
+ */
+CCTK_INT TOV_C_find_index(CCTK_INT array_size,
+ CCTK_REAL *array,
+ CCTK_REAL goal,
+ CCTK_INT lower_index,
+ CCTK_INT upper_index)
+{
+ CCTK_INT middle_index;
+
+ if (lower_index >= (upper_index-1))
+ return lower_index;
+
+ middle_index = (lower_index + upper_index) /2;
+
+ if (array[middle_index] < goal)
+ return TOV_C_find_index(array_size, array, goal, middle_index, upper_index);
+ else
+ return TOV_C_find_index(array_size, array, goal, lower_index, middle_index);
+}
+
+/* utility rountine
+ * interpolates from (thorn-internal) 1D-data to Cactus 3D-grid */
+/* input is all but *press_point *phi_point and *r_point */
+void TOV_C_interp_tov_isotropic(
+ CCTK_INT star,
+ CCTK_REAL *TOV_press_1d_local,
+ CCTK_REAL *TOV_phi_1d_local,
+ CCTK_REAL *TOV_rbar_1d_local,
+ CCTK_REAL *TOV_r_1d_local,
+ CCTK_REAL *r,
+ CCTK_REAL surface,
+ CCTK_REAL *press_point,
+ CCTK_REAL *phi_point,
+ CCTK_REAL *r_point,
+ CCTK_INT TOV_warn_small_grid,
+ CCTK_INT TOV_zero_atmosphere,
+ CCTK_REAL *TOV_Atmosphere)
+{
+ DECLARE_CCTK_PARAMETERS
+ CCTK_INT left_index;
+ CCTK_REAL h, M;
+
+ if (*r < 0.0)
+ CCTK_WARN(0, "Negative radius found");
+ if (*r < TOV_rbar_1d_local[1])
+ *r=TOV_rbar_1d_local[1];
+ if (*r > TOV_rbar_1d_local[TOV_Num_Radial-2])
+ {
+ if (TOV_warn_small_grid)
+ CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Grid not large enough - last point: %.20f.",
+ TOV_rbar_1d_local[TOV_Num_Radial-1]);
+ else
+ {
+ if (!TOV_zero_atmosphere)
+ *press_point= TOV_K[star] * pow(TOV_Atmosphere[star],
+ TOV_Gamma[star]);
+ else
+ *press_point=0.0;
+ M = 0.5 * TOV_r_1d_local[TOV_Num_Radial-1] *
+ (1.0 - exp(2.0*TOV_phi_1d_local[TOV_Num_Radial-1]));
+ *r_point=(2* *r+M)*(2* *r+M)*0.25/ *r;
+ *phi_point=0.5*log(1-2*M/ *r_point);
+ return;
+ }
+ }
+
+ if (TOV_Fast_Interpolation)
+ left_index = TOV_C_find_index(TOV_Num_Radial-1, TOV_rbar_1d_local, *r, 0,
+ TOV_Num_Radial-1);
+ else
+ {
+ left_index=0;
+ while( (left_index < TOV_Num_Radial-2) &&
+ (TOV_rbar_1d_local[left_index+1] < *r) )
+ left_index++;
+ }
+
+ h = (*r - TOV_rbar_1d_local[left_index]) /
+ (TOV_rbar_1d_local[left_index+1] - TOV_rbar_1d_local[left_index]);
+ *r_point = (1.0 - h) * TOV_r_1d_local[left_index] +
+ h * TOV_r_1d_local[left_index+1];
+ *phi_point = (1.0 - h) * TOV_phi_1d_local[left_index] +
+ h * TOV_phi_1d_local[left_index+1];
+ if (!TOV_zero_atmosphere ||
+ (*r_point < surface))
+ *press_point = (1.0 - h) * TOV_press_1d_local[left_index] +
+ h * TOV_press_1d_local[left_index+1];
+ else
+ *press_point = 0.0;
+}
+
+/*@@
+ @routine TOV_Exact
+ @date Thu Oct 24 14:30:00 2002
+ @author Frank Loeffler, converted fortran routine by Ian Hawke
+ @desc
+ Schedule routine for interpolation of 1D to 3D grid
+ @enddesc
+ @calls
+ @calledby
+ @history
+ @endhistory
+@@*/
+void TOV_C_Exact(CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL *press_point, *rho_point, *eps_point,
+ *mu_point, *phi_point, *r_point;
+
+ CCTK_INT LSH_MAX_I;
+
+ CCTK_INT i,j,k, i3D, star, star_i;
+ CCTK_REAL *r_to_star;
+ CCTK_REAL g_diag, max_g_diag, max_rho, det, sqrt_det;
+ CCTK_REAL my_velx, my_vely, my_velz, my_psi4;
+ CCTK_REAL vlowx, vlowy, vlowz;
+ CCTK_REAL D_h_w, PI, local_tiny;
+
+ CCTK_INT tov_lapse;
+
+ tov_lapse = CCTK_EQUALS(initial_lapse, "tov");
+
+ PI=4.0*atan(1.0);
+ local_tiny=1.0e-14;
+ /* remember index of last member of array */
+ LSH_MAX_I = CCTK_GFINDEX3D(cctkGH,
+ cctk_lsh[0]-1, cctk_lsh[1]-1, cctk_lsh[2]-1);
+
+ assert(TOV_Surface!=0);
+ assert(TOV_R_Surface!=0);
+ assert(TOV_Atmosphere!=0);
+
+ assert(TOV_r_1d!=0);
+ assert(TOV_rbar_1d!=0);
+ assert(TOV_press_1d!=0);
+ assert(TOV_phi_1d!=0);
+ assert(TOV_m_1d!=0);
+
+ /* allocate local arrays */
+ r_to_star = (CCTK_REAL *) calloc (TOV_Num_TOVs, sizeof(CCTK_REAL));
+ press_point = (CCTK_REAL *) calloc (TOV_Num_TOVs, sizeof(CCTK_REAL));
+ rho_point = (CCTK_REAL *) calloc (TOV_Num_TOVs, sizeof(CCTK_REAL));
+ eps_point = (CCTK_REAL *) calloc (TOV_Num_TOVs, sizeof(CCTK_REAL));
+ mu_point = (CCTK_REAL *) calloc (TOV_Num_TOVs, sizeof(CCTK_REAL));
+ phi_point = (CCTK_REAL *) calloc (TOV_Num_TOVs, sizeof(CCTK_REAL));
+ r_point = (CCTK_REAL *) calloc (TOV_Num_TOVs, sizeof(CCTK_REAL));
+
+ /* clear initial data */
+ if (TOV_Clear_Initial_Data > 0 && !(TOV_Use_Old_Initial_Data))
+ {
+ TOV_C_fill(kxx, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(kxy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(kxz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(kyy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(kyz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(kzz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(gxx, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(gyy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(gzz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(gxy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(gxz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(gyz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(alp, LSH_MAX_I+1, 1.0);
+
+ if (*shift_state != 0)
+ {
+ TOV_C_fill(betax, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(betay, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(betaz, LSH_MAX_I+1, 0.0);
+ }
+
+ if (*conformal_state != 0)
+ {
+ TOV_C_fill(psi, LSH_MAX_I+1, 1.0);
+ if (*conformal_state > 1)
+ {
+ TOV_C_fill(psix, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(psiy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(psiz, LSH_MAX_I+1, 0.0);
+ if (*conformal_state > 2)
+ {
+ TOV_C_fill(psixx, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(psixy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(psixz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(psiyy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(psiyz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(psizz, LSH_MAX_I+1, 0.0);
+ }
+ }
+ }
+
+ if (!TOV_Use_Old_Matter_Initial_Data)
+ {
+ TOV_C_fill(rho, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(dens, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(eps, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(press, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(tau, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(w_lorentz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(sx, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(sy, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(sz, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(velx, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(vely, LSH_MAX_I+1, 0.0);
+ TOV_C_fill(velz, LSH_MAX_I+1, 0.0);
+ }
+ }
+ /* use the fast interpolation? only useful for testing this */
+ if (TOV_Fast_Interpolation == 0)
+ CCTK_INFO("Interpolating the slow way.");
+
+ /* go over all 3D-grid points */
+ for(i=0; i<cctk_lsh[0]; i++)
+ for(j=0; j<cctk_lsh[1]; j++)
+ for(k=0; k<cctk_lsh[2]; k++)
+ {
+ i3D=CCTK_GFINDEX3D(cctkGH, i, j, k);
+ /* remember the old conformal factor to the power of 4 */
+ if (*conformal_state != 0)
+ my_psi4=pow(psi[i3D], 4.0);
+ else
+ my_psi4=1.0;
+
+ for (star=0; star<TOV_Num_TOVs; star++)
+ {
+ r_to_star[star] =
+ sqrt( (x[i3D]-TOV_Position_x[star]) *
+ (x[i3D]-TOV_Position_x[star]) +
+ (y[i3D]-TOV_Position_y[star]) *
+ (y[i3D]-TOV_Position_y[star]) +
+ (z[i3D]-TOV_Position_z[star]) *
+ (z[i3D]-TOV_Position_z[star]) );
+ star_i = star * TOV_Num_Radial;
+
+ /* do the actual interpolation */
+ TOV_C_interp_tov_isotropic(star,
+ &(TOV_press_1d[star_i]), &(TOV_phi_1d[star_i]),
+ &(TOV_rbar_1d[star_i]), &(TOV_r_1d[star_i]),
+ &(r_to_star[star]), TOV_Surface[star],
+ &(press_point[star]),
+ &(phi_point[star]), &(r_point[star]),
+ 0, 0, TOV_Atmosphere);
+
+ /* is some perturbation wanted? */
+ if (Perturb[star] == 0)
+ rho_point[star] = pow(press_point[star]/TOV_K[star],
+ 1.0/TOV_Gamma[star]);
+ else
+ rho_point[star] = pow(press_point[star]/TOV_K[star],
+ 1.0/TOV_Gamma[star]) *
+ (1.0 +
+ Pert_Amplitude[star] *
+ cos(PI/2.0 * r[i3D] / TOV_R_Surface[star]));
+
+ eps_point[star] = press_point[star] / (TOV_Gamma[star] - 1.0)
+ / rho_point[star];
+ mu_point[star] = rho_point[star] * (1.0 + eps_point[star]);
+ }
+ /* find out from which star we want to have the data */
+ if (CCTK_EQUALS(TOV_Combine_Method, "maximum"))
+ {
+ /* to do this, we use here simply the max of the gxx-value */
+ star=0;
+ max_g_diag = 0.0;
+ max_rho = rho_point[0];
+ for (star_i=0; star_i<TOV_Num_TOVs; star_i++)
+ {
+ g_diag = (r_point[star_i] / (r_to_star[star_i] + 1.0e-30)) *
+ (r_point[star_i] / (r_to_star[star_i] + 1.0e-30));
+ if ((g_diag - max_g_diag) > local_tiny)
+ {
+ max_g_diag=g_diag;
+ star=star_i;
+ }
+ if ((rho_point[star_i] - max_rho) > local_tiny)
+ {
+ max_rho=rho_point[star_i];
+ star=star_i;
+ }
+ }
+ /* handle initial data */
+ if (TOV_Use_Old_Initial_Data)
+ {
+ /* check metric */
+ if ((my_psi4 * gxx[i3D] < max_g_diag) &&
+ (my_psi4 * gyy[i3D] < max_g_diag) &&
+ (my_psi4 * gzz[i3D] < max_g_diag))
+ {
+ if (TOV_Conformal_Flat_Three_Metric)
+ {
+ psi[i3D] = pow(max_g_diag, 0.25);
+ my_psi4 = max_g_diag;
+ }
+ else
+ {
+ gxx[i3D] = max_g_diag/my_psi4;
+ gyy[i3D] = max_g_diag/my_psi4;
+ gzz[i3D] = max_g_diag/my_psi4;
+ }
+ }
+ /* check matter */
+ if (TOV_Use_Old_Matter_Initial_Data)
+ {
+ if (rho[i3D] > max_rho)
+ {
+ /* we do not need this array element anymore, since we use
+ * the initial data, so lets use it */
+ star=0;
+ max_rho =rho[i3D];
+ eps_point[star] =eps[i3D];
+ press_point[star]=press[i3D];
+ my_velx=velx[i3D];
+ my_vely=vely[i3D];
+ my_velz=velz[i3D];
+ }
+ else
+ {
+ if (tov_lapse)
+ alp[i3D] = exp(phi_point[star]);
+ my_velx=TOV_Velocity_x[star];
+ my_vely=TOV_Velocity_y[star];
+ my_velz=TOV_Velocity_z[star];
+ }
+ }
+ else
+ {
+ if (tov_lapse)
+ alp[i3D] = exp(phi_point[star]);
+ my_velx=TOV_Velocity_x[star];
+ my_vely=TOV_Velocity_y[star];
+ my_velz=TOV_Velocity_z[star];
+ }
+ }
+ else /* do not use old initial data */
+ {
+ /* no psi, since it is 1.0 here */
+ /* but maybe we want to have it != 1.0 */
+ if (TOV_Conformal_Flat_Three_Metric)
+ {
+ psi[i3D] = pow(max_g_diag, 0.25);
+ my_psi4 = max_g_diag;
+ gxx[i3D] = gyy[i3D] = gzz[i3D] = 1.0;
+ }
+ else
+ {
+ gxx[i3D] = max_g_diag;
+ gyy[i3D] = max_g_diag;
+ gzz[i3D] = max_g_diag;
+ }
+ if (tov_lapse)
+ alp[i3D] = exp(phi_point[star]);
+ my_velx=TOV_Velocity_x[star];
+ my_vely=TOV_Velocity_y[star];
+ my_velz=TOV_Velocity_z[star];
+ }
+
+ /* set to defined velocity. default is 0.0 because other velocities
+ * violate Einsteins equations */
+ velx[i3D] = my_velx;
+ vely[i3D] = my_vely;
+ velz[i3D] = my_velz;
+
+ w_lorentz[i3D] = 1/sqrt(1.0-(
+ gxx[i3D] * velx[i3D] * velx[i3D]+
+ gyy[i3D] * vely[i3D] * vely[i3D]+
+ gzz[i3D] * velz[i3D] * velz[i3D]+
+ 2*gxy[i3D] * velx[i3D] * vely[i3D]+
+ 2*gxz[i3D] * velx[i3D] * velz[i3D]+
+ 2*gyz[i3D] * vely[i3D] * velz[i3D])*
+ my_psi4);
+
+ rho[i3D] = max_rho;
+ eps[i3D] = eps_point[star];
+ press[i3D] = press_point[star];
+
+ }
+ else if (CCTK_EQUALS(TOV_Combine_Method, "average"))
+ {
+ /* here we 'average' all values in a more intelligent way */
+ if (TOV_Use_Old_Matter_Initial_Data)
+ max_rho=rho[i3D];
+ else
+ {
+ max_rho=0.0;
+ rho[i3D] = 0.0;
+ }
+ star=-1;
+ for (star_i=0; star_i<TOV_Num_TOVs; star_i++)
+ {
+ if (tov_lapse)
+ alp[i3D] *= exp(phi_point[star_i]);
+ if (TOV_Conformal_Flat_Three_Metric)
+ {
+ /* This is a hack, since it does not check, if the input data is
+ * really conformally flat. It simply assumes this by only using
+ * gxx */
+ my_psi4 = (r_point[star_i] * r_point[star_i] /
+ (r_to_star[star_i] * r_to_star[star_i] + 1.0e-30)) /
+ my_psi4 + pow(psi[i3D], 4.0) * gxx[i3D];
+ psi[i3D] = pow(my_psi4, 0.25);
+ if (!TOV_Use_Old_Initial_Data)
+ gxx[i3D] = gyy[i3D] = gzz[i3D] = 1.0;
+ }
+ else
+ gxx[i3D] += (r_point[star_i] * r_point[star_i] /
+ (r_to_star[star_i] * r_to_star[star_i] + 1.0e-30)) /
+ my_psi4;
+ rho[i3D] += rho_point[star_i];
+ eps[i3D] += eps_point[star_i];
+ press[i3D] += press_point[star_i];
+ /* we still have to know if we are inside one star - and which */
+ if ( (rho_point[star_i] > max_rho) &&
+ (rho_point[star_i] > TOV_Atmosphere[star_i]))
+ {
+ max_rho=rho_point[star_i];
+ star=star_i;
+ }
+
+ if(rho[i3D] <= TOV_Atmosphere[star_i])
+ rho[i3D] = TOV_Atmosphere[star_i];
+
+ }
+
+ if (TOV_Conformal_Flat_Three_Metric)
+ {
+ my_psi4 -= ((TOV_Num_TOVs+TOV_Use_Old_Initial_Data-1)/my_psi4);
+ psi[i3D] = pow(my_psi4, 0.25);
+ }
+ else
+ {
+ gxx[i3D] -= ((TOV_Num_TOVs+TOV_Use_Old_Initial_Data-1)/my_psi4);
+ gyy[i3D] = gxx[i3D];
+ gzz[i3D] = gxx[i3D];
+ }
+
+ /* set to defined velocity. default is 0.0 because other velocities
+ * violate the constraints */
+ if (star > -1)
+ {
+ velx[i3D] = TOV_Velocity_x[star];
+ vely[i3D] = TOV_Velocity_y[star];
+ velz[i3D] = TOV_Velocity_z[star];
+ }
+
+ w_lorentz[i3D] = 1/sqrt(1.0-(
+ gxx[i3D] * velx[i3D] * velx[i3D]+
+ gyy[i3D] * vely[i3D] * vely[i3D]+
+ gzz[i3D] * velz[i3D] * velz[i3D]+
+ 2*gxy[i3D] * velx[i3D] * vely[i3D]+
+ 2*gxz[i3D] * velx[i3D] * velz[i3D]+
+ 2*gyz[i3D] * vely[i3D] * velz[i3D]) * my_psi4);
+ }
+ /* now all combine methods are doing the same */
+ if ((TOV_Num_TOVs==1) && (rho[i3D] < TOV_Atmosphere[0]))
+ velx[i3D] = vely[i3D] = velz[i3D] = 0.0;
+
+ SpatialDet(gxx[i3D],gxy[i3D],gxz[i3D],gyy[i3D],gyz[i3D],gzz[i3D],&det);
+
+ sqrt_det=sqrt(det) * pow(my_psi4, 1.5);
+ dens[i3D] = sqrt_det * w_lorentz[i3D] * rho[i3D];
+
+ /* this variable is only for temporal storage */
+ D_h_w = dens[i3D] * (1 + eps[i3D] + press[i3D]/rho[i3D]) * w_lorentz[i3D];
+
+ vlowx = gxx[i3D]*velx[i3D] + gxy[i3D]*vely[i3D] + gxz[i3D]*velz[i3D];
+ vlowy = gxy[i3D]*velx[i3D] + gyy[i3D]*vely[i3D] + gyz[i3D]*velz[i3D];
+ vlowz = gxz[i3D]*velx[i3D] + gyz[i3D]*vely[i3D] + gzz[i3D]*velz[i3D];
+
+ sx[i3D] = D_h_w * vlowx;
+ sy[i3D] = D_h_w * vlowy;
+ sz[i3D] = D_h_w * vlowz;
+
+ /* One could use D_h_w here, but it would introduce more error */
+ tau[i3D] = sqrt_det * (rho[i3D] *w_lorentz[i3D]*w_lorentz[i3D] *
+ (1.0 + eps[i3D]) +
+ press[i3D]*(w_lorentz[i3D]*w_lorentz[i3D]-1.0) ) -
+ dens[i3D];
+ }
+ /* if used, recalculate the derivatives of the conformal factor */
+ if (*conformal_state > 1)
+ /* go again over all 3D-grid points */
+ for(i=0; i<cctk_lsh[0]; i++)
+ for(j=0; j<cctk_lsh[1]; j++)
+ for(k=0; k<cctk_lsh[2]; k++)
+ {
+ i3D=CCTK_GFINDEX3D(cctkGH, i, j, k);
+ psix[i3D]=(((i==0)?
+ (psi[CCTK_GFINDEX3D(cctkGH, i+1, j, k)] -
+ psi[CCTK_GFINDEX3D(cctkGH, i , j, k)]):
+ (i==(cctk_lsh[0]-1))?
+ (psi[CCTK_GFINDEX3D(cctkGH, i , j, k)] -
+ psi[CCTK_GFINDEX3D(cctkGH, i-1, j, k)]):
+ 0.5*(psi[CCTK_GFINDEX3D(cctkGH, i+1, j, k)] -
+ psi[CCTK_GFINDEX3D(cctkGH, i-1, j, k)])));
+ psix[i3D] = DIFF_X(psi);
+ psiy[i3D] = DIFF_Y(psi);
+ psiz[i3D] = DIFF_Z(psi);
+ }
+ if (*conformal_state > 2)
+ /* go again over all 3D-grid points */
+ for(i=0; i<cctk_lsh[0]; i++)
+ for(j=0; j<cctk_lsh[1]; j++)
+ for(k=0; k<cctk_lsh[2]; k++)
+ {
+ i3D=CCTK_GFINDEX3D(cctkGH, i, j, k);
+ psixx[i3D] = DIFF_X(psix)/psi[i3D];
+ psiyy[i3D] = DIFF_Y(psiy)/psi[i3D];
+ psizz[i3D] = DIFF_Z(psiz)/psi[i3D];
+ psixy[i3D] = DIFF_X(psiy)/psi[i3D];
+ psiyz[i3D] = DIFF_Y(psiz)/psi[i3D];
+ psixz[i3D] = DIFF_Z(psix)/psi[i3D];
+ }
+ if (*conformal_state > 1)
+ /* go again over all 3D-grid points */
+ for(i=0; i<cctk_lsh[0]; i++)
+ for(j=0; j<cctk_lsh[1]; j++)
+ for(k=0; k<cctk_lsh[2]; k++)
+ {
+ i3D=CCTK_GFINDEX3D(cctkGH, i, j, k);
+ psix[i3D] /= psi[i3D];
+ psiy[i3D] /= psi[i3D];
+ psiz[i3D] /= psi[i3D];
+ }
+ i3D = cctk_lsh[2]*cctk_lsh[1]*cctk_lsh[0];
+ switch(TOV_Populate_Timelevels)
+ {
+ case 3:
+ TOV_Copy(i3D, gxx_p_p, gxx);
+ TOV_Copy(i3D, gyy_p_p, gyy);
+ TOV_Copy(i3D, gzz_p_p, gzz);
+ TOV_Copy(i3D, rho_p_p, rho);
+ TOV_Copy(i3D, eps_p_p, eps);
+ TOV_Copy(i3D, velx_p_p, velx);
+ TOV_Copy(i3D, vely_p_p, vely);
+ TOV_Copy(i3D, velz_p_p, velz);
+ TOV_Copy(i3D, dens_p_p, dens);
+ TOV_Copy(i3D, tau_p_p, tau);
+ TOV_Copy(i3D, sx_p_p, sx);
+ TOV_Copy(i3D, sy_p_p, sy);
+ TOV_Copy(i3D, sz_p_p, sz);
+ TOV_Copy(i3D, w_lorentz_p_p, w_lorentz);
+ case 2:
+ TOV_Copy(i3D, gxx_p, gxx);
+ TOV_Copy(i3D, gyy_p, gyy);
+ TOV_Copy(i3D, gzz_p, gzz);
+ TOV_Copy(i3D, rho_p, rho);
+ TOV_Copy(i3D, eps_p, eps);
+ TOV_Copy(i3D, velx_p, velx);
+ TOV_Copy(i3D, vely_p, vely);
+ TOV_Copy(i3D, velz_p, velz);
+ TOV_Copy(i3D, dens_p, dens);
+ TOV_Copy(i3D, tau_p, tau);
+ TOV_Copy(i3D, sx_p, sx);
+ TOV_Copy(i3D, sy_p, sy);
+ TOV_Copy(i3D, sz_p, sz);
+ TOV_Copy(i3D, w_lorentz_p, w_lorentz);
+ }
+ CCTK_INFO("Done interpolation.");
+
+ /* free local arrays */
+ free(r_to_star);
+ free(press_point);
+ free(rho_point);
+ free(eps_point);
+ free(mu_point);
+ free(phi_point);
+ free(r_point);
+}
+
+void TOV_Prepare_Fake_Evolution(CCTK_ARGUMENTS)
+{
+ if (CCTK_ParameterSet("TOV_Populate_Timelevels",
+ "Whisky_TOVSolverC",
+ "1"))
+ CCTK_WARN(0,
+ "Could not prepare for fake evolution - steering failed\n");
+}
+
+#include "external.inc"