def min_noif(a, b): # Returns the minimum of a and b if a == sp.sympify(0): return sp.Rational(1, 2) * (b - nrpyAbs(b)) if b == sp.sympify(0): return sp.Rational(1, 2) * (a - nrpyAbs(a)) return sp.Rational(1, 2) * (a + b - nrpyAbs(a - b))
def Ar_SM(r, theta, phi, **params): M = params["M"] a = params["a"] # A_r = -aC/8 * cos \theta ( 1 + 4M/r ) \sqrt{1 + 2M/r} return -a * C_SM * sp.Rational(1, 8) * nrpyAbs( sp.cos(theta)) * (sp.sympify(1) + sp.sympify(4) * M / r) * sp.sqrt(sp.sympify(1) + sp.sympify(2) * M / r)
def u4U_in_terms_of_ValenciavU__rescale_ValenciavU_by_applying_speed_limit( alpha, betaU, gammaDD, ValenciavU): # Inputs: Metric lapse alpha, shift betaU, 3-metric gammaDD, Valencia 3-velocity ValenciavU # Outputs (as globals): u4U_ito_ValenciavU, rescaledValenciavU # R = gamma_{ij} v^i v^j R = sp.sympify(0) for i in range(3): for j in range(3): R += gammaDD[i][j] * ValenciavU[i] * ValenciavU[j] thismodule = __name__ # The default value isn't terribly important here, since we can overwrite in the main C code GAMMA_SPEED_LIMIT = par.Cparameters("REAL", thismodule, "GAMMA_SPEED_LIMIT", 10.0) # Default value based on # IllinoisGRMHD. # GiRaFFE default = 2000.0 Rmax = 1 - 1 / (GAMMA_SPEED_LIMIT * GAMMA_SPEED_LIMIT) # Now, we set Rstar = min(Rmax,R): # If R < Rmax, then Rstar = 0.5*(Rmax+R-Rmax+R) = R # If R >= Rmax, then Rstar = 0.5*(Rmax+R+Rmax-R) = Rmax Rstar = sp.Rational(1, 2) * (Rmax + R - nrpyAbs(Rmax - R)) # We add TINYDOUBLE to R below to avoid a 0/0, which occurs when # ValenciavU == 0 for all Valencia 3-velocity components. # "Those tiny *doubles* make me warm all over # with a feeling that I'm gonna love you till the end of time." # - Adapted from Connie Francis' "Tiny Bubbles" TINYDOUBLE = par.Cparameters("#define", thismodule, "TINYDOUBLE", 1e-100) # The rescaled (speed-limited) Valencia 3-velocity # is given by, v_{(n)}^i = sqrt{Rstar/R} v^i global rescaledValenciavU rescaledValenciavU = ixp.zerorank1() for i in range(3): # If R == 0, then Rstar == 0, so sqrt( Rstar/(R+TINYDOUBLE) )=sqrt(0/1e-100) = 0 # If your velocities are of order 1e-100 and this is physically # meaningful, there must be something wrong with your unit conversion. rescaledValenciavU[i] = ValenciavU[i] * sp.sqrt(Rstar / (R + TINYDOUBLE)) # Finally compute u^mu in terms of Valenciav^i # u^0 = 1/(alpha-sqrt(1-R^*)) global u4U_ito_ValenciavU u4U_ito_ValenciavU = ixp.zerorank1(DIM=4) u4U_ito_ValenciavU[0] = 1 / (alpha * sp.sqrt(1 - Rstar)) # u^i = u^0 ( alpha v^i_{(n)} - beta^i ), where v^i_{(n)} is the Valencia 3-velocity for i in range(3): u4U_ito_ValenciavU[i + 1] = u4U_ito_ValenciavU[0] * ( alpha * rescaledValenciavU[i] - betaU[i])
def Enforce_Detgammabar_Constraint_symb_expressions(): # Set spatial dimension (must be 3 for BSSN) DIM = 3 # Then we set the coordinate system for the numerical grid rfm.reference_metric( ) # Create ReU, ReDD needed for rescaling B-L initial data, generating BSSN RHSs, etc. # We will need the h_{ij} quantities defined within BSSN_RHSs # below when we enforce the gammahat=gammabar constraint # Step 1: All barred quantities are defined in terms of BSSN rescaled gridfunctions, # which we declare here in case they haven't yet been declared elsewhere. Bq.declare_BSSN_gridfunctions_if_not_declared_already() hDD = Bq.hDD Bq.BSSN_basic_tensors() gammabarDD = Bq.gammabarDD # First define the Kronecker delta: KroneckerDeltaDD = ixp.zerorank2() for i in range(DIM): KroneckerDeltaDD[i][i] = sp.sympify(1) # The detgammabar in BSSN_RHSs is set to detgammahat when BSSN_RHSs::detgbarOverdetghat_equals_one=True (default), # so we manually compute it here: dummygammabarUU, detgammabar = ixp.symm_matrix_inverter3x3(gammabarDD) # Next apply the constraint enforcement equation above. hprimeDD = ixp.zerorank2() for i in range(DIM): for j in range(DIM): hprimeDD[i][j] = \ (nrpyAbs(rfm.detgammahat) / detgammabar) ** (sp.Rational(1, 3)) * (KroneckerDeltaDD[i][j] + hDD[i][j]) \ - KroneckerDeltaDD[i][j] enforce_detg_constraint_symb_expressions = [ lhrh(lhs=gri.gfaccess("in_gfs", "hDD00"), rhs=hprimeDD[0][0]), lhrh(lhs=gri.gfaccess("in_gfs", "hDD01"), rhs=hprimeDD[0][1]), lhrh(lhs=gri.gfaccess("in_gfs", "hDD02"), rhs=hprimeDD[0][2]), lhrh(lhs=gri.gfaccess("in_gfs", "hDD11"), rhs=hprimeDD[1][1]), lhrh(lhs=gri.gfaccess("in_gfs", "hDD12"), rhs=hprimeDD[1][2]), lhrh(lhs=gri.gfaccess("in_gfs", "hDD22"), rhs=hprimeDD[2][2]) ] return enforce_detg_constraint_symb_expressions
def Aph_SM(r, theta, phi, **params): M = params["M"] a = params["a"] # A_\phi = M^2 C [1-\cos \theta + a^2 f(r) cos \theta sin^2 \theta] return M * M * C_SM * (sp.sympify(1) - nrpyAbs(sp.cos(theta)) + a * a * f_of_r(r, M) * sp.cos(theta) * sp.sin(theta)**2)
def GiRaFFE_NRPy_C2P(StildeD,BU,gammaDD,betaU,alpha): GRHD.compute_sqrtgammaDET(gammaDD) gammaUU,unusedgammadet = ixp.symm_matrix_inverter3x3(gammaDD) BtildeU = ixp.zerorank1() for i in range(3): # \tilde{B}^i = B^i \sqrt{\gamma} BtildeU[i] = GRHD.sqrtgammaDET*BU[i] BtildeD = ixp.zerorank1() for i in range(3): for j in range(3): BtildeD[j] += gammaDD[i][j]*BtildeU[i] Btilde2 = sp.sympify(0) for i in range(3): Btilde2 += BtildeU[i]*BtildeD[i] global outStildeD outStildeD = StildeD # Then, enforce the orthogonality: if par.parval_from_str("enforce_orthogonality_StildeD_BtildeU"): StimesB = sp.sympify(0) for i in range(3): StimesB += StildeD[i]*BtildeU[i] for i in range(3): # {\tilde S}_i = {\tilde S}_i - ({\tilde S}_j {\tilde B}^j) {\tilde B}_i/{\tilde B}^2 outStildeD[i] -= StimesB*BtildeD[i]/Btilde2 # Calculate \tilde{S}^2: Stilde2 = sp.sympify(0) for i in range(3): for j in range(3): Stilde2 += gammaUU[i][j]*outStildeD[i]*outStildeD[j] # First we need to compute the factor f: # f = \sqrt{(1-\Gamma_{\max}^{-2}){\tilde B}^4/(16 \pi^2 \gamma {\tilde S}^2)} speed_limit_factor = sp.sqrt((sp.sympify(1)-GAMMA_SPEED_LIMIT**(-2.0))*Btilde2*Btilde2*sp.Rational(1,16)/\ (M_PI*M_PI*GRHD.sqrtgammaDET*GRHD.sqrtgammaDET*Stilde2)) import Min_Max_and_Piecewise_Expressions as noif # Calculate B^2 B2 = sp.sympify(0) for i in range(3): for j in range(3): B2 += gammaDD[i][j]*BU[i]*BU[j] # Enforce the speed limit on StildeD: if par.parval_from_str("enforce_speed_limit_StildeD"): for i in range(3): outStildeD[i] *= noif.min_noif(sp.sympify(1),speed_limit_factor) global ValenciavU ValenciavU = ixp.zerorank1() # Recompute 3-velocity: for i in range(3): for j in range(3): # \bar{v}^i = 4 \pi \gamma^{ij} {\tilde S}_j / (\sqrt{\gamma} B^2) ValenciavU[i] += sp.sympify(4)*M_PI*gammaUU[i][j]*outStildeD[j]/(GRHD.sqrtgammaDET*B2) # This number determines how far away (in grid points) we will apply the fix. grid_points_from_z_plane = par.Cparameters("REAL",thismodule,"grid_points_from_z_plane",4.0) if par.parval_from_str("enforce_current_sheet_prescription"): # Calculate the drift velocity driftvU = ixp.zerorank1() for i in range(3): driftvU[i] = alpha*ValenciavU[i] - betaU[i] # The direct approach, used by the original GiRaFFE: # v^z = -(\gamma_{xz} v^x + \gamma_{yz} v^y) / \gamma_{zz} newdriftvU2 = -(gammaDD[0][2]*driftvU[0] + gammaDD[1][2]*driftvU[1])/gammaDD[2][2] # Now that we have the z component, it's time to substitute its Valencia form in. # Remember, we only do this if abs(z) < (k+0.01)*dz. Note that we add 0.01; this helps # avoid floating point errors and division by zero. This is the same as abs(z) - (k+0.01)*dz<0 coord = nrpyAbs(rfm.xx[2]) bound =(grid_points_from_z_plane+sp.Rational(1,100))*gri.dxx[2] ValenciavU[2] = noif.coord_leq_bound(coord,bound)*(newdriftvU2+betaU[2])/alpha \ + noif.coord_greater_bound(coord,bound)*ValenciavU[2]