Skip to content

Commit dd2ec06

Browse files
authored
compressible: add a get_external_sources method (#290)
this will make it easier to do external sources problem-by-problem For the conservative update, we now do a predictor-corrector, in the same fashion as Castro: * U^{n+1,*} = U^n - dt [div{F}]^{n+1/2} + dt S^n * S^{n+1} = S(U^{n+1,*}) * U^{n+1} = U^{n+1,*} + dt/2 (S^{n+1} - S^n) and we construct the gravity part of S^{n+1} to give us the implicit update.
1 parent a08adc7 commit dd2ec06

File tree

3 files changed

+100
-46
lines changed

3 files changed

+100
-46
lines changed

pyro/compressible/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66

77
__all__ = ["simulation"]
88

9-
from .simulation import Simulation, Variables, cons_to_prim, prim_to_cons
9+
from .simulation import (Simulation, Variables, cons_to_prim,
10+
get_external_sources, prim_to_cons)

pyro/compressible/simulation.py

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,60 @@ def prim_to_cons(q, gamma, ivars, myg):
9191
return U
9292

9393

94+
def get_external_sources(t, dt, U, ivars, rp, myg, *, U_old=None):
95+
"""compute the external sources, including gravity"""
96+
97+
_ = t # maybe unused
98+
99+
S = myg.scratch_array(nvar=ivars.nvar)
100+
101+
grav = rp.get_param("compressible.grav")
102+
103+
if U_old is None:
104+
# we are just computing the sources from the current state U
105+
106+
if myg.coord_type == 1:
107+
# gravity points in the radial direction for spherical
108+
S[:, :, ivars.ixmom] = U[:, :, ivars.idens] * grav
109+
S[:, :, ivars.iener] = U[:, :, ivars.ixmom] * grav
110+
111+
S[:, :, ivars.ixmom] += U[:, :, ivars.iymom]**2 / (U[:, :, ivars.idens] * myg.x2d)
112+
S[:, :, ivars.iymom] += -U[:, :, ivars.ixmom] * U[:, :, ivars.iymom] / U[:, :, ivars.idens]
113+
114+
else:
115+
# gravity points in the vertical (y) direction for Cartesian
116+
S[:, :, ivars.iymom] = U[:, :, ivars.idens] * grav
117+
S[:, :, ivars.iener] = U[:, :, ivars.iymom] * grav
118+
119+
else:
120+
# we want to compute gravity using the time-updated momentum
121+
# we assume that U is an approximation to U^{n+1}, which includes
122+
# a full dt * S_old
123+
124+
if myg.coord_type == 1:
125+
S[:, :, ivars.ixmom] = U[:, :, ivars.idens] * grav
126+
S_old_xmom = U_old[:, :, ivars.idens] * grav
127+
128+
# we want the corrected xmom that has a time-centered source
129+
xmom_new = U[:, :, ivars.ixmom] + 0.5 * dt * (S[:, :, ivars.ixmom] - S_old_xmom)
130+
131+
S[:, :, ivars.iener] = xmom_new * grav
132+
133+
S[:, :, ivars.ixmom] += U[:, :, ivars.iymom]**2 / (U[:, :, ivars.idens] * myg.x2d)
134+
S[:, :, ivars.iymom] += -U[:, :, ivars.ixmom] * U[:, :, ivars.iymom] / U[:, :, ivars.idens]
135+
136+
else:
137+
S[:, :, ivars.iymom] = U[:, :, ivars.idens] * grav
138+
S_old_ymom = U_old[:, :, ivars.idens] * grav
139+
140+
# we want the corrected ymom that has a time-centered source
141+
ymom_new = U[:, :, ivars.iymom] + 0.5 * dt * (S[:, :, ivars.iymom] - S_old_ymom)
142+
143+
S[:, :, ivars.iener] = ymom_new * grav
144+
145+
return S
146+
147+
94148
class Simulation(NullSimulation):
95149
"""The main simulation class for the corner transport upwind
96150
compressible hydrodynamics solver
@@ -207,7 +261,6 @@ def evolve(self):
207261
ymom = self.cc_data.get_var("y-momentum")
208262
ener = self.cc_data.get_var("energy")
209263

210-
grav = self.rp.get_param("compressible.grav")
211264
gamma = self.rp.get_param("eos.gamma")
212265

213266
myg = self.cc_data.grid
@@ -268,9 +321,12 @@ def evolve(self):
268321
self.cc_data, self.rp,
269322
self.ivars)
270323

271-
old_dens = dens.copy()
272-
old_xmom = xmom.copy()
273-
old_ymom = ymom.copy()
324+
# save the old state (without ghost cells)
325+
U_old = myg.scratch_array(nvar=self.ivars.nvar)
326+
U_old[:, :, self.ivars.idens] = dens[:, :]
327+
U_old[:, :, self.ivars.ixmom] = xmom[:, :]
328+
U_old[:, :, self.ivars.iymom] = ymom[:, :]
329+
U_old[:, :, self.ivars.iener] = ener[:, :]
274330

275331
# Conservative update
276332

@@ -286,32 +342,40 @@ def evolve(self):
286342

287343
# Now apply external sources
288344

289-
# For SphericalPolar (coord_type == 1):
290-
# There are gravity (external) sources,
291-
# geometric terms due to local unit vectors, and pressure gradient
292-
# since we don't include pressure in xmom and ymom fluxes
293-
# due to incompatible divergence and gradient in non-Cartesian geometry
294-
295-
# For Cartesian2d (coord_type == 0):
296-
# There is only gravity sources.
345+
# For SphericalPolar (coord_type == 1) there are pressure
346+
# gradients since we don't include pressure in xmom and ymom
347+
# fluxes
297348

298349
if myg.coord_type == 1:
299-
xmom.v()[:, :] += 0.5*self.dt * \
300-
((dens.v() + old_dens.v())*grav +
301-
(ymom.v()**2 / dens.v() +
302-
old_ymom.v()**2 / old_dens.v()) / myg.x2d.v()) - \
303-
self.dt * (qx.ip(1, n=self.ivars.ip) - qx.v(n=self.ivars.ip)) / myg.Lx.v()
350+
xmom.v()[:, :] -= self.dt * (qx.ip(1, n=self.ivars.ip) -
351+
qx.v(n=self.ivars.ip)) / myg.Lx.v()
352+
ymom.v()[:, :] -= self.dt * (qy.jp(1, n=self.ivars.ip) -
353+
qy.v(n=self.ivars.ip)) / myg.Ly.v()
354+
355+
# now the external sources (including gravity). We are going
356+
# to do a predictor-corrector here:
357+
#
358+
# * compute old sources using old state: S^n = S(U^n)
359+
# * update state full dt using old sources: U^{n+1,*} += dt * S^n
360+
# * compute new sources using this updated state: S^{n+1) = S(U^{n+1,*})
361+
# * correct: U^{n+1} = U^{n+1,*} + dt/2 (S^{n+1} - S^n)
362+
363+
S_old = get_external_sources(self.cc_data.t, self.dt, U_old,
364+
self.ivars, self.rp, myg)
304365

305-
ymom.v()[:, :] += 0.5*self.dt * \
306-
(-xmom.v()*ymom.v() / dens.v() -
307-
old_xmom.v()*old_ymom.v() / old_dens.v()) / myg.x2d.v() - \
308-
self.dt * (qy.jp(1, n=self.ivars.ip) - qy.v(n=self.ivars.ip)) / myg.Ly.v()
366+
for n in range(self.ivars.nvar):
367+
var = self.cc_data.get_var_by_index(n)
368+
var.v()[:, :] += self.dt * S_old.v(n=n)
309369

310-
ener.v()[:, :] += 0.5*self.dt*(xmom.v() + old_xmom.v())*grav
370+
# now get the new time source
311371

312-
else:
313-
ymom.v()[:, :] += 0.5*self.dt*(dens.v() + old_dens.v())*grav
314-
ener.v()[:, :] += 0.5*self.dt*(ymom.v() + old_ymom.v())*grav
372+
S_new = get_external_sources(self.cc_data.t, self.dt, self.cc_data.data,
373+
self.ivars, self.rp, myg, U_old=U_old)
374+
375+
# and correct
376+
for n in range(self.ivars.nvar):
377+
var = self.cc_data.get_var_by_index(n)
378+
var.v()[:, :] += 0.5 * self.dt * (S_new.v(n=n) - S_old.v(n=n))
315379

316380
if self.particles is not None:
317381
self.particles.update_particles(self.dt)

pyro/compressible/unsplit_fluxes.py

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -283,35 +283,24 @@ def apply_source_terms(U_xl, U_xr, U_yl, U_yr,
283283

284284
myg = my_data.grid
285285

286-
dens = my_data.get_var("density")
287-
xmom = my_data.get_var("x-momentum")
288-
ymom = my_data.get_var("y-momentum")
289286
pres = my_data.get_var("pressure")
290287

291288
dens_src = my_aux.get_var("dens_src")
292289
xmom_src = my_aux.get_var("xmom_src")
293290
ymom_src = my_aux.get_var("ymom_src")
294291
E_src = my_aux.get_var("E_src")
295292

296-
grav = rp.get_param("compressible.grav")
293+
U_src = comp.get_external_sources(my_data.t, dt, my_data.data, ivars, rp, myg)
297294

298-
# Calculate external source (gravity), geometric, and pressure terms
299-
if myg.coord_type == 1:
300-
# assume gravity points in r-direction in spherical.
301-
dens_src.v()[:, :] = 0.0
302-
xmom_src.v()[:, :] = dens.v()*grav + \
303-
ymom.v()**2 / (dens.v()*myg.x2d.v()) - \
304-
(pres.ip(1) - pres.v()) / myg.Lx.v()
305-
ymom_src.v()[:, :] = -(pres.jp(1) - pres.v()) / myg.Ly.v() - \
306-
xmom.v()*ymom.v() / (dens.v()*myg.x2d.v())
307-
E_src.v()[:, :] = xmom.v()*grav
295+
dens_src[:, :] = U_src[:, :, ivars.idens]
296+
xmom_src[:, :] = U_src[:, :, ivars.ixmom]
297+
ymom_src[:, :] = U_src[:, :, ivars.iymom]
298+
E_src[:, :] = U_src[:, :, ivars.iener]
308299

309-
else:
310-
# assume gravity points in y-direction in cartesian
311-
dens_src.v()[:, :] = 0.0
312-
xmom_src.v()[:, :] = 0.0
313-
ymom_src.v()[:, :] = dens.v()*grav
314-
E_src.v()[:, :] = ymom.v()*grav
300+
# apply non-conservative pressure gradient
301+
if myg.coord_type == 1:
302+
xmom_src.v()[:, :] += -(pres.ip(1) - pres.v()) / myg.Lx.v()
303+
ymom_src.v()[:, :] += -(pres.jp(1) - pres.v()) / myg.Ly.v()
315304

316305
my_aux.fill_BC("dens_src")
317306
my_aux.fill_BC("xmom_src")

0 commit comments

Comments
 (0)