diff options
Diffstat (limited to 'src/GRHydro_Bondi.c')
-rw-r--r-- | src/GRHydro_Bondi.c | 1180 |
1 files changed, 1180 insertions, 0 deletions
diff --git a/src/GRHydro_Bondi.c b/src/GRHydro_Bondi.c new file mode 100644 index 0000000..eb98ee4 --- /dev/null +++ b/src/GRHydro_Bondi.c @@ -0,0 +1,1180 @@ + /*@@ + @file GRHydro_Bondi.c + @date Wed Jan 13 13:00:49 EST 2010 + @author Scott C. Noble + @desc + Hydro initial data for the relativistic Bondi solution about + a single Schwarzschild black hole. + @enddesc + @@*/ + +/***********************************************************************************/ +/***********************************************************************************/ +/*********************************************************************************** + Calculates the Bondi solution, or the spherically symmetric hydrostationary + solution to a fluid on a static fixed background spacetime. We assume that one can + calculate a radius "r" from the grid and that with respect to this radial coordinate, + the solution satisfies + + d (\rho u^r) / dr = 0 + + Assumes that the equation of state is P = K \rho^\Gamma and K is set by + the location of the sonic point. + + + -- Implicitly assumes that there is no spin in the geometry as there is no Bondi + solution for spinning black holes. If a spin is specified, a spherically symmetric + is still assumed but the 4-velocity is set consistently with the spinning spacetime. + +***********************************************************************************/ +/***********************************************************************************/ +/***********************************************************************************/ + + +#include "cctk.h" +#include "cctk_Arguments.h" +#include "cctk_Parameters.h" +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +# define M_PI 3.14159265358979323846 /* pi */ + +// set to 1 to tracing output +#define LTRACE 1 + + +/* Mnemonics: */ + +#define NDIM (4) /* Number of spacetime dimensions */ + +/* mnemonics for dimensional indices */ +#define TT (0) +#define RR (1) +#define TH (2) +#define PH (3) + +/* mnemonics for dimensional indices */ +#define XX (1) +#define YY (2) +#define ZZ (3) + +/* mnemonics for coordinate system choice */ +#define COORD_BOYERLINDQUIST (0) +#define COORD_KERRSCHILD (1) +#define COORD_ISOTROPIC (2) + +/* Macros: */ +#define DLOOP1 for(i=0 ;i<NDIM ;i++) +#define DLOOP2 for(i=0 ;i<NDIM ;i++) for(j=0 ;j<NDIM ;j++) + + +#if !defined(__INTEL_COMPILER) +# define LOCAL_SINCOS +# define sincos( theta_ , sth_ , cth_ ) { *(sth_) = sin((theta_)) ; *(cth_) = cos((theta_)) ; } +#endif + + +//Newton-Raphson parameters: +#define NEWT_DIM_B (1 ) +#define MAX_NEWT_ITER_B (30 ) /* Max. # of Newton-Raphson iterations for find_root_2D(); */ +#define NEWT_TOL_B (1.0e-15) /* Min. of tolerance allowed for Newton-Raphson iterations */ +#define MIN_NEWT_TOL_B (1.0e-10) /* Max. of tolerance allowed for Newton-Raphson iterations */ +#define EXTRA_NEWT_ITER_B (2 ) +#define SMALL_BONDI (1.e-20) + + +static CCTK_REAL Mdot, rs, vs_sq, vs, cs_sq, cs, rhos, hs, K, Qdot, gamma_eos, r_sol; +static CCTK_REAL M, a, asq, Msq; +static CCTK_REAL x_cen, y_cen, z_cen; +static unsigned short int coord_type; + + +/****************************************************************************** + bl_to_ks_con(): + ---------- + -- transforms a contravariant vector in BL coordinates to KS coordinates; + ******************************************************************************/ +static void bl_to_ks_con(CCTK_REAL *x, CCTK_REAL blcon[], CCTK_REAL kscon[] ) +{ + CCTK_REAL delta_m1, dtKS_drBL, dphiKS_drBL; + + delta_m1 = 1./( x[RR] * ( x[RR] - 2*M ) + asq ); + dtKS_drBL = 2*M*x[RR] * delta_m1; + dphiKS_drBL = a * delta_m1; + + kscon[TT] = blcon[TT] + blcon[RR] * dtKS_drBL; + kscon[RR] = blcon[RR]; + kscon[TH] = blcon[TH]; + kscon[PH] = blcon[PH] + blcon[RR] * dphiKS_drBL; + + return; +} + +/****************************************************************************** + dxc_dxs_ks_calc(): + ---------------------- + -- calculates the transformation matrix Lambda^\hat{a}_a defined: + + x^\hat{a}[Cartesian] = \Lambda^\hat{a}_a x^a[Spherical] + + where dxc_dxs[i][j] = \Lambda^i_j + + for Kerr-Schild coordinates. + + ******************************************************************************/ +static void dxc_dxs_ks_calc(CCTK_REAL *x_cart, CCTK_REAL *x_spher, CCTK_REAL dxc_dxs[][NDIM] ) +{ + int i; + CCTK_REAL r, th, ph; + CCTK_REAL sth,cth,sph,cph; + + for( i = 0 ; i < NDIM*NDIM ; i++ ) { dxc_dxs[0][i] = 0. ; } + + r = x_spher[RR]; + th = x_spher[TH]; + ph = x_spher[PH]; + + sincos( th, &sth , &cth ); + sincos( ph, &sph , &cph ); + + dxc_dxs[TT][TT] = 1. ; // dt/dt + dxc_dxs[XX][RR] = cph * sth ; // dx/dr + dxc_dxs[XX][TH] = (r*cph - a*sph) * cth ; // dx/dtheta + dxc_dxs[XX][PH] = -(x_cart[YY] - y_cen) ; // dx/dphi + dxc_dxs[YY][RR] = sph * sth ; // dy/dr + dxc_dxs[YY][TH] = (r*sph + a*cph) * cth ; // dy/dtheta + dxc_dxs[YY][PH] = x_cart[XX] - x_cen ; // dy/dphi + dxc_dxs[ZZ][RR] = cth ; // dz/dr + dxc_dxs[ZZ][TH] = -r*sth ; // dz/dtheta + // dxc_dxs[ZZ][PH] = 0. ; // dz/dphi + + return; + +} + +/****************************************************************************** + dxc_dxs_bl_calc(): + ---------------------- + -- calculates the transformation matrix Lambda^\hat{a}_a defined: + + x^\hat{a}[Cartesian] = \Lambda^\hat{a}_a x^a[Spherical] + + where dxc_dxs[i][j] = \Lambda^i_j + + for Boyer-Lindquist coordinates. + + ******************************************************************************/ +static void dxc_dxs_bl_calc(CCTK_REAL *x_cart, CCTK_REAL *x_spher, CCTK_REAL dxc_dxs[][NDIM] ) +{ + int i; + CCTK_REAL r, th, ph, rterm, dr; + CCTK_REAL sth,cth,sph,cph; + + for( i = 0 ; i < NDIM*NDIM ; i++ ) { dxc_dxs[0][i] = 0. ; } + + r = x_spher[RR]; + th = x_spher[TH]; + ph = x_spher[PH]; + + sincos( th, &sth , &cth ); + sincos( ph, &sph , &cph ); + + rterm = sqrt( r*r + asq ); + dr = r / rterm; + + dxc_dxs[TT][TT] = 1. ; // dt/dt + dxc_dxs[XX][RR] = cph * sth * dr ; // dx/dr + dxc_dxs[XX][TH] = rterm * cph * cth ; // dx/dtheta + dxc_dxs[XX][PH] = -(x_cart[YY] - y_cen) ; // dx/dphi + dxc_dxs[YY][RR] = sph * sth * dr ; // dy/dr + dxc_dxs[YY][TH] = rterm * sph * cth ; // dy/dtheta + dxc_dxs[YY][PH] = x_cart[XX] - x_cen ; // dy/dphi + dxc_dxs[ZZ][RR] = cth ; // dz/dr + dxc_dxs[ZZ][TH] = -r*sth ; // dz/dtheta + // dxc_dxs[ZZ][PH] = 0. ; // dz/dphi + + return; + +} + +/****************************************************************************** + dxc_dxs_iso_calc(): + ---------------------- + -- calculates the transformation matrix Lambda^\hat{a}_a defined: + + x^\hat{a}[Cartesian] = \Lambda^\hat{a}_a x^a[Spherical] + + where dxc_dxs[i][j] = \Lambda^i_j + + for "Isotropic" coordinates. + + ******************************************************************************/ +static void dxc_dxs_iso_calc(CCTK_REAL *x_cart, CCTK_REAL *x_spher, CCTK_REAL dxc_dxs[][NDIM] ) +{ + int i; + CCTK_REAL th, ph,r_iso; + CCTK_REAL sth,cth,sph,cph; + + for( i = 0 ; i < NDIM*NDIM ; i++ ) { dxc_dxs[0][i] = 0. ; } + + /* BL spherical coordinates : */ + th = x_spher[TH]; + ph = x_spher[PH]; + + r_iso = x_spher[TT]; + + sincos( th, &sth , &cth ); + sincos( ph, &sph , &cph ); + + dxc_dxs[TT][TT] = 1. ; // dt/dt + dxc_dxs[XX][RR] = cph * sth ; // dx/dr + dxc_dxs[XX][TH] = r_iso * cph * cth ; // dx/dtheta + dxc_dxs[XX][PH] = -(x_cart[YY] - y_cen) ; // dx/dphi + dxc_dxs[YY][RR] = sph * sth ; // dy/dr + dxc_dxs[YY][TH] = r_iso * sph * cth ; // dy/dtheta + dxc_dxs[YY][PH] = x_cart[XX] - x_cen ; // dy/dphi + dxc_dxs[ZZ][RR] = cth ; // dz/dr + dxc_dxs[ZZ][TH] = -r_iso*sth ; // dz/dtheta + // dxc_dxs[ZZ][PH] = 0. ; // dz/dphi + + return; + +} + +/****************************************************************************** + ks_cart_to_ks_spher_pos(): + ---------- + -- transforms the position in Cartesian KS coordinates to Spherical KS coordinates; + ******************************************************************************/ +static void ks_cart_to_ks_spher_pos(CCTK_REAL *x_cart, CCTK_REAL *x_spher) +{ + CCTK_REAL xx,yy,zz,r,t3; + + xx = x_cart[XX] - x_cen; + yy = x_cart[YY] - y_cen; + zz = x_cart[ZZ] - z_cen; + + t3 = 0.5*(xx*xx + yy*yy + zz*zz - asq); + r = sqrt( t3 + sqrt( t3*t3 + asq*zz*zz ) ); + + x_spher[TT] = x_cart[TT]; + x_spher[RR] = r; + x_spher[TH] = acos(zz / r); + t3 = atan2( (yy*r - xx*a) , (xx*r + yy*a) ); + if( t3 < 0. ) { t3 += 2.*M_PI; } + x_spher[PH] = t3; + + return; +} + +/****************************************************************************** + bl_cart_to_bl_spher_pos(): + ---------- + -- transforms the position in Cartesian BL coordinates to Spherical BL coordinates; + ******************************************************************************/ +static void bl_cart_to_bl_spher_pos(CCTK_REAL *x_cart, CCTK_REAL *x_spher) +{ + CCTK_REAL xx,yy,zz,r,t3; + + xx = x_cart[XX] - x_cen; + yy = x_cart[YY] - y_cen; + zz = x_cart[ZZ] - z_cen; + + t3 = 0.5*(xx*xx + yy*yy + zz*zz - asq); + r = sqrt( t3 + sqrt( t3*t3 + asq*zz*zz ) ); + + x_spher[TT] = x_cart[TT]; + x_spher[RR] = r; + x_spher[TH] = acos(zz / r); + t3 = atan2( yy , xx ); + if( t3 < 0. ) { t3 += 2.*M_PI; } + x_spher[PH] = t3; + + return; +} + +/****************************************************************************** + iso_cart_to_bl_spher_pos(): + ---------- + -- transforms the position in Cartesian "Isotropic" coordinates to Spherical BL coordinates; + -- r^2 = x^2 + y^2 + z^2 in these coordinates, so they are slightly distorted from flatspace + ******************************************************************************/ +static void iso_cart_to_bl_spher_pos(CCTK_REAL *x_cart, CCTK_REAL *x_spher) +{ + CCTK_REAL xx,yy,zz,riso,r,t3; + + xx = x_cart[XX] - x_cen; + yy = x_cart[YY] - y_cen; + zz = x_cart[ZZ] - z_cen; + + riso = sqrt(xx*xx + yy*yy + zz*zz); + r = 0.25 * ( 2.*riso + M + a ) * ( 2.*riso + M - a ) / riso ; + + x_spher[TT] = riso; + x_spher[RR] = r; + x_spher[TH] = acos(zz / riso); + t3 = atan2( yy , xx ); + if( t3 < 0. ) { t3 += 2.*M_PI; } + x_spher[PH] = t3; + + return; +} + +/**************************************************************************** + setutcon(): + ------------ + -- find the contravariant time-component of a time-like vector + pointing forward in time; +****************************************************************************/ +static void setutcon(CCTK_REAL *vcon, CCTK_REAL gcov[][NDIM]) +{ + int i,j; + CCTK_REAL d,b,c; + + d=gcov[TT][TT]; + + b = gcov[TT][1]*vcon[1] + gcov[TT][2]*vcon[2] + gcov[TT][3]*vcon[3] ; + + c = gcov[1][1] * vcon[1] * vcon[1] + + gcov[2][2] * vcon[2] * vcon[2] + + gcov[3][3] * vcon[3] * vcon[3] + + 2.*( gcov[1][2] * vcon[1] * vcon[2] + + gcov[1][3] * vcon[1] * vcon[3] + + gcov[2][3] * vcon[2] * vcon[3] ); + + c += 1. ; /* vector is timelike */ + + vcon[0]=(-b-sqrt(b*b-d*c))/(d); /* sign for pointing forward in time */ + + return; +} + +/**************************************************************************** + bl_gcov_func(): + --------------- + -- Covariant Kerr metric in Boyer-Lindquist coordinates. +****************************************************************************/ +static void bl_gcov_func( CCTK_REAL *x, CCTK_REAL gcov[][NDIM]) +{ + int i,j,k ; + CCTK_REAL sth,cth,s2,r2,DD,mu ; + CCTK_REAL r,th; + + for( i = 0 ; i < NDIM*NDIM ; i++ ) { gcov[0][i] = 0. ; } + + r = x[RR]; + th = x[TH]; + sincos( th, &sth , &cth ); + + s2 = sth*sth ; + r2 = r*r ; + DD = 1. - 2.*M/r + asq/r2 ; + mu = 1. + asq*cth*cth/r2 ; + + gcov[TT][TT] = -(1. - 2.*M/(r*mu)) ; + gcov[TT][3] = -2.*M*a*s2/(r*mu) ; + gcov[3][TT] = gcov[TT][3] ; + gcov[1][1] = mu/DD ; + gcov[2][2] = r2*mu ; + gcov[3][3] = r2*s2*(1. + asq/r2 + 2.*M*asq*s2/(r2*r*mu)) ; + + return; +} + + +/*************************************************************************** + + set_bondi_parameters(): + --------------------- + -- finds the values of the hydro. quantities at the sonic point, which + serves as a reference point for the conservation equations given + in Shapiro and Teukolsky equations (G.21,G.22). + + -- The sonic point values are then used in find_bondi_solution() to determine + the hydro. quantities at an arbitrary radius; + + -- the "boundary conditions" that uniquely determine the Bondi solution + are the radius of the sonic point, "rs", and the mass accretion rate, + Mdot; + + -- the Bondi solution here in is the isentropic, spherically symmetric, + perfect fluid solution to Einstein's equations. That is, we only + assume an r-dependence, there's a in-going radial velocity only, + and the EOS are : P = (G-1)*rho and P = K rho^G + where K = const. and G is the adiabatic constant "gam". + +***************************************************************************/ +static void set_bondi_parameters( CCTK_REAL M_in, CCTK_REAL Mdot_in, CCTK_REAL rs_in, CCTK_REAL gam ) +{ + + CCTK_REAL my_pi, checkp; + CCTK_REAL gtemp; + + /* Set the solution-determining parameters: */ + M = M_in; + Mdot = Mdot_in; + Msq = M*M; + rs = rs_in; + gamma_eos = gam; + + + /* Calculate the hydro. quantities: */ + cs_sq = M / ( 2.*rs - 3.*M ) ; + + if( cs_sq > (gam - 1.) ) { + cs_sq = gam - 1.; + rs = 0.5 * M * ( 3. + 1./cs_sq ) ; + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"set_bondi_parameters(): bad value of rs, need to increase it !! \n"); + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"set_bondi_parameters(): Need to change rs !! \n"); + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"set_bondi_parameters(): rs[old] = %28.15e rs[new] = %28.16e \n\n",rs_in,rs); + } + + cs = sqrt(cs_sq); + vs_sq = M / ( 2. * rs ) ; + vs = sqrt(vs_sq); + rhos = Mdot / ( 4. * M_PI * vs * rs * rs ) ; + gtemp = gam - 1.; + hs = 1. / ( 1. - cs_sq / (gam - 1.) ); + K = hs * cs_sq * pow( rhos, (-gtemp) ) / gam ; + Qdot = hs * hs * ( 1. - 3. * vs_sq ) ; + gamma_eos = gam; + +#if( LTRACE ) + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\n#######################################################\n"); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"Bondi Solution Parameters1: \n"); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"------------------------- \n\n"); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"M = %28.20e Mdot = %28.20e rs = %28.20e \n",M,Mdot,rs); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"vs = %28.20e cs = %28.20e rhos = %28.20e \n",vs,cs,rhos); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"hs = %28.20e K = %28.20e Qdot = %28.20e \n",hs,K,Qdot); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"gam= %28.20e r_sol= %28.20e \n",gamma_eos, r_sol); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"rs = : %28.20e \n", rs) ; + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"urs = : %28.20e \n", vs) ; + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"rhos = : %28.20e \n", rhos) ; + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"K = : %28.20e \n", K) ; + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"#######################################################\n\n"); +#endif + + return; + +} + +/**********************************************************************/ +/************************************************************ + + gnr_bondi(): + ----------- + -- should be just like the routine general_newton_raphson() in utoprim*.c + except the "physicality" condition is different; + + -- performs Newton-Rapshon method on an arbitrary system + though tailored to calculate rho second Bondi Conservation eq. + by ensuring that rho > 0 (look near "METHOD specific:") + + -- inspired in part by Num. Rec.'s routine newt(); + + Arguements: + + -- x[] = set of independent variables to solve for; + -- n = number of independent variables and residuals; + -- funcd = name of function that calculates residuals, etc.; + +*****************************************************************/ +static int gnr_bondi( CCTK_REAL x[], int n, + void (*funcd) (CCTK_REAL [], CCTK_REAL [], CCTK_REAL [], + CCTK_REAL [][NEWT_DIM_B], CCTK_REAL *, + CCTK_REAL *, int) ) +{ + CCTK_REAL f, df, dx[NEWT_DIM_B], x_old[NEWT_DIM_B], resid[NEWT_DIM_B], + jac[NEWT_DIM_B][NEWT_DIM_B]; + CCTK_REAL errx, x_orig[NEWT_DIM_B]; + int n_iter, id, jd, i_extra, doing_extra; + + int keep_iterating, i_increase; + + + // Initialize various parameters and variables: + errx = 1. ; + df = f = 1.; + i_extra = doing_extra = 0; + for( id = 0; id < n ; id++) x_old[id] = x_orig[id] = x[id] ; + + n_iter = 0; + + + /* Start the Newton-Raphson iterations : */ + keep_iterating = 1; + while( keep_iterating ) { + + (*funcd) (x, dx, resid, jac, &f, &df, n); /* returns with new dx, f, df */ + + /* Save old values before calculating the new: */ + errx = 0.; + for( id = 0; id < n ; id++) { + x_old[id] = x[id] ; + } + + /* don't use line search : */ + for( id = 0; id < n ; id++) { + x[id] += dx[id] ; + } + + /****************************************/ + /* Calculate the convergence criterion */ + /****************************************/ + + /* For the new criterion, always look at relative error in indep. variable: */ + // METHOD specific: + errx = (x[0]==0.) ? fabs(dx[0]) : fabs(dx[0]/x[0]); + + + /****************************************/ + /* Make sure that the new x[] is physical : */ + /****************************************/ + x[0] = (x[0] == 0.) ? (SMALL_BONDI) : fabs(x[0]); + + + /*****************************************************************************/ + /* If we've reached the tolerance level, then just do a few extra iterations */ + /* before stopping */ + /*****************************************************************************/ + + if( (fabs(errx) <= NEWT_TOL_B) && (doing_extra == 0) && (EXTRA_NEWT_ITER_B > 0) ) { + doing_extra = 1; + } + + if( doing_extra == 1 ) i_extra++ ; + + if( ((fabs(errx) <= NEWT_TOL_B)&&(doing_extra == 0)) || + (i_extra > EXTRA_NEWT_ITER_B) || (n_iter >= (MAX_NEWT_ITER_B-1)) ) { + keep_iterating = 0; + } + + n_iter++; + + } // END of while(keep_iterating) + + + /* Check for bad untrapped divergences : */ + if( (finite(f)==0) || (finite(df)==0) ) { + return(2); + } + + + if( fabs(errx) > MIN_NEWT_TOL_B){ + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"newt: errx = %28.20e \n", errx); + return(1); + } + if( (fabs(errx) <= MIN_NEWT_TOL_B) && (fabs(errx) > NEWT_TOL_B) ){ + return(0); + } + if( fabs(errx) <= NEWT_TOL_B ){ + return(0); + } + + return(0); + +} + +/******************************************************************************/ +/****************************************************************************** + + bondi_resid(): + -------------- + -- routine to calculate the residual and jacobian used by + the Newton-Raphson routine general_newton_raphson(), which is + used to find X2 from theta; + +***********************************************************************************/ +static void bondi_resid(CCTK_REAL x[], CCTK_REAL dx[], CCTK_REAL resid[], CCTK_REAL jac[][NEWT_DIM_B], + CCTK_REAL *f, CCTK_REAL *df, int n ) +{ + CCTK_REAL v, vp, h, hp, term; + + hp = K * gamma_eos * pow( x[0], (gamma_eos - 2.) ); // dh/drho + h = 1. + hp * x[0] / ( gamma_eos - 1. ); + v = Mdot / ( 4. * M_PI * r_sol * r_sol * x[0] ); + vp = -v / x[0]; // dv/drho + term = 1. - 2.*M/r_sol + v*v; + resid[0] = -Qdot + h * h * term; + jac[0][0] = 2. * h *( hp*term + h*v*vp ); + dx[0] = -resid[0] / jac[0][0]; + *f = 0.5*resid[0]*resid[0]; + *df = -2. * (*f); + + return; + +} + + +/***************************************************************************/ +/*************************************************************************** + + find_bondi_solution(): + --------------------- + + -- essentially just calls gnr_bondi() to find the solution for + the density at a given radius, given the parameters calculated from + set_bondi_parameters(); + + -- after the density is found, the density (rho), internal energy densit (u), magnitude + of the radial component of the 4-velocity (v) are returned to the calling + routine; + + -- requires r = radius at which we want solution + + -- note that v is a magnitude, so the user will have to set u^r = -v ; + + -- if there is an error in finding the solution, it returns the error + status from the root-finding routine. See documentation of the + gnr_bondi() for further details; + +***************************************************************************/ +static int find_bondi_solution( CCTK_REAL r, CCTK_REAL *rho, CCTK_REAL *u, CCTK_REAL *v ) +{ + + int retval=0; + const int ntries = 10000; + int itry; + + CCTK_REAL rhotmp, rho_guess; + CCTK_REAL dr,ur; + + + /************************************************************************/ + /* Find the initial guess for the newton iterations: */ + /* Take the sonic point values if we have no better guess (when rho<0) */ + /************************************************************************/ + + if( *rho < 0. ) { + if( r > 0.9*rs && r < 1.1*rs ) { + *rho = rhos; + } + else { + // rhotmp = (sqrt(Qdot) - 1.) * (gamma_eos - 1.) / ( gamma_eos * K ); + // rho_guess = pow( rhotmp , (1./(gamma_eos - 1.)) ); + if(r < rs) { ur = pow(r,-0.5) ; } + else { ur = 0.5*pow(r,-1.5) ; } + rho_guess = Mdot / (4.*M_PI * r * r * ur); + *rho = rho_guess; + } + } + + // set global variables needed by residual function: + r_sol = r ; + + + // Use Newton's method to find rho: + retval = gnr_bondi( rho, NEWT_DIM_B, bondi_resid); + + + // first try guess if failure + if( retval ) { + *rho = rho_guess; + retval = gnr_bondi( rho, NEWT_DIM_B, bondi_resid); + } + + // If we were unsure about the guess and solver fails, then creep from known solution to desired point: + if( retval ) { + + dr = (r - rs)/(1.*(ntries-1)); + + *rho = rhos; // start with sonic point value and near sonic point + + // go gradually away from sonic point toward location where we want the solution: + r_sol = rs ; + for( itry = 1; itry < ntries; itry++ ) { + r_sol += dr; + + retval = gnr_bondi( rho, NEWT_DIM_B, bondi_resid); + + if( retval ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"find_bondi_solution: Incr. guess failed, decrease dfactor, retval = %d, r = %g, itry = %d \n", retval, r, itry); + return(10); + } + } + + // No try where we want the solution: + r_sol = r ; + retval = gnr_bondi( rho, NEWT_DIM_B, bondi_resid ); + + if( retval ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"find_bondi_solution: Final Incr. guess failed, decrease dfactor??, retval = %d \n", retval); + return(11); + } + + } + + rhotmp = *rho; + + // Calculate other quantities: + *u = K * pow( rhotmp, gamma_eos ) / (gamma_eos - 1.); + + *v = Mdot / ( 4. * M_PI * r * r * rhotmp ); + + if( *u <= 0. ) { retval = -1; } + + return( retval ) ; + +} + +/***********************************************************************************/ +/*********************************************************************************** + calc_vel_bondi(): + --------- + -- calculates the 4-velocity from the amplitude of the + radial component of the 4-velocity in Boyer-Lindquist coordinates. + +***********************************************************************************/ +static void calc_vel_bondi( CCTK_REAL vtmp, CCTK_REAL x[NDIM], CCTK_REAL x_spher[NDIM], CCTK_REAL ucon[NDIM] ) +{ + int i,j; + CCTK_REAL ucon_bl[NDIM] = {0.}; + CCTK_REAL ucon_ks[NDIM]; + CCTK_REAL gcov[NDIM][NDIM]; + CCTK_REAL r_iso; + CCTK_REAL dxc_dxs[NDIM][NDIM]; + + ucon_bl[RR] = -vtmp; + + /* Find time component of 4-velocity: */ + bl_gcov_func( x_spher, gcov ); + setutcon( ucon_bl, gcov ); + + + switch( coord_type ) { + + case COORD_BOYERLINDQUIST : + dxc_dxs_bl_calc(x, x_spher, dxc_dxs ); + DLOOP1 { ucon[i] = 0.; } + DLOOP2 { ucon[i] += dxc_dxs[i][j] * ucon_bl[j] ; } + break; + + + case COORD_KERRSCHILD : + bl_to_ks_con(x_spher,ucon_bl,ucon_ks); + dxc_dxs_ks_calc(x, x_spher, dxc_dxs ); + DLOOP1 { ucon[i] = 0.; } + DLOOP2 { ucon[i] += dxc_dxs[i][j] * ucon_ks[j] ; } + break; + + + case COORD_ISOTROPIC : + r_iso = x_spher[TT]; + ucon_bl[RR] /= 1. + 0.25 * (asq-Msq) / (r_iso*r_iso) ; /* BL to Isotropic coordinate transformation */ + /* I believe we can use BL's cartesian transformation, while using BL's radius : */ + dxc_dxs_iso_calc(x, x_spher, dxc_dxs ); + DLOOP1 { ucon[i] = 0.; } + DLOOP2 { ucon[i] += dxc_dxs[i][j] * ucon_bl[j] ; } + break; + + } + + return; +} + +/***********************************************************************************/ +/*********************************************************************************** + GRHydro_Bondi(): + --------- + -- driver routine for the Bondi solution; + +***********************************************************************************/ +void GRHydro_Bondi(CCTK_ARGUMENTS) +{ + DECLARE_CCTK_ARGUMENTS; + DECLARE_CCTK_PARAMETERS; + CCTK_REAL det; + CCTK_REAL rhotmp, utmp, vtmp, rspher, xpos[NDIM], x_spher[NDIM], ucon[NDIM]; + int retval; + CCTK_REAL *r_bondi, *logr_bondi, *rho_bondi, *u_bondi, *v_bondi; + CCTK_INT *bad_bondi; + CCTK_REAL dlogr,logrmin; + CCTK_REAL rmin_bondi,rmax_bondi; + CCTK_INT GRHydro_reflevel=0; + + CCTK_INT nbondi; + CCTK_INT ileft, iright, nans_exist; + CCTK_REAL sigma; + + + const int size = cctk_lsh[0] * cctk_lsh[1] * cctk_lsh[2]; + int i, imin, j; + +# define velx(i_) vel[i_ + 0*size] +# define vely(i_) vel[i_ + 1*size] +# define velz(i_) vel[i_ + 2*size] +# define sx(i_) scon[i_ + 0*size] +# define sy(i_) scon[i_ + 1*size] +# define sz(i_) scon[i_ + 2*size] + + if( CCTK_EQUALS(bondi_coordinates,"Boyer-Lindquist") ) { + coord_type = COORD_BOYERLINDQUIST ; + } + if( CCTK_EQUALS(bondi_coordinates,"Kerr-Schild") ) { + coord_type = COORD_KERRSCHILD ; + } + if( CCTK_EQUALS(bondi_coordinates,"Isotropic") ) { + coord_type = COORD_ISOTROPIC ; + } + + /* xyz location of the black hole : */ + i = 0; + x_cen = bh_bondi_pos_x[i] ; + y_cen = bh_bondi_pos_y[i] ; + z_cen = bh_bondi_pos_z[i] ; + + M = bondi_central_mass[i]; + a = M*bondi_central_spin[i]; + asq = a * a; + rmin_bondi = M * bondi_rmin[i]; + rmax_bondi = M * bondi_rmax[i]; + + nbondi = n_bondi_pts[i]; + + set_bondi_parameters( M, mdot_sonicpt_bondi, r_sonicpt_bondi, gl_gamma); + + +#if(LTRACE) + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\n##################################################\n"); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING," Geometry PARAMETERS \n------------------------------------\n"); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t M = %28.18e \n",M ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t a = %28.18e \n",a ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t x_cen = %28.18e \n",x_cen ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t y_cen = %28.18e \n",y_cen ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t z_cen = %28.18e \n",z_cen ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t rmin_bondi = %28.18e \n",rmin_bondi ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t rmax_bondi = %28.18e \n",rmax_bondi ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t nbondi = %d \n",nbondi ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\n------------------------------------\n"); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING," SOLUTION PARAMETERS \n------------------------------------\n"); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t bondi_coordinates = %s \n",bondi_coordinates ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t mdot_sonicpt_bondi = %28.18e \n",mdot_sonicpt_bondi); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t r_sonicpt_bondi = %28.18e \n",r_sonicpt_bondi ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\t gl_gamma = %28.18e \n",gl_gamma ); + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"\n------------------------------------\n"); +#endif + + if( r_sonicpt_bondi < rmin_bondi ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"sonic point lies below solution domain!!"); + } + + if( r_sonicpt_bondi > rmax_bondi ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"sonic point lies beyond solution domain!!"); + } + + + /********************************************************************************* + ARRAY ALLOCATIONS : + *********************************************************************************/ + /* global solution : */ + if( (r_bondi = (CCTK_REAL *) calloc(nbondi, sizeof(CCTK_REAL))) == NULL ) { + CCTK_WARN(CCTK_WARN_ABORT,"Cannot alloc r_bondi \n"); + return; + } + if( (logr_bondi = (CCTK_REAL *) calloc(nbondi, sizeof(CCTK_REAL))) == NULL ) { + free(r_bondi); + CCTK_WARN(CCTK_WARN_ABORT,"Cannot alloc logr_bondi \n"); + return; + } + if( (rho_bondi = (CCTK_REAL *) calloc(nbondi, sizeof(CCTK_REAL))) == NULL ) { + free(r_bondi); free(logr_bondi); + CCTK_WARN(CCTK_WARN_ABORT,"Cannot alloc rho_bondi \n"); + return; + } + if( (u_bondi = (CCTK_REAL *) calloc(nbondi, sizeof(CCTK_REAL))) == NULL ) { + free(r_bondi); free(logr_bondi); free(rho_bondi); + CCTK_WARN(CCTK_WARN_ABORT,"Cannot alloc u_bondi \n"); + return; + } + if( (v_bondi = (CCTK_REAL *) calloc(nbondi, sizeof(CCTK_REAL))) == NULL ) { + free(r_bondi); free(logr_bondi); free(rho_bondi); free(u_bondi); + CCTK_WARN(CCTK_WARN_ABORT,"Cannot alloc v_bondi \n"); + return; + } + if( (bad_bondi = (CCTK_INT *) calloc(nbondi, sizeof(CCTK_INT))) == NULL ) { + free(r_bondi); free(logr_bondi); free(rho_bondi); free(u_bondi); free(v_bondi); + CCTK_WARN(CCTK_WARN_ABORT,"Cannot alloc bad_bondi \n"); + return; + } + + + /********************************************************************************* + SOLUTION DOMAIN : + *********************************************************************************/ + logrmin = log10(rmin_bondi); + dlogr = (log10(rmax_bondi) - logrmin)/(1.*(nbondi-1)); + + for(i=0; i < nbondi; i++) { + logr_bondi[i] = logrmin + dlogr*i; + } + + for(i=0; i < nbondi; i++) { + r_bondi[i] = pow(10.,logr_bondi[i]); + } + + rhotmp = 1.e200; + imin = 0; + + /* find the position in the array where the sonic point lies */ + for(i=0; i < nbondi; i++) { + utmp = fabs(r_bondi[i] - r_sonicpt_bondi); + if( utmp < rhotmp ) { + rhotmp = utmp; + imin = i ; + } + } + + /********************************************************************************* + DETERMINE BONDI SOLUTION : + *********************************************************************************/ + + /* start at the sonic point (where we know the solution) and spread out from there using the + adjacent point as the guess for the next furthest point : */ + rhotmp = -1.; // start with guess + + for(i=imin; i < nbondi; i++) { + rspher = r_bondi[i]; + retval = find_bondi_solution( rspher, &rhotmp, &utmp, &vtmp ); + if( retval ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"Problem1 with find_bondi_solution() at i = %d, r = %28.16e \n",i,rspher); + rhotmp = -1. ; vtmp = 0.; /* trigger the floor and set to staticity */ + } + if(rhotmp < initial_rho_abs_min) { + rhotmp = initial_rho_abs_min; + utmp = K * pow( rhotmp, gl_gamma ) / (gl_gamma - 1.); + } + rho_bondi[i] = rhotmp; u_bondi[i] = utmp; v_bondi[i] = vtmp; + } + + rhotmp = -1.; // start with guess + + for(i=imin-1; i >= 0; i--) { + rspher = r_bondi[i]; + retval = find_bondi_solution( rspher, &rhotmp, &utmp, &vtmp ); + if( retval ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"Problem2 with find_bondi_solution() at i = %d, r = %28.16e \n",i,rspher); + rhotmp = -1. ; vtmp = 0.; /* trigger the floor and set to staticity */ + } + if(rhotmp < initial_rho_abs_min) { + rhotmp = initial_rho_abs_min; + utmp = K * pow( rhotmp, gl_gamma ) / (gl_gamma - 1.); + } + rho_bondi[i] = rhotmp; u_bondi[i] = utmp; v_bondi[i] = vtmp; + } + + + /* Verify Bondi solution, extrapolate/interpolate over Nans */ + nans_exist = 0 ; + + for(i=0; i < nbondi; i++) { bad_bondi[i] = 0 ; } + for(i=0; i < nbondi; i++) { + if( (!finite(rho_bondi[i])) || (!finite(u_bondi[i])) || (!finite(v_bondi[i])) || (rho_bondi[i]==0.) || (v_bondi[i]==0.) || (u_bondi[i]==0.) ) { + bad_bondi[i] = 1 ; + nans_exist++; + } + } + + if( nans_exist > (nbondi-3) ) { + CCTK_VWarn(CCTK_WARN_ABORT, __LINE__, __FILE__, CCTK_THORNSTRING,"Too many bad points %12d out of %12d \n",nans_exist,nbondi); + } + + /* We find the 2-point stencil by favoring interpolation over extrapolation, no matter the distance between the points */ + if( nans_exist ) { + for(i=0; i < nbondi; i++) { + if( bad_bondi[i] ) { + j = i-1; + while( (j > 0) && (bad_bondi[j]) ) { j--; } + + if( (j==0) && bad_bondi[j] ) { + /* No good points to the left, need two points on the right: */ + + while( (j < (nbondi-1)) && (bad_bondi[j]) ) { j++; } + if( (j==(nbondi-1)) && bad_bondi[j] ) { + CCTK_WARN(CCTK_WARN_ABORT,"No available points with which to interpolate!\n"); + } + else { + ileft = j ; + + /* Continue searching to the right: */ + j++; + while( (j < (nbondi-1)) && (bad_bondi[j]) ) { j++; } + if( (j==(nbondi-1)) && bad_bondi[j] ) { + CCTK_WARN(CCTK_WARN_ABORT,"Need another point to the right but cannot find one! \n"); + } + else { + iright = j ; + } + } + } + else { + /* Found a left point, need a right: */ + ileft = j ; + + j = i+1; + while( (j < (nbondi-1)) && (bad_bondi[j]) ) { j++; } + if( (j==(nbondi-1)) && bad_bondi[j] ) { + /* No good points to the right, need to find another point on the left: */ + iright = ileft; + + j = ileft-1; + while( (j > 0) && (bad_bondi[j]) ) { j--; } + if( (j==0) && bad_bondi[j] ) { + CCTK_WARN(CCTK_WARN_ABORT,"Need another point to the left but cannot find one! \n"); + } + else { + ileft = j; + } + } + else { + iright = j; + } + } + /* Now interpolate over the bad point with the good points found: */ + + sigma = (r_bondi[i]-r_bondi[ileft])/(r_bondi[iright]-r_bondi[ileft]); + rho_bondi[i] = rho_bondi[iright] * sigma + rho_bondi[ileft] * (1.-sigma) ; + u_bondi[i] = u_bondi[iright] * sigma + u_bondi[ileft] * (1.-sigma) ; + v_bondi[i] = v_bondi[iright] * sigma + v_bondi[ileft] * (1.-sigma) ; + } + } + } + + + +#if(LTRACE) + for(i=0; i < nbondi; i++) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"radial-bondisoln %12d %26.16e %26.16e %26.16e %26.16e %12d \n",i,r_bondi[i],rho_bondi[i],u_bondi[i],v_bondi[i], bad_bondi[i]); + } +#endif + + /********************************************************************************* + LOAD GRID FUNCTIONS WITH THE SOLUTION + *********************************************************************************/ + xpos[TT] = 0.; + + for(i=0; i < size; i++) { + + xpos[XX] = x[i] ; + xpos[YY] = y[i] ; + xpos[ZZ] = z[i] ; + + + switch( coord_type ) { + + case COORD_BOYERLINDQUIST : + bl_cart_to_bl_spher_pos( xpos, x_spher); + break; + + case COORD_KERRSCHILD : + ks_cart_to_ks_spher_pos( xpos, x_spher); + break; + + case COORD_ISOTROPIC : + iso_cart_to_bl_spher_pos(xpos, x_spher); + break; + + } + + rspher = x_spher[RR]; + + if( rspher < rmin_bondi ) rspher = rmin_bondi; + + + /* Find nearest point in the Bondi solution : */ + j = (int) ( 0.5 + (log10(rspher) - logrmin) / dlogr ) ; + + if( j < 0 ) { + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"Grid point resides outside solution domain: %26.16e %26.16e %26.16e %26.16e %26.16e\n", rspher, rmin_bondi, xpos[XX],xpos[YY],xpos[ZZ]); + j = 0; + } + else if( j > (nbondi - 1) ) { + CCTK_VWarn(CCTK_WARN_DEBUG, __LINE__, __FILE__, CCTK_THORNSTRING,"GRHydro_Bondi:: Grid point resides outside solution domain: %26.16e %26.16e %26.16e %26.16e %26.16e\n", rspher, rmin_bondi, xpos[XX],xpos[YY],xpos[ZZ]); + j = nbondi - 1; + } + + rhotmp = rho_bondi[j]; + retval = find_bondi_solution( rspher, &rhotmp, &utmp, &vtmp ); + if( retval ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"Problem3 with find_bondi_solution() at i = %d, r = %28.16e \n",i,rspher); + rhotmp = -1. ; vtmp = 0.; /* trigger the floor and set to staticity */ + } + + if(rhotmp < initial_rho_abs_min) { + rhotmp = initial_rho_abs_min; + utmp = K * pow( rhotmp, gl_gamma ) / (gl_gamma - 1.); + } + + rho[i] = rhotmp; + eps[i] = utmp/rhotmp; + calc_vel_bondi(vtmp, xpos, x_spher, ucon); + + det = 1./alp[i]; /* temp var */ + + velx(i) = (ucon[XX]/ucon[TT] + betax[i]) * det; + vely(i) = (ucon[YY]/ucon[TT] + betay[i]) * det; + velz(i) = (ucon[ZZ]/ucon[TT] + betaz[i]) * det; + + + SpatialDet(gxx[i],gxy[i],gxz[i],gyy[i],gyz[i],gzz[i],&det); + + Prim2ConGen(*GRHydro_eos_handle,gxx[i],gxy[i], + gxz[i],gyy[i],gyz[i],gzz[i], + det, &dens[i],&sx(i),&sy(i),&sz(i), + &tau[i],rho[i], + velx(i),vely(i),velz(i), + eps[i],&press[i],&w_lorentz[i]); + + if( (!finite(dens[i])) || (!finite(sx(i))) || (!finite(sy(i))) || (sz(i)==0.) || (tau[i]==0.) || (press[i]==0.) || (w_lorentz[i]==0.) ) { + CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,"bad point at %12d : %26.16e %26.16e %26.16e %26.16e %26.16e %26.16e %26.16e %26.16e %26.16e %26.16e %26.16e \n",i,rspher, rho[i], eps[i], press[i], velx(i), vely(i), velz(i), dens[i], sx(i), sy(i), sz(i) ); + dens[i] = rho_bondi[0]; + tau[i] = u_bondi[0]; + press[i] = (gamma_eos-1.)*u_bondi[0]; + w_lorentz[i] = 1.; + sx(i) = 0.; sy(i) = 0.; sz(i) = 0.; + } + + } + + free(r_bondi); free(logr_bondi); free(rho_bondi); free(u_bondi); free(v_bondi); + + +# undef velx +# undef vely +# undef velz +# undef sx +# undef sy +# undef sz + + + return; +} + + + + +#undef LTRACE +#undef NEWT_DIM_B +#undef MAX_NEWT_ITER_B +#undef NEWT_TOL_B +#undef MIN_NEWT_TOL_B +#undef EXTRA_NEWT_ITER_B +#undef SMALL_BONDI +#undef NDIM +#undef TT +#undef RR +#undef TH +#undef PH +#undef XX +#undef YY +#undef ZZ +#undef COORD_BOYERLINDQUIST +#undef COORD_KERRSCHILD +#undef COORD_ISOTROPIC +#undef DLOOP1 +#undef DLOOP2 + +#ifdef LOCAL_SINCOS +# undef sincos +# undef LOCAL_SINCOS +#endif |