def test_example_BSSN(): import NRPy_param_funcs as par, reference_metric as rfm, BSSN.BSSN_RHSs as Brhs Parser.clear_namespace() parse(r""" % define deltaDD (3D), sym01 hDD (3D), sym01 aDD (3D), vetU (3D) % parse \hat{\gamma}_{ij} = \delta_{ij} % assign symbolic <H> gammahatDD % parse \bar{\gamma}_{ij} = h_{ij} + \hat{\gamma}_{ij} % assign numeric hDD, aDD, vetU, gammabarDD % assign metric gammahatDD, gammabarDD % srepl "\bar{A}" -> "a", "\beta" -> "\text{vet}" % parse \bar{A}^i_j = \bar{\gamma}^{ik} \bar{A}_{kj} \begin{align} % define basis [x, y, z] %% parse \partial_k \bar{\gamma}_{ij} = \vphantom{upwind} \partial_k h_{ij} + \partial_k \hat{\gamma}_{ij} % srepl "\text{vet}^<1> \partial_<1>" -> "\text{vet}^<1> \vphantom{upwind} \partial_<1>" %% (inside Lie derivative expansion) % srepl "\bar{D}_k \text{vet}^k" -> "(\partial_k \text{vet}^k + \frac{\text{vet}^k \vphantom{symbolic} \partial_k \text{gammabardet}}{2 \text{gammabardet}})" % srepl "\partial_t \bar{\gamma}" -> "\text{h_rhs}" \partial_t \bar{\gamma}_{ij} &= \mathcal{L}_\beta \bar{\gamma}_{ij} + \frac{2}{3} \bar{\gamma}_{ij} \left(\alpha \bar{A}^k{}_k - \bar{D}_k \beta^k\right) - 2 \alpha \bar{A}_{ij} % srepl "K" -> "\text{trK}", "\phi" -> "\text{cf}", "\partial_t \text{cf}" -> "\text{cf_rhs}" \partial_t \phi &= \mathcal{L}_\beta \phi - \frac{1}{3} \phi \left(\bar{D}_k \beta^k - \alpha K \right) \end{align} """) par.set_parval_from_str('reference_metric::CoordSystem', 'Cartesian') rfm.reference_metric() Brhs.BSSN_RHSs() assert_equal({ 'h_rhsDD': h_rhsDD, 'cf_rhs': cf_rhs }, { 'h_rhsDD': Brhs.h_rhsDD, 'cf_rhs': Brhs.cf_rhs })
def Ricci__generate_symbolic_expressions(): ###################################### # START: GENERATE SYMBOLIC EXPRESSIONS print("Generating symbolic expressions for Ricci tensor...") start = time.time() # Enable rfm_precompute infrastructure, which results in # BSSN RHSs that are free of transcendental functions, # even in curvilinear coordinates, so long as # ConformalFactor is set to "W" (default). par.set_parval_from_str("reference_metric::enable_rfm_precompute","True") par.set_parval_from_str("reference_metric::rfm_precompute_Ccode_outdir",os.path.join(outdir,"rfm_files/")) # Evaluate BSSN + BSSN gauge RHSs with rfm_precompute enabled: import BSSN.BSSN_quantities as Bq # Next compute Ricci tensor # par.set_parval_from_str("BSSN.BSSN_quantities::LeaveRicciSymbolic","False") RbarDD_already_registered = False for i in range(len(gri.glb_gridfcs_list)): if "RbarDD00" in gri.glb_gridfcs_list[i].name: RbarDD_already_registered = True if not RbarDD_already_registered: # We ignore the return value of ixp.register_gridfunctions_for_single_rank2() below # as it is unused. ixp.register_gridfunctions_for_single_rank2("AUXEVOL","RbarDD","sym01") rhs.BSSN_RHSs() Bq.RicciBar__gammabarDD_dHatD__DGammaUDD__DGammaU() # Now that we are finished with all the rfm hatted # quantities in generic precomputed functional # form, let's restore them to their closed- # form expressions. par.set_parval_from_str("reference_metric::enable_rfm_precompute","False") # Reset to False to disable rfm_precompute. rfm.ref_metric__hatted_quantities() end = time.time() print("(BENCH) Finished Ricci symbolic expressions in "+str(end-start)+" seconds.") # END: GENERATE SYMBOLIC EXPRESSIONS ###################################### Ricci_SymbExpressions = [lhrh(lhs=gri.gfaccess("auxevol_gfs","RbarDD00"),rhs=Bq.RbarDD[0][0]), lhrh(lhs=gri.gfaccess("auxevol_gfs","RbarDD01"),rhs=Bq.RbarDD[0][1]), lhrh(lhs=gri.gfaccess("auxevol_gfs","RbarDD02"),rhs=Bq.RbarDD[0][2]), lhrh(lhs=gri.gfaccess("auxevol_gfs","RbarDD11"),rhs=Bq.RbarDD[1][1]), lhrh(lhs=gri.gfaccess("auxevol_gfs","RbarDD12"),rhs=Bq.RbarDD[1][2]), lhrh(lhs=gri.gfaccess("auxevol_gfs","RbarDD22"),rhs=Bq.RbarDD[2][2])] return [Ricci_SymbExpressions]
def BSSN_RHSs__generate_symbolic_expressions(): ###################################### # START: GENERATE SYMBOLIC EXPRESSIONS print("Generating symbolic expressions for BSSN RHSs...") start = time.time() # Enable rfm_precompute infrastructure, which results in # BSSN RHSs that are free of transcendental functions, # even in curvilinear coordinates, so long as # ConformalFactor is set to "W" (default). par.set_parval_from_str("reference_metric::enable_rfm_precompute","True") par.set_parval_from_str("reference_metric::rfm_precompute_Ccode_outdir",os.path.join(outdir,"rfm_files/")) # Evaluate BSSN + BSSN gauge RHSs with rfm_precompute enabled: import BSSN.BSSN_quantities as Bq par.set_parval_from_str("BSSN.BSSN_quantities::LeaveRicciSymbolic","True") rhs.BSSN_RHSs() if T4UU != None: import BSSN.BSSN_stress_energy_source_terms as Bsest Bsest.BSSN_source_terms_for_BSSN_RHSs(T4UU) rhs.trK_rhs += Bsest.sourceterm_trK_rhs for i in range(3): # Needed for Gamma-driving shift RHSs: rhs.Lambdabar_rhsU[i] += Bsest.sourceterm_Lambdabar_rhsU[i] # Needed for BSSN RHSs: rhs.lambda_rhsU[i] += Bsest.sourceterm_lambda_rhsU[i] for j in range(3): rhs.a_rhsDD[i][j] += Bsest.sourceterm_a_rhsDD[i][j] gaugerhs.BSSN_gauge_RHSs() # Add Kreiss-Oliger dissipation to the BSSN RHSs: thismodule = "KO_Dissipation" diss_strength = par.Cparameters("REAL", thismodule, "diss_strength", default_KO_strength) alpha_dKOD = ixp.declarerank1("alpha_dKOD") cf_dKOD = ixp.declarerank1("cf_dKOD") trK_dKOD = ixp.declarerank1("trK_dKOD") betU_dKOD = ixp.declarerank2("betU_dKOD","nosym") vetU_dKOD = ixp.declarerank2("vetU_dKOD","nosym") lambdaU_dKOD = ixp.declarerank2("lambdaU_dKOD","nosym") aDD_dKOD = ixp.declarerank3("aDD_dKOD","sym01") hDD_dKOD = ixp.declarerank3("hDD_dKOD","sym01") for k in range(3): gaugerhs.alpha_rhs += diss_strength*alpha_dKOD[k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.cf_rhs += diss_strength* cf_dKOD[k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.trK_rhs += diss_strength* trK_dKOD[k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] for i in range(3): if "2ndOrder" in ShiftCondition: gaugerhs.bet_rhsU[i] += diss_strength* betU_dKOD[i][k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] gaugerhs.vet_rhsU[i] += diss_strength* vetU_dKOD[i][k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.lambda_rhsU[i] += diss_strength*lambdaU_dKOD[i][k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] for j in range(3): rhs.a_rhsDD[i][j] += diss_strength*aDD_dKOD[i][j][k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.h_rhsDD[i][j] += diss_strength*hDD_dKOD[i][j][k]*rfm.ReU[k] # ReU[k] = 1/scalefactor_orthog_funcform[k] # We use betaU as our upwinding control vector: Bq.BSSN_basic_tensors() betaU = Bq.betaU # Now that we are finished with all the rfm hatted # quantities in generic precomputed functional # form, let's restore them to their closed- # form expressions. par.set_parval_from_str("reference_metric::enable_rfm_precompute","False") # Reset to False to disable rfm_precompute. rfm.ref_metric__hatted_quantities() par.set_parval_from_str("BSSN.BSSN_quantities::LeaveRicciSymbolic","False") end = time.time() print("(BENCH) Finished BSSN RHS symbolic expressions in "+str(end-start)+" seconds.") # END: GENERATE SYMBOLIC EXPRESSIONS ###################################### BSSN_RHSs_SymbExpressions = [lhrh(lhs=gri.gfaccess("rhs_gfs","aDD00"), rhs=rhs.a_rhsDD[0][0]), lhrh(lhs=gri.gfaccess("rhs_gfs","aDD01"), rhs=rhs.a_rhsDD[0][1]), lhrh(lhs=gri.gfaccess("rhs_gfs","aDD02"), rhs=rhs.a_rhsDD[0][2]), lhrh(lhs=gri.gfaccess("rhs_gfs","aDD11"), rhs=rhs.a_rhsDD[1][1]), lhrh(lhs=gri.gfaccess("rhs_gfs","aDD12"), rhs=rhs.a_rhsDD[1][2]), lhrh(lhs=gri.gfaccess("rhs_gfs","aDD22"), rhs=rhs.a_rhsDD[2][2]), lhrh(lhs=gri.gfaccess("rhs_gfs","alpha"), rhs=gaugerhs.alpha_rhs), lhrh(lhs=gri.gfaccess("rhs_gfs","betU0"), rhs=gaugerhs.bet_rhsU[0]), lhrh(lhs=gri.gfaccess("rhs_gfs","betU1"), rhs=gaugerhs.bet_rhsU[1]), lhrh(lhs=gri.gfaccess("rhs_gfs","betU2"), rhs=gaugerhs.bet_rhsU[2]), lhrh(lhs=gri.gfaccess("rhs_gfs","cf"), rhs=rhs.cf_rhs), lhrh(lhs=gri.gfaccess("rhs_gfs","hDD00"), rhs=rhs.h_rhsDD[0][0]), lhrh(lhs=gri.gfaccess("rhs_gfs","hDD01") ,rhs=rhs.h_rhsDD[0][1]), lhrh(lhs=gri.gfaccess("rhs_gfs","hDD02"), rhs=rhs.h_rhsDD[0][2]), lhrh(lhs=gri.gfaccess("rhs_gfs","hDD11"), rhs=rhs.h_rhsDD[1][1]), lhrh(lhs=gri.gfaccess("rhs_gfs","hDD12"), rhs=rhs.h_rhsDD[1][2]), lhrh(lhs=gri.gfaccess("rhs_gfs","hDD22"), rhs=rhs.h_rhsDD[2][2]), lhrh(lhs=gri.gfaccess("rhs_gfs","lambdaU0"),rhs=rhs.lambda_rhsU[0]), lhrh(lhs=gri.gfaccess("rhs_gfs","lambdaU1"),rhs=rhs.lambda_rhsU[1]), lhrh(lhs=gri.gfaccess("rhs_gfs","lambdaU2"),rhs=rhs.lambda_rhsU[2]), lhrh(lhs=gri.gfaccess("rhs_gfs","trK"), rhs=rhs.trK_rhs), lhrh(lhs=gri.gfaccess("rhs_gfs","vetU0"), rhs=gaugerhs.vet_rhsU[0]), lhrh(lhs=gri.gfaccess("rhs_gfs","vetU1"), rhs=gaugerhs.vet_rhsU[1]), lhrh(lhs=gri.gfaccess("rhs_gfs","vetU2"), rhs=gaugerhs.vet_rhsU[2]) ] return [betaU,BSSN_RHSs_SymbExpressions]
def test_example_BSSN(): parse_latex(r""" \begin{align} % keydef basis [x, y, z] % ignore "\\%", "\qquad" % vardef -kron 'deltaDD' % parse \hat{\gamma}_{ij} = \delta_{ij} % assign -diff_type=symbolic -metric 'gammahatDD' % vardef -diff_type=dD -symmetry=sym01 'hDD' % parse \bar{\gamma}_{ij} = h_{ij} + \hat{\gamma}_{ij} % assign -diff_type=dD -metric 'gammabarDD' % srepl "\beta" -> "\text{vet}" % vardef -diff_type=dD 'vetU' %% upwind pattern inside Lie derivative expansion % srepl -persist "\text{vet}^{<1>} \partial_{<1>}" -> "\text{vet}^{<1>} \vphantom{dupD} \partial_{<1>}" %% substitute tensor identity (see appropriate BSSN notebook) % srepl "\bar{D}_k \text{vet}^k" -> "(\partial_k \text{vet}^k + \frac{\partial_k \text{gammahatdet} \text{vet}^k}{2 \text{gammahatdet}})" % srepl "\bar{A}" -> "\text{a}" % vardef -diff_type=dD -symmetry=sym01 'aDD' % assign -metric='gammabar' 'aDD' % srepl "\partial_t \bar{\gamma}" -> "\text{h_rhs}" \partial_t \bar{\gamma}_{ij} &= \mathcal{L}_\beta \bar{\gamma}_{ij} + \frac{2}{3} \bar{\gamma}_{ij} \left(\alpha \bar{A}^k{}_k - \bar{D}_k \beta^k\right) - 2 \alpha \bar{A}_{ij} \\ % srepl "K" -> "\text{trK}" % vardef -diff_type=dD 'cf', 'trK' %% replace 'phi' with conformal factor cf = W = e^{-2\phi} % srepl "e^{-4\phi}" -> "\text{cf}^2" % srepl "\partial_t \phi = <1..> \\" -> "\text{cf_rhs} = -2 \text{cf} (<1..>) \\" % srepl -persist "\partial_{<1>} \phi" -> "\partial_{<1>} \text{cf} \frac{-1}{2 \text{cf}}" % srepl "\partial_<1> \phi" -> "\partial_<1> \text{cf} \frac{-1}{2 \text{cf}}" \partial_t \phi &= \mathcal{L}_\beta \phi + \frac{1}{6} \left(\bar{D}_k \beta^k - \alpha K \right) \\ % vardef -diff_type=dD 'alpha' % srepl "\partial_t \text{trK}" -> "\text{trK_rhs}" \partial_t K &= \mathcal{L}_\beta K + \frac{1}{3} \alpha K^2 + \alpha \bar{A}_{ij} \bar{A}^{ij} - e^{-4\phi} \left(\bar{D}_i \bar{D}^i \alpha + 2 \bar{D}^i \alpha \bar{D}_i \phi\right) \\ % srepl "\bar{\Lambda}" -> "\text{lambda}" % vardef -diff_type=dD 'lambdaU' % parse \Delta^k_{ij} = \bar{\Gamma}^k_{ij} - \hat{\Gamma}^k_{ij} % assign -metric='gammabar' 'DeltaUDD' % parse \Delta^k = \bar{\gamma}^{ij} \Delta^k_{ij} % srepl "\partial_t \text{lambda}" -> "\text{Lambdabar_rhs}" \partial_t \bar{\Lambda}^i &= \mathcal{L}_\beta \bar{\Lambda}^i + \bar{\gamma}^{jk} \hat{D}_j \hat{D}_k \beta^i + \frac{2}{3} \Delta^i \bar{D}_k \beta^k + \frac{1}{3} \bar{D}^i \bar{D}_k \beta^k \\% &\qquad- 2 \bar{A}^{ij} \left(\partial_j \alpha - 6 \alpha \partial_j \phi\right) + 2 \alpha \bar{A}^{jk} \Delta^i_{jk} - \frac{4}{3} \alpha \bar{\gamma}^{ij} \partial_j K \\ % vardef -diff_type=dD -symmetry=sym01 'RbarDD' X_{ij} &= -2 \alpha \bar{D}_i \bar{D}_j \phi + 4 \alpha \bar{D}_i \phi \bar{D}_j \phi + 2 \bar{D}_i \alpha \bar{D}_j \phi + 2 \bar{D}_j \alpha \bar{D}_i \phi - \bar{D}_i \bar{D}_j \alpha + \alpha \bar{R}_{ij} \\ \hat{X}_{ij} &= X_{ij} - \frac{1}{3} \bar{\gamma}_{ij} \bar{\gamma}^{kl} X_{kl} \\ % srepl "\partial_t \text{a}" -> "\text{a_rhs}" \partial_t \bar{A}_{ij} &= \mathcal{L}_\beta \bar{A}_{ij} - \frac{2}{3} \bar{A}_{ij} \bar{D}_k \beta^k - 2 \alpha \bar{A}_{ik} \bar{A}^k_j + \alpha \bar{A}_{ij} K + e^{-4\phi} \hat{X}_{ij} \\ % srepl "\partial_t \alpha" -> "\text{alpha_rhs}" \partial_t \alpha &= \mathcal{L}_\beta \alpha - 2 \alpha K \\ % srepl "B" -> "\text{bet}" % vardef -diff_type=dD 'betU' % srepl "\partial_t \text{vet}" -> "\text{vet_rhs}" \partial_t \beta^i &= \left[\beta^j \vphantom{dupD} \bar{D}_j \beta^i\right] + B^i \\ % vardef -const 'eta' % srepl "\partial_t \text{bet}" -> "\text{bet_rhs}" \partial_t B^i &= \left[\beta^j \vphantom{dupD} \bar{D}_j B^i\right] + \frac{3}{4} \left(\partial_t \bar{\Lambda}^i - \left[\beta^j \vphantom{dupD} \bar{D}_j \bar{\Lambda}^i\right]\right) - \eta B^i \\ % parse \bar{R} = \bar{\gamma}^{ij} \bar{R}_{ij} % srepl "\bar{D}^2" -> "\bar{D}^i \bar{D}_i", "\mathcal{<1>}" -> "<1>" \mathcal{H} &= \frac{2}{3} K^2 - \bar{A}_{ij} \bar{A}^{ij} + e^{-4\phi} \left(\bar{R} - 8 \bar{D}^i \phi \bar{D}_i \phi - 8 \bar{D}^2 \phi\right) \\ \mathcal{M}^i &= e^{-4\phi} \left(\bar{D}_j \bar{A}^{ij} + 6 \bar{A}^{ij} \partial_j \phi - \frac{2}{3} \bar{\gamma}^{ij} \partial_j K\right) \\ \bar{R}_{ij} &= -\frac{1}{2} \bar{\gamma}^{kl} \hat{D}_k \hat{D}_l \bar{\gamma}_{ij} + \frac{1}{2} \left(\bar{\gamma}_{ki} \hat{D}_j \bar{\Lambda}^k + \bar{\gamma}_{kj} \hat{D}_i \bar{\Lambda}^k\right) + \frac{1}{2} \Delta^k \left(\Delta_{ijk} + \Delta_{jik}\right) \\% &\qquad+ \bar{\gamma}^{kl} \left(\Delta^m_{ki} \Delta_{jml} + \Delta^m_{kj} \Delta_{iml} + \Delta^m_{ik} \Delta_{mjl}\right) \end{align} """, ignore_warning=True) par.set_parval_from_str('reference_metric::CoordSystem', 'Cartesian') par.set_parval_from_str('BSSN.BSSN_quantities::LeaveRicciSymbolic', 'True') rfm.reference_metric() Brhs.BSSN_RHSs() gaugerhs.BSSN_gauge_RHSs() bssncon.BSSN_constraints() par.set_parval_from_str('BSSN.BSSN_quantities::LeaveRicciSymbolic', 'False') Bq.RicciBar__gammabarDD_dHatD__DGammaUDD__DGammaU() assert_equal( { 'h_rhsDD': h_rhsDD, 'cf_rhs': cf_rhs, 'trK_rhs': trK_rhs, 'Lambdabar_rhsU': Lambdabar_rhsU, 'a_rhsDD': a_rhsDD, 'alpha_rhs': alpha_rhs, 'vet_rhsU': vet_rhsU, 'bet_rhsU': bet_rhsU, 'H': H, 'MU': MU, 'RbarDD': RbarDD }, { 'h_rhsDD': Brhs.h_rhsDD, 'cf_rhs': Brhs.cf_rhs, 'trK_rhs': Brhs.trK_rhs, 'Lambdabar_rhsU': Brhs.Lambdabar_rhsU, 'a_rhsDD': Brhs.a_rhsDD, 'alpha_rhs': gaugerhs.alpha_rhs, 'vet_rhsU': gaugerhs.vet_rhsU, 'bet_rhsU': gaugerhs.bet_rhsU, 'H': bssncon.H, 'MU': bssncon.MU, 'RbarDD': Bq.RbarDD }, suppress_message=True)
def test_example_BSSN(): import NRPy_param_funcs as par, reference_metric as rfm import BSSN.BSSN_RHSs as Brhs, BSSN.BSSN_quantities as Bq Parser.clear_namespace() parse(r""" % keydef basis [x, y, z] % ignore "\\%", "\qquad" % vardef 'deltaDD', 'vetU', 'lambdaU' % vardef -numeric -sym01 'hDD', 'aDD', 'RbarDD' % assign -numeric 'cf', 'alpha', 'trK', 'vetU', 'lambdaU' % parse \hat{\gamma}_{ij} = \delta_{ij} % assign -symbolic <H> -metric 'gammahatDD' % parse \bar{\gamma}_{ij} = h_{ij} + \hat{\gamma}_{ij} % assign -numeric -metric 'gammabarDD' \begin{align} %% replace LaTeX variable(s) with BSSN variable(s) % srepl "\bar{A}" -> "\text{a}", "\beta" -> "\text{vet}", "K" -> "\text{trK}", "\bar{\Lambda}" -> "\text{lambda}" % srepl "e^{{-4\phi}}" -> "\text{cf}^{{2}}" % srepl "\partial_t \phi = <1..> \\" -> "\text{cf_rhs} = -2 \text{cf} (<1..>) \\" % srepl -global "\partial_<1> \phi" -> "\partial_<1> \text{cf} \frac{-1}{2 \text{cf}}" % srepl -global "\partial_<1> \text{phi}" -> "\partial_<1> \text{cf} \frac{-1}{2 \text{cf}}" % srepl -global "\partial_<1> (\text{phi})" -> "\partial_<1> \text{cf} \frac{-1}{2 \text{cf}}" %% upwind pattern inside Lie derivative expansion % srepl -global "\text{vet}^<1> \partial_<1>" -> "\text{vet}^<1> \vphantom{upwind} \partial_<1>" %% enforce metric constraint gammabardet == gammahatdet % srepl -global "\bar{D}^i \bar{D}_k \text{vet}^k" -> "(\bar{D}^i \partial_k \text{vet}^k)" % srepl -global "\bar{D}_k \text{vet}^k" -> "(\partial_k \text{vet}^k + \frac{\partial_k \text{gammahatdet} \text{vet}^k}{2 \text{gammahatdet}})" % parse \bar{A}^i_j = \bar{\gamma}^{ik} \bar{A}_{kj} % srepl "\partial_t \bar{\gamma}" -> "\text{h_rhs}" \partial_t \bar{\gamma}_{ij} &= \mathcal{L}_\beta \bar{\gamma}_{ij} + \frac{2}{3} \bar{\gamma}_{ij} \left(\alpha \bar{A}^k{}_k - \bar{D}_k \beta^k\right) - 2 \alpha \bar{A}_{ij} \\ \partial_t \phi &= \mathcal{L}_\beta \phi + \frac{1}{6} \left(\bar{D}_k \beta^k - \alpha K \right) \\ % parse \bar{A}^{ij} = \bar{\gamma}^{ik} \bar{\gamma}^{jl} \bar{A}_{kl} % srepl "\partial_t \text{trK}" -> "\text{trK_rhs}" \partial_t K &= \mathcal{L}_\beta K + \frac{1}{3} \alpha K^{{2}} + \alpha \bar{A}_{ij} \bar{A}^{ij} - e^{{-4\phi}} \left(\bar{D}_i \bar{D}^i \alpha + 2 \bar{D}^i \alpha \bar{D}_i \phi\right) \\ % parse \Pi^k_{ij} = \bar{\Gamma}^k_{ij} - \hat{\Gamma}^k_{ij} % parse \Pi_{ijk} = \bar{\gamma}_{il} \Pi^l_{jk} % parse \Pi^k = \bar{\gamma}^{ij} \Pi^k_{ij} % srepl "\partial_t \text{lambda}" -> "\text{Lambdabar_rhs}" \partial_t \bar{\Lambda}^i &= \mathcal{L}_\beta \bar{\Lambda}^i + \bar{\gamma}^{jk} \hat{D}_j \hat{D}_k \beta^i + \frac{2}{3} \Pi^i \bar{D}_k \beta^k + \frac{1}{3} \bar{D}^i \bar{D}_k \beta^k \\% &\qquad- 2 \bar{A}^{ij} (\partial_j \alpha - 6 \alpha \partial_j \phi) + 2 \alpha \bar{A}^{jk} \Pi^i_{jk} - \frac{4}{3} \alpha \bar{\gamma}^{ij} \partial_j K \\ X_{ij} &= -2 \alpha \bar{D}_i \bar{D}_j \phi + 4 \alpha \bar{D}_i \phi \bar{D}_j \phi + 2 \bar{D}_i \alpha \bar{D}_j \phi + 2 \bar{D}_j \alpha \bar{D}_i \phi - \bar{D}_i \bar{D}_j \alpha + \alpha \bar{R}_{ij} \\ \hat{X}_{ij} &= X_{ij} - \frac{1}{3} \bar{\gamma}_{ij} \bar{\gamma}^{kl} X_{kl} \\ % srepl "\partial_t \text{a}" -> "\text{a_rhs}" \partial_t \bar{A}_{ij} &= \mathcal{L}_\beta \bar{A}_{ij} - \frac{2}{3} \bar{A}_{ij} \bar{D}_k \beta^k - 2 \alpha \bar{A}_{ik} \bar{A}^k_j + \alpha \bar{A}_{ij} K + e^{{-4\phi}} \hat{X}_{ij} \\ \bar{R}_{ij} &= -\frac{1}{2} \bar{\gamma}^{kl} \hat{D}_k \hat{D}_l \bar{\gamma}_{ij} + \frac{1}{2} (\bar{\gamma}_{ki} \hat{D}_j \bar{\Lambda}^k + \bar{\gamma}_{kj} \hat{D}_i \bar{\Lambda}^k) + \frac{1}{2} \Pi^k (\Pi_{ijk} + \Pi_{jik}) \\% &\qquad+ \bar{\gamma}^{kl} (\Pi^m_{ki} \Pi_{jml} + \Pi^m_{kj} \Pi_{iml} + \Pi^m_{ik} \Pi_{mjl}) \end{align} """) par.set_parval_from_str('reference_metric::CoordSystem', 'Cartesian') par.set_parval_from_str('BSSN.BSSN_quantities::LeaveRicciSymbolic', 'True') rfm.reference_metric() Brhs.BSSN_RHSs() par.set_parval_from_str('BSSN.BSSN_quantities::LeaveRicciSymbolic', 'False') Bq.RicciBar__gammabarDD_dHatD__DGammaUDD__DGammaU() assert_equal( { 'h_rhsDD': h_rhsDD, 'cf_rhs': cf_rhs, 'trK_rhs': trK_rhs, 'Lambdabar_rhsU': Lambdabar_rhsU, 'a_rhsDD': a_rhsDD, 'RbarDD': RbarDD }, { 'h_rhsDD': Brhs.h_rhsDD, 'cf_rhs': Brhs.cf_rhs, 'trK_rhs': Brhs.trK_rhs, 'Lambdabar_rhsU': Brhs.Lambdabar_rhsU, 'a_rhsDD': Brhs.a_rhsDD, 'RbarDD': Bq.RbarDD })
def BSSN_RHSs__generate_symbolic_expressions( LapseCondition="OnePlusLog", ShiftCondition="GammaDriving2ndOrder_Covariant", enable_KreissOliger_dissipation=True, enable_stress_energy_source_terms=False, leave_Ricci_symbolic=True): ###################################### # START: GENERATE SYMBOLIC EXPRESSIONS starttime = print_msg_with_timing("BSSN_RHSs", msg="Symbolic", startstop="start") # Returns None if enable_stress_energy_source_terms==False; otherwise returns symb expressions for T4UU T4UU = register_stress_energy_source_terms_return_T4UU( enable_stress_energy_source_terms) # Evaluate BSSN RHSs: import BSSN.BSSN_quantities as Bq par.set_parval_from_str("BSSN.BSSN_quantities::LeaveRicciSymbolic", str(leave_Ricci_symbolic)) rhs.BSSN_RHSs() if enable_stress_energy_source_terms: import BSSN.BSSN_stress_energy_source_terms as Bsest Bsest.BSSN_source_terms_for_BSSN_RHSs(T4UU) rhs.trK_rhs += Bsest.sourceterm_trK_rhs for i in range(3): # Needed for Gamma-driving shift RHSs: rhs.Lambdabar_rhsU[i] += Bsest.sourceterm_Lambdabar_rhsU[i] # Needed for BSSN RHSs: rhs.lambda_rhsU[i] += Bsest.sourceterm_lambda_rhsU[i] for j in range(3): rhs.a_rhsDD[i][j] += Bsest.sourceterm_a_rhsDD[i][j] par.set_parval_from_str("BSSN.BSSN_gauge_RHSs::LapseEvolutionOption", LapseCondition) par.set_parval_from_str("BSSN.BSSN_gauge_RHSs::ShiftEvolutionOption", ShiftCondition) gaugerhs.BSSN_gauge_RHSs() # Can depend on above RHSs # Restore BSSN.BSSN_quantities::LeaveRicciSymbolic to False par.set_parval_from_str("BSSN.BSSN_quantities::LeaveRicciSymbolic", "False") # Add Kreiss-Oliger dissipation to the BSSN RHSs: if enable_KreissOliger_dissipation: thismodule = "KO_Dissipation" diss_strength = par.Cparameters( "REAL", thismodule, "diss_strength", 0.1 ) # *Bq.cf # *Bq.cf*Bq.cf*Bq.cf # cf**1 is found better than cf**4 over the long term. alpha_dKOD = ixp.declarerank1("alpha_dKOD") cf_dKOD = ixp.declarerank1("cf_dKOD") trK_dKOD = ixp.declarerank1("trK_dKOD") betU_dKOD = ixp.declarerank2("betU_dKOD", "nosym") vetU_dKOD = ixp.declarerank2("vetU_dKOD", "nosym") lambdaU_dKOD = ixp.declarerank2("lambdaU_dKOD", "nosym") aDD_dKOD = ixp.declarerank3("aDD_dKOD", "sym01") hDD_dKOD = ixp.declarerank3("hDD_dKOD", "sym01") for k in range(3): gaugerhs.alpha_rhs += diss_strength * alpha_dKOD[k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.cf_rhs += diss_strength * cf_dKOD[k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.trK_rhs += diss_strength * trK_dKOD[k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] for i in range(3): if "2ndOrder" in ShiftCondition: gaugerhs.bet_rhsU[ i] += diss_strength * betU_dKOD[i][k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] gaugerhs.vet_rhsU[ i] += diss_strength * vetU_dKOD[i][k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.lambda_rhsU[ i] += diss_strength * lambdaU_dKOD[i][k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] for j in range(3): rhs.a_rhsDD[i][ j] += diss_strength * aDD_dKOD[i][j][k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] rhs.h_rhsDD[i][ j] += diss_strength * hDD_dKOD[i][j][k] * rfm.ReU[ k] # ReU[k] = 1/scalefactor_orthog_funcform[k] # We use betaU as our upwinding control vector: Bq.BSSN_basic_tensors() betaU = Bq.betaU # END: GENERATE SYMBOLIC EXPRESSIONS ###################################### lhs_names = ["alpha", "cf", "trK"] rhs_exprs = [gaugerhs.alpha_rhs, rhs.cf_rhs, rhs.trK_rhs] for i in range(3): lhs_names.append("betU" + str(i)) rhs_exprs.append(gaugerhs.bet_rhsU[i]) lhs_names.append("lambdaU" + str(i)) rhs_exprs.append(rhs.lambda_rhsU[i]) lhs_names.append("vetU" + str(i)) rhs_exprs.append(gaugerhs.vet_rhsU[i]) for j in range(i, 3): lhs_names.append("aDD" + str(i) + str(j)) rhs_exprs.append(rhs.a_rhsDD[i][j]) lhs_names.append("hDD" + str(i) + str(j)) rhs_exprs.append(rhs.h_rhsDD[i][j]) # Sort the lhss list alphabetically, and rhss to match. # This ensures the RHSs are evaluated in the same order # they're allocated in memory: lhs_names, rhs_exprs = [ list(x) for x in zip( *sorted(zip(lhs_names, rhs_exprs), key=lambda pair: pair[0])) ] # Declare the list of lhrh's BSSN_RHSs_SymbExpressions = [] for var in range(len(lhs_names)): BSSN_RHSs_SymbExpressions.append( lhrh(lhs=gri.gfaccess("rhs_gfs", lhs_names[var]), rhs=rhs_exprs[var])) print_msg_with_timing("BSSN_RHSs", msg="Symbolic", startstop="stop", starttime=starttime) return [betaU, BSSN_RHSs_SymbExpressions]
def BSSN_gauge_RHSs(): # Step 1.d: Set spatial dimension (must be 3 for BSSN, as BSSN is # a 3+1-dimensional decomposition of the general # relativistic field equations) DIM = 3 # Step 1.e: Given the chosen coordinate system, set up # corresponding reference metric and needed # reference metric quantities # The following function call sets up the reference metric # and related quantities, including rescaling matrices ReDD, # ReU, and hatted quantities. rfm.reference_metric() # Step 1.f: Define needed BSSN quantities: # Declare scalars & tensors (in terms of rescaled BSSN quantities) Bq.BSSN_basic_tensors() Bq.betaU_derivs() # Declare BSSN_RHSs (excluding the time evolution equations for the gauge conditions) Brhs.BSSN_RHSs() # Step 2.a: The 1+log lapse condition: # \partial_t \alpha = \beta^i \alpha_{,i} - 2*\alpha*K # First import expressions from BSSN_quantities cf = Bq.cf trK = Bq.trK alpha = Bq.alpha betaU = Bq.betaU # Implement the 1+log lapse condition global alpha_rhs alpha_rhs = sp.sympify(0) if par.parval_from_str(thismodule + "::LapseEvolutionOption") == "OnePlusLog": alpha_rhs = -2 * alpha * trK alpha_dupD = ixp.declarerank1("alpha_dupD") for i in range(DIM): alpha_rhs += betaU[i] * alpha_dupD[i] # Step 2.b: Implement the harmonic slicing lapse condition elif par.parval_from_str(thismodule + "::LapseEvolutionOption") == "HarmonicSlicing": if par.parval_from_str( "BSSN.BSSN_quantities::EvolvedConformalFactor_cf") == "W": alpha_rhs = -3 * cf**(-4) * Brhs.cf_rhs elif par.parval_from_str( "BSSN.BSSN_quantities::EvolvedConformalFactor_cf") == "phi": alpha_rhs = 6 * sp.exp(6 * cf) * Brhs.cf_rhs else: print( "Error LapseEvolutionOption==HarmonicSlicing unsupported for EvolvedConformalFactor_cf!=(W or phi)" ) exit(1) # Step 2.c: Frozen lapse # \partial_t \alpha = 0 elif par.parval_from_str(thismodule + "::LapseEvolutionOption") == "Frozen": alpha_rhs = sp.sympify(0) else: print("Error: " + thismodule + "::LapseEvolutionOption == " + par.parval_from_str(thismodule + "::LapseEvolutionOption") + " not supported!") exit(1) # Step 3.a: Set \partial_t \beta^i # First import expressions from BSSN_quantities BU = Bq.BU betU = Bq.betU betaU_dupD = Bq.betaU_dupD # Define needed quantities beta_rhsU = ixp.zerorank1() B_rhsU = ixp.zerorank1() if par.parval_from_str( thismodule + "::ShiftEvolutionOption") == "GammaDriving2ndOrder_NoCovariant": # Step 3.a.i: Compute right-hand side of beta^i # * \partial_t \beta^i = \beta^j \beta^i_{,j} + B^i for i in range(DIM): beta_rhsU[i] += BU[i] for j in range(DIM): beta_rhsU[i] += betaU[j] * betaU_dupD[i][j] # Compute right-hand side of B^i: eta = par.Cparameters("REAL", thismodule, ["eta"]) # Step 3.a.ii: Compute right-hand side of B^i # * \partial_t B^i = \beta^j B^i_{,j} + 3/4 * \partial_0 \Lambda^i - eta B^i # Step 3.a.iii: Define BU_dupD, in terms of derivative of rescaled variable \bet^i BU_dupD = ixp.zerorank2() betU_dupD = ixp.declarerank2("betU_dupD", "nosym") for i in range(DIM): for j in range(DIM): BU_dupD[i][j] = betU_dupD[i][j] * rfm.ReU[i] + betU[ i] * rfm.ReUdD[i][j] # Step 3.a.iv: Compute \partial_0 \bar{\Lambda}^i = (\partial_t - \beta^i \partial_i) \bar{\Lambda}^j Lambdabar_partial0 = ixp.zerorank1() for i in range(DIM): Lambdabar_partial0[i] = Brhs.Lambdabar_rhsU[i] for i in range(DIM): for j in range(DIM): Lambdabar_partial0[j] += -betaU[i] * Brhs.LambdabarU_dupD[j][i] # Step 3.a.v: Evaluate RHS of B^i: for i in range(DIM): B_rhsU[i] += sp.Rational(3, 4) * Lambdabar_partial0[i] - eta * BU[i] for j in range(DIM): B_rhsU[i] += betaU[j] * BU_dupD[i][j] # Step 3.b: The right-hand side of the \partial_t \beta^i equation if par.parval_from_str( thismodule + "::ShiftEvolutionOption") == "GammaDriving2ndOrder_Covariant": # Step 3.b Option 2: \partial_t \beta^i = \left[\beta^j \bar{D}_j \beta^i\right] + B^{i} # First we need GammabarUDD, defined in Bq.gammabar__inverse_and_derivs() Bq.gammabar__inverse_and_derivs() GammabarUDD = Bq.GammabarUDD # Then compute right-hand side: # Term 1: \beta^j \beta^i_{,j} for i in range(DIM): for j in range(DIM): beta_rhsU[i] += betaU[j] * betaU_dupD[i][j] # Term 2: \beta^j \bar{\Gamma}^i_{mj} \beta^m for i in range(DIM): for j in range(DIM): for m in range(DIM): beta_rhsU[i] += betaU[j] * GammabarUDD[i][m][j] * betaU[m] # Term 3: B^i for i in range(DIM): beta_rhsU[i] += BU[i] if par.parval_from_str( thismodule + "::ShiftEvolutionOption") == "GammaDriving2ndOrder_Covariant": # Step 3.c: Covariant option: # \partial_t B^i = \beta^j \bar{D}_j B^i # + \frac{3}{4} ( \partial_t \bar{\Lambda}^{i} - \beta^j \bar{D}_j \bar{\Lambda}^{i} ) # - \eta B^{i} # = \beta^j B^i_{,j} + \beta^j \bar{\Gamma}^i_{mj} B^m # + \frac{3}{4}[ \partial_t \bar{\Lambda}^{i} # - \beta^j (\bar{\Lambda}^i_{,j} + \bar{\Gamma}^i_{mj} \bar{\Lambda}^m)] # - \eta B^{i} # Term 1, part a: First compute B^i_{,j} using upwinded derivative BU_dupD = ixp.zerorank2() betU_dupD = ixp.declarerank2("betU_dupD", "nosym") for i in range(DIM): for j in range(DIM): BU_dupD[i][j] = betU_dupD[i][j] * rfm.ReU[i] + betU[ i] * rfm.ReUdD[i][j] # Term 1: \beta^j B^i_{,j} for i in range(DIM): for j in range(DIM): B_rhsU[i] += betaU[j] * BU_dupD[i][j] # Term 2: \beta^j \bar{\Gamma}^i_{mj} B^m for i in range(DIM): for j in range(DIM): for m in range(DIM): B_rhsU[i] += betaU[j] * GammabarUDD[i][m][j] * BU[m] # Term 3: \frac{3}{4}\partial_t \bar{\Lambda}^{i} for i in range(DIM): B_rhsU[i] += sp.Rational(3, 4) * Brhs.Lambdabar_rhsU[i] # Term 4: -\frac{3}{4}\beta^j \bar{\Lambda}^i_{,j} for i in range(DIM): for j in range(DIM): B_rhsU[i] += -sp.Rational( 3, 4) * betaU[j] * Brhs.LambdabarU_dupD[i][j] # Term 5: -\frac{3}{4}\beta^j \bar{\Gamma}^i_{mj} \bar{\Lambda}^m for i in range(DIM): for j in range(DIM): for m in range(DIM): B_rhsU[i] += -sp.Rational(3, 4) * betaU[j] * GammabarUDD[ i][m][j] * Bq.LambdabarU[m] # Term 6: - \eta B^i # eta is a free parameter; we declare it here: eta = par.Cparameters("REAL", thismodule, ["eta"]) for i in range(DIM): B_rhsU[i] += -eta * BU[i] # Step 4: Rescale the BSSN gauge RHS quantities so that the evolved # variables may remain smooth across coord singularities global vet_rhsU, bet_rhsU vet_rhsU = ixp.zerorank1() bet_rhsU = ixp.zerorank1() for i in range(DIM): vet_rhsU[i] = beta_rhsU[i] / rfm.ReU[i] bet_rhsU[i] = B_rhsU[i] / rfm.ReU[i]