Source code for pyro.compressible_sdc.simulation
"""The routines that implement the 4th-order compressible scheme,
using SDC time integration
"""
from pyro import compressible_fv4
from pyro.mesh import patch
from pyro.util import msg
[docs]
class Simulation(compressible_fv4.Simulation):
"""Drive the 4th-order compressible solver with SDC time integration"""
[docs]
def sdc_integral(self, m_start, m_end, As):
"""Compute the integral over the sources from m to m+1 with a
Simpson's rule"""
integral = self.cc_data.grid.scratch_array(nvar=self.ivars.nvar)
if m_start == 0 and m_end == 1:
for n in range(self.ivars.nvar):
integral.v(n=n)[:, :] = self.dt/24.0 * (5.0*As[0].v(n=n) + 8.0*As[1].v(n=n) - As[2].v(n=n))
elif m_start == 1 and m_end == 2:
for n in range(self.ivars.nvar):
integral.v(n=n)[:, :] = self.dt/24.0 * (-As[0].v(n=n) + 8.0*As[1].v(n=n) + 5.0*As[2].v(n=n))
else:
msg.fail("invalid quadrature range")
return integral
[docs]
def evolve(self):
"""
Evolve the equations of compressible hydrodynamics through a
timestep dt.
"""
tm_evolve = self.tc.timer("evolve")
tm_evolve.begin()
myd = self.cc_data
# we need the solution at 3 time points and at the old and
# current iteration (except for m = 0 -- that doesn't change).
# This copy will initialize the the solution at all time nodes
# with the current (old) solution.
U_kold = []
U_kold.append(patch.cell_center_data_clone(self.cc_data))
U_kold.append(patch.cell_center_data_clone(self.cc_data))
U_kold.append(patch.cell_center_data_clone(self.cc_data))
U_knew = []
U_knew.append(U_kold[0])
U_knew.append(patch.cell_center_data_clone(self.cc_data))
U_knew.append(patch.cell_center_data_clone(self.cc_data))
# loop over iterations
for _ in range(1, 5):
# we need the advective term at all time nodes at the old
# iteration -- we'll compute this now
A_kold = []
for m in range(3):
_tmp = self.substep(U_kold[m])
A_kold.append(_tmp)
# loop over the time nodes and update
for m in range(2):
# update m to m+1 for knew
# compute A(U_m^{k+1})
A_knew = self.substep(U_knew[m])
# compute the integral over A at the old iteration
integral = self.sdc_integral(m, m+1, A_kold)
# and the final update
for n in range(self.ivars.nvar):
U_knew[m+1].data.v(n=n)[:, :] = U_knew[m].data.v(n=n) + \
0.5*self.dt * (A_knew.v(n=n) - A_kold[m].v(n=n)) + integral.v(n=n)
# fill ghost cells
U_knew[m+1].fill_BC_all()
# store the current iteration as the old iteration
for m in range(1, 3):
U_kold[m].data[:, :, :] = U_knew[m].data[:, :, :]
# store the new solution
self.cc_data.data[:, :, :] = U_knew[-1].data[:, :, :]
if self.particles is not None:
self.particles.update_particles(self.dt)
# increment the time
myd.t += self.dt
self.n += 1
tm_evolve.end()