Skip to content

Commit e958e9c

Browse files
committed
Z4c: Make evolveA, evolveB evolution stationary for Kerr-Schild
1 parent aebab6d commit e958e9c

7 files changed

Lines changed: 343 additions & 110 deletions

File tree

Z4c/param.ccl

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,23 +51,29 @@ CCTK_REAL eta "eta" STEERABLE=always
5151

5252
# Integrated ("second order") gauge conditions.
5353
#
54-
# With these off, the gauge is the usual first order one:
55-
# d/dt alpha = -alpha f_mu_L Khat
56-
# d/dt beta^i = f_mu_S Gamt^i - eta beta^i
54+
# With these off, the gauge is the usual first order one, advected along the
55+
# shift:
56+
# d/dt alpha = -alpha f_mu_L Khat + beta^i d_i alpha
57+
# d/dt beta^i = f_mu_S Gamt^i - eta beta^i + beta^j d_j beta^i
5758
#
5859
# With them on, d/dt alpha and d/dt beta^i become evolved variables A and B^i
59-
# (group dtalphaG / dtbetaG), obeying
60+
# (groups dtalphaG / dtbetaG), the complete coordinate time derivatives:
6061
# d/dt alpha = A
61-
# d/dt A = d/dt (-alpha f_mu_L Khat) - alphaDriver (A + alpha f_mu_L Khat)
62-
# and correspondingly for the shift. The driver terms relax A and B^i towards
63-
# the first order values; with a driver of zero and A, B^i initialised to
64-
# those values the first order gauge is reproduced exactly, which is what the
65-
# unit test checks.
62+
# d/dt A = d/dt (-alpha f_mu_L Khat + beta^i d_i alpha)
63+
# - alphaDriver (A + alpha f_mu_L Khat - beta^i d_i alpha)
64+
# and correspondingly for the shift, where d/dt on the right hand side is the
65+
# complete time derivative (d/dt alpha = A, d/dt beta^i = B^i, and
66+
# d/dt Khat = Kh_rhs + beta^i d_i Khat). The driver terms relax A and B^i
67+
# towards the first order values; with a driver of zero and A, B^i initialised
68+
# to those values the first order gauge is reproduced exactly.
6669
#
6770
# The point of the integrated form is that A and B^i can be initialised from
6871
# ADMBaseX::dtlapse and ADMBaseX::dtshift. For stationary initial data in
69-
# horizon-penetrating coordinates those are zero, so the gauge starts at rest
70-
# instead of being kicked by a nonzero -alpha f_mu_L Khat at t = 0.
72+
# horizon-penetrating coordinates those are zero, and since d/dt Khat and
73+
# d/dt Gamt^i vanish as well, every right hand side vanishes: the data stay
74+
# stationary up to truncation error instead of the gauge being kicked by a
75+
# nonzero -alpha f_mu_L Khat at t = 0. A nonzero driver re-introduces that
76+
# kick, since the first order values are not zero for such data.
7177

7278
BOOLEAN evolveA "Evolve A = d/dt alpha instead of setting it algebraically"
7379
{
@@ -97,6 +103,48 @@ CCTK_REAL alphaG_floor "Floor for alphaG" STEERABLE=always
97103
(0:* :: ""
98104
} 1.0e-10
99105

106+
# Clamping of extreme values. Kerr-Schild data with a "stuffed" interior
107+
# collapse there in finite coordinate time when the lapse does not collapse
108+
# with them (the stuffed shift makes Khat ~ 1/(alpha rtilde(0)), and
109+
# d/dt K ~ alpha K^2). Clamping bounds that garbage: it acts only where values
110+
# are extreme, which for such data is inside the horizon, where any
111+
# modification is acceptable; a healthy exterior never reaches the bounds.
112+
# Clamps introduce kinks, which the Kreiss-Oliger dissipation smooths.
113+
114+
CCTK_REAL alpha_max "Ceiling for the lapse alpha; 0 disables" STEERABLE=always
115+
{
116+
0.0 :: "disabled"
117+
(0.0:* :: "clamp alpha to at most this value"
118+
} 0.0
119+
120+
CCTK_REAL clamp_max "Clamp |Khat|, |Atilde_ij|, |Gamma_tilde^i|, |Theta|, |A| and |B^i| (all of dimension 1/M) to at most this value; 0 disables" STEERABLE=always
121+
{
122+
0.0 :: "disabled"
123+
(0.0:* :: "clamp to this value"
124+
} 0.0
125+
126+
# Once the lapse has collapsed inside, only the shift-driven terms remain
127+
# active there; an unbounded shift then drives the conformal metric through
128+
# the Lie-derivative terms. These two bound that path.
129+
130+
CCTK_REAL beta_max "Clamp |beta^i| (each component) to at most this value; 0 disables" STEERABLE=always
131+
{
132+
0.0 :: "disabled"
133+
(0.0:* :: "clamp to this value"
134+
} 0.0
135+
136+
CCTK_REAL gammat_max "Clamp |gamma_tilde_ij - delta_ij| (each component) to at most this value, before and after det gamma_tilde = 1 is enforced; where delta + gamma_tilde is not positive definite it is reset to flat; 0 disables" STEERABLE=always
137+
{
138+
0.0 :: "disabled"
139+
(0.0:* :: "clamp to this value"
140+
} 0.0
141+
142+
CCTK_REAL chi_max "Ceiling for chi (the physical metric is gamma_tilde / chi); 0 disables" STEERABLE=always
143+
{
144+
0.0 :: "disabled"
145+
(0.0:* :: "clamp chi to at most this value"
146+
} 0.0
147+
100148
CCTK_REAL epsdiss "Dissipation coefficient <arXiv:gr-qc/0610128>" STEERABLE=always
101149
{
102150
0.0:* :: ""

Z4c/schedule.ccl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,24 @@ SCHEDULE Z4c_Enforce IN Z4c_PostStepGroup
147147
LANG: C
148148
READS: chi(interior)
149149
READS: gamma_tilde(interior)
150+
READS: K_hat(interior)
150151
READS: A_tilde(interior)
152+
READS: Gam_tilde(interior)
153+
READS: Theta(interior)
151154
READS: alphaG(interior)
155+
READS: betaG(interior)
156+
READS: dtalphaG(interior)
157+
READS: dtbetaG(interior)
152158
WRITES: chi(interior)
153159
WRITES: gamma_tilde(interior)
160+
WRITES: K_hat(interior)
154161
WRITES: A_tilde(interior)
162+
WRITES: Gam_tilde(interior)
163+
WRITES: Theta(interior)
155164
WRITES: alphaG(interior)
165+
WRITES: betaG(interior)
166+
WRITES: dtalphaG(interior)
167+
WRITES: dtbetaG(interior)
156168
SYNC: chi
157169
SYNC: gamma_tilde
158170
SYNC: K_hat

Z4c/src/adm.cxx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,16 @@ extern "C" void Z4c_ADM(CCTK_ARGUMENTS) {
133133
nvtxRangeEnd(range);
134134
#endif
135135

136-
// vars.dtalpha and vars.dtbeta are only the source terms of the gauge
137-
// conditions. The conditions themselves are advected along the shift,
136+
// Without evolveA, vars.dtalpha is only the source term of the lapse
137+
// condition. The condition itself is advected along the shift,
138138
//
139139
// d/dt alpha = -alpha f_mu_L Khat + beta^i d_i alpha
140140
//
141-
// and correspondingly for the shift, so ADMBaseX::dtlapse and dtshift are
142-
// wrong by beta^i d_i alpha (a few percent near a black hole horizon)
143-
// unless that term is added here as well. It is added for both gauges: with
144-
// evolveA the stored value is A, and the lapse is still advected on top of
145-
// it.
141+
// and correspondingly for the shift, so ADMBaseX::dtlapse and dtshift would
142+
// be wrong by beta^i d_i alpha (a few percent near a black hole horizon)
143+
// unless that term is added here as well. With evolveA the stored value is
144+
// A, which is the complete d/dt alpha (rhs.cxx does not advect alphaG on
145+
// top of it), so nothing is added.
146146
//
147147
// Kreiss-Oliger dissipation is deliberately NOT added. It is applied to the
148148
// evolved right hand sides in rhs.cxx because it stabilises the discrete
@@ -155,10 +155,12 @@ extern "C" void Z4c_ADM(CCTK_ARGUMENTS) {
155155
// applies the configured CarpetX outer boundary condition; only with
156156
// CarpetX::boundary_* = "none" does the outer boundary layer keep the
157157
// source term alone.
158-
apply_upwind(cctkGH, gf_alphaG1, gf_betaG1, gf_dtalp1);
158+
if (!evolveA)
159+
apply_upwind(cctkGH, gf_alphaG1, gf_betaG1, gf_dtalp1);
159160

160-
for (int a = 0; a < 3; ++a)
161-
apply_upwind(cctkGH, gf_betaG1(a), gf_betaG1, gf_dtbeta1(a));
161+
if (!evolveB)
162+
for (int a = 0; a < 3; ++a)
163+
apply_upwind(cctkGH, gf_betaG1(a), gf_betaG1, gf_dtbeta1(a));
162164
}
163165

164166
} // namespace Z4c

Z4c/src/adm2.cxx

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -246,25 +246,29 @@ extern "C" void Z4c_ADM2(CCTK_ARGUMENTS) {
246246
// beta^k d_k K_ij, which is added below with apply_upwind.
247247
gf_dtk1.store(mask, index1, vars.K_rhs);
248248

249-
// Z4c_ADM reports the advected gauge conditions,
249+
// Z4c_ADM reports the complete time derivatives of lapse and shift,
250250
//
251-
// D = d/dt alpha = S + beta^i d_i alpha
252-
// D^a = d/dt beta^a = S^a + beta^j d_j beta^a
251+
// D = d/dt alpha, D^a = d/dt beta^a.
253252
//
254-
// so their time derivatives are
253+
// Without evolveA, D = S + beta^i d_i alpha with the source
254+
// S = -alpha f_mu_L Khat, so
255255
//
256256
// d/dt D = d/dt S + (d/dt beta^i) d_i alpha + beta^i d_i D
257257
// d/dt D^a = d/dt S^a + (d/dt beta^j) d_j beta^a + beta^j d_j D^a
258258
//
259-
// z4c_vars' dtalpha_target_rhs and dtbeta_target_rhs cannot be used
260-
// for the d/dt S terms: they differentiate the sources using the
261-
// pre-advection right hand sides held by z4c_vars. The sources
262-
// are recomputed here from the advected derivatives instead. Khat and
263-
// Gamt^i are advected with the centred derivatives that z4c_vars
264-
// carries rather than the upwinded ones rhs.cxx uses, and Kreiss-
265-
// Oliger dissipation is excluded throughout, so these remain the
266-
// derivatives of the continuum gauge conditions rather than of the
267-
// discrete update.
259+
// where d/dt S needs the complete d/dt Khat = Kh_rhs + beta^i d_i Khat.
260+
// Khat and Gamt^i are advected with the centred derivatives that
261+
// z4c_vars carries rather than the upwinded ones rhs.cxx uses, and
262+
// Kreiss-Oliger dissipation is excluded throughout, so these remain
263+
// the derivatives of the continuum gauge conditions rather than of the
264+
// discrete update. The beta^i d_i D term is added below with
265+
// apply_upwind.
266+
//
267+
// With evolveA, D = A and d/dt D = A_rhs + beta^i d_i A: z4c_vars'
268+
// A_rhs is the complete d/dt of the advective lapse condition,
269+
// (d/dt beta^i) d_i alpha included, except for the advection of A
270+
// itself, which is added below with apply_upwind. Likewise for the
271+
// shift.
268272
const vreal D = gf_dtalp1(mask, index1);
269273
const vec<vreal, 3> Da = gf_dtbeta1(mask, index1);
270274

@@ -278,27 +282,23 @@ extern "C" void Z4c_ADM2(CCTK_ARGUMENTS) {
278282
});
279283
});
280284

281-
// With evolveA / evolveB the source is the evolved A (B^i), whose
282-
// full time derivative is A_rhs plus the advection term beta^i d_i A
283-
// that rhs.cxx adds; that advection term is added below with
284-
// apply_upwind.
285-
const vreal dS =
285+
const vreal dt2alp =
286286
evolveA ? vars.A_rhs
287-
: -f_mu_L * (D * vars.Kh + (1 + vars.alphaG) * dtKh);
288-
289-
const vec<vreal, 3> dSa([&](int a) ARITH_INLINE {
290-
return evolveB ? vars.B_rhs(a) : f_mu_S * dtGamt(a) - eta * Da(a);
287+
: -f_mu_L * (D * vars.Kh + (1 + vars.alphaG) * dtKh) +
288+
sum<3>([&](int i) ARITH_INLINE {
289+
return Da(i) * vars.dalphaG(i);
290+
});
291+
292+
const vec<vreal, 3> dt2beta([&](int a) ARITH_INLINE {
293+
return evolveB ? vars.B_rhs(a)
294+
: f_mu_S * dtGamt(a) - eta * Da(a) +
295+
sum<3>([&](int j) ARITH_INLINE {
296+
return Da(j) * vars.dbetaG(a)(j);
297+
});
291298
});
292299

293-
gf_dt2alp1.store(mask, index1, dS + sum<3>([&](int i) ARITH_INLINE {
294-
return Da(i) * vars.dalphaG(i);
295-
}));
296-
297-
gf_dt2beta1.store(mask, index1, vec<vreal, 3>([&](int a) ARITH_INLINE {
298-
return dSa(a) + sum<3>([&](int j) ARITH_INLINE {
299-
return Da(j) * vars.dbetaG(a)(j);
300-
});
301-
}));
300+
gf_dt2alp1.store(mask, index1, dt2alp);
301+
gf_dt2beta1.store(mask, index1, dt2beta);
302302
});
303303
#ifdef __CUDACC__
304304
nvtxRangeEnd(range);
@@ -313,15 +313,18 @@ extern "C" void Z4c_ADM2(CCTK_ARGUMENTS) {
313313
for (int b = a; b < 3; ++b)
314314
apply_upwind(cctkGH, gf_k1(a, b), gf_betaG1, gf_dtk1(a, b));
315315

316-
// beta^i d_i D and beta^j d_j D^a
317-
apply_upwind(cctkGH, gf_dtalp1, gf_betaG1, gf_dt2alp1);
316+
// beta^i d_i D and beta^j d_j D^a, completing d/dt D and d/dt D^a when A,
317+
// B^i are not evolved
318+
if (!evolveA)
319+
apply_upwind(cctkGH, gf_dtalp1, gf_betaG1, gf_dt2alp1);
318320

319-
for (int a = 0; a < 3; ++a)
320-
apply_upwind(cctkGH, gf_dtbeta1(a), gf_betaG1, gf_dt2beta1(a));
321+
if (!evolveB)
322+
for (int a = 0; a < 3; ++a)
323+
apply_upwind(cctkGH, gf_dtbeta1(a), gf_betaG1, gf_dt2beta1(a));
321324

322-
// With evolveA / evolveB the evolved A and B^i are themselves advected in
323-
// rhs.cxx, so d/dt A = A_rhs + beta^i d_i A enters d/dt D; the main loop
324-
// stored only A_rhs. Mirrors the evolveA / evolveB guards in rhs.cxx.
325+
// With evolveA / evolveB, D = A and D^a = B^a, which are advected in
326+
// rhs.cxx, so d/dt D = A_rhs + beta^i d_i A; the main loop stored only
327+
// A_rhs. Mirrors the evolveA / evolveB guards in rhs.cxx.
325328
if (evolveA)
326329
apply_upwind(cctkGH, gf_A1, gf_betaG1, gf_dt2alp1);
327330

0 commit comments

Comments
 (0)