Skip to content

Commit 888a86a

Browse files
authored
add some protection against negatives in 4th order (#309)
this now uses a mask when we convert from averages to centers. If either density or internal energy become negative, then we flag the mask for that zone. We then go back and reset all of the flagged zones to the cell averages -- this will drop the method to 2nd order in that zone, but its better than having negative density because of a steep gradient.
1 parent 0c96684 commit 888a86a

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

pyro/compressible_fv4/fluxes.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ def fluxes(myd, rp, ivars):
5757
U_cc[:, :, ivars.iymom] = myd.to_centers("y-momentum")
5858
U_cc[:, :, ivars.iener] = myd.to_centers("energy")
5959

60+
# the mask will be 1 in any zone where the density or energy
61+
# is unphysical do to the conversion from averages to centers
62+
63+
rhoe = U_cc[..., ivars.iener] - 0.5 * (U_cc[..., ivars.ixmom]**2 +
64+
U_cc[..., ivars.iymom]**2) / U_cc[..., ivars.idens]
65+
66+
mask = myg.scratch_array(dtype=np.uint8)
67+
mask[:, :] = np.where(np.logical_or(U_cc[:, :, ivars.idens] < 0, rhoe < 0),
68+
1, 0)
69+
70+
U_cc[..., ivars.idens] = np.where(mask == 1, U_avg[..., ivars.idens], U_cc[..., ivars.idens])
71+
U_cc[..., ivars.ixmom] = np.where(mask == 1, U_avg[..., ivars.ixmom], U_cc[..., ivars.ixmom])
72+
U_cc[..., ivars.iymom] = np.where(mask == 1, U_avg[..., ivars.iymom], U_cc[..., ivars.iymom])
73+
U_cc[..., ivars.iener] = np.where(mask == 1, U_avg[..., ivars.iener], U_cc[..., ivars.iener])
74+
6075
# compute the primitive variables of both the cell-center and averages
6176
q_bar = comp.cons_to_prim(U_avg, gamma, ivars, myd.grid)
6277
q_cc = comp.cons_to_prim(U_cc, gamma, ivars, myd.grid)
@@ -66,6 +81,15 @@ def fluxes(myd, rp, ivars):
6681
for n in range(ivars.nq):
6782
q_avg.v(n=n, buf=3)[:, :] = q_cc.v(n=n, buf=3) + myg.dx**2/24.0 * q_bar.lap(n=n, buf=3)
6883

84+
# enforce positivity
85+
q_avg.v(n=ivars.irho, buf=3)[:, :] = np.where(q_avg.v(n=ivars.irho, buf=3) > 0,
86+
q_avg.v(n=ivars.irho, buf=3),
87+
q_cc.v(n=ivars.irho, buf=3))
88+
89+
q_avg.v(n=ivars.ip, buf=3)[:, :] = np.where(q_avg.v(n=ivars.ip, buf=3) > 0,
90+
q_avg.v(n=ivars.ip, buf=3),
91+
q_cc.v(n=ivars.ip, buf=3))
92+
6993
# flattening -- there is a single flattening coefficient (xi) for all directions
7094
use_flattening = rp.get_param("compressible.use_flattening")
7195

pyro/mesh/fv.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
44
"""
55

6+
import numpy as np
7+
68
from pyro.mesh.patch import CellCenterData2d
79

810

@@ -13,14 +15,18 @@ class FV2d(CellCenterData2d):
1315
1416
"""
1517

16-
def to_centers(self, name):
18+
def to_centers(self, name, is_positive=False):
1719
""" convert variable name from an average to cell-centers """
1820

1921
a = self.get_var(name)
2022
c = self.grid.scratch_array()
2123
ng = self.grid.ng
2224
c[:, :] = a[:, :]
2325
c.v(buf=ng-1)[:, :] = a.v(buf=ng-1) - self.grid.dx**2*a.lap(buf=ng-1)/24.0
26+
27+
if is_positive:
28+
c.v(buf=ng-1)[:, :] = np.where(c.v(buf=ng-1) >= 0.0, c.v(buf=ng-1), a.v(buf=ng-1))
29+
2430
return c
2531

2632
def from_centers(self, name):

pyro/mesh/patch.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,15 @@ def __init__(self, nx, ny, *, ng=1,
146146
self.xr2d = ArrayIndexer(d=xr2d, grid=self)
147147
self.yr2d = ArrayIndexer(d=yr2d, grid=self)
148148

149-
def scratch_array(self, *, nvar=1):
149+
def scratch_array(self, *, nvar=1, dtype=np.float64):
150150
"""
151151
return a standard numpy array dimensioned to have the size
152152
and number of ghostcells as the parent grid
153153
"""
154154
if nvar == 1:
155-
_tmp = np.zeros((self.qx, self.qy), dtype=np.float64)
155+
_tmp = np.zeros((self.qx, self.qy), dtype=dtype)
156156
else:
157-
_tmp = np.zeros((self.qx, self.qy, nvar), dtype=np.float64)
157+
_tmp = np.zeros((self.qx, self.qy, nvar), dtype=dtype)
158158
return ArrayIndexer(d=_tmp, grid=self)
159159

160160
def coarse_like(self, N):

0 commit comments

Comments
 (0)