@@ -91,6 +91,60 @@ def prim_to_cons(q, gamma, ivars, myg):
91
91
return U
92
92
93
93
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
+
94
148
class Simulation (NullSimulation ):
95
149
"""The main simulation class for the corner transport upwind
96
150
compressible hydrodynamics solver
@@ -207,7 +261,6 @@ def evolve(self):
207
261
ymom = self .cc_data .get_var ("y-momentum" )
208
262
ener = self .cc_data .get_var ("energy" )
209
263
210
- grav = self .rp .get_param ("compressible.grav" )
211
264
gamma = self .rp .get_param ("eos.gamma" )
212
265
213
266
myg = self .cc_data .grid
@@ -268,9 +321,12 @@ def evolve(self):
268
321
self .cc_data , self .rp ,
269
322
self .ivars )
270
323
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 [:, :]
274
330
275
331
# Conservative update
276
332
@@ -286,32 +342,40 @@ def evolve(self):
286
342
287
343
# Now apply external sources
288
344
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
297
348
298
349
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 )
304
365
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 )
309
369
310
- ener . v ()[:, :] += 0.5 * self . dt * ( xmom . v () + old_xmom . v ()) * grav
370
+ # now get the new time source
311
371
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 ))
315
379
316
380
if self .particles is not None :
317
381
self .particles .update_particles (self .dt )
0 commit comments