Source code for pyro.burgers.simulation

import matplotlib.pyplot as plt
import numpy as np

from pyro.burgers import burgers_interface
from pyro.mesh import patch, reconstruction
from pyro.particles import particles
from pyro.simulation_null import NullSimulation, bc_setup, grid_setup
from pyro.util import plot_tools


[docs] class Simulation(NullSimulation):
[docs] def initialize(self): """ Initialize the grid and variables for advection and set the initial conditions for the chosen problem. """ # create grid, self.rp contains mesh.nx and mesh.ny my_grid = grid_setup(self.rp, ng=4) # create the variables my_data = patch.CellCenterData2d(my_grid) # outputs: bc, bc_xodd and bc_yodd for reflection boundary cond bc = bc_setup(self.rp)[0] # register variables in the data # burgers equation advects velocity my_data.register_var("x-velocity", bc) my_data.register_var("y-velocity", bc) my_data.create() # holds various data, like time and registered variable. self.cc_data = my_data if self.rp.get_param("particles.do_particles") == 1: n_particles = self.rp.get_param("particles.n_particles") particle_generator = self.rp.get_param("particles.particle_generator") self.particles = particles.Particles(self.cc_data, bc, n_particles, particle_generator) # now set the initial conditions for the problem self.problem_func(self.cc_data, self.rp)
[docs] def method_compute_timestep(self): """ The timestep() function computes the advective timestep (CFL) constraint. The CFL constraint says that information cannot propagate further than one zone per timestep. We use the driver.cfl parameter to control what fraction of the CFL step we actually take. """ cfl = self.rp.get_param("driver.cfl") u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") # the timestep is min(dx/|u|, dy|v|) xtmp = self.cc_data.grid.dx / max(abs(u).max(), self.SMALL) ytmp = self.cc_data.grid.dy / max(abs(v).max(), self.SMALL) self.dt = cfl * min(xtmp, ytmp)
[docs] def evolve(self): """ Evolve the burgers equation through one timestep. """ myg = self.cc_data.grid dtdx = self.dt/myg.dx dtdy = self.dt/myg.dy u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") # -------------------------------------------------------------------------- # monotonized central differences # -------------------------------------------------------------------------- limiter = self.rp.get_param("advection.limiter") # Give da/dx and da/dy using input: (state, grid, direction, limiter) ldelta_ux = reconstruction.limit(u, myg, 1, limiter) ldelta_uy = reconstruction.limit(u, myg, 2, limiter) ldelta_vx = reconstruction.limit(v, myg, 1, limiter) ldelta_vy = reconstruction.limit(v, myg, 2, limiter) # Get u, v fluxes u_xl, u_xr, u_yl, u_yr, v_xl, v_xr, v_yl, v_yr = burgers_interface.get_interface_states(myg, self.dt, u, v, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy) u_xl, u_xr, u_yl, u_yr, v_xl, v_xr, v_yl, v_yr = burgers_interface.apply_transverse_corrections(myg, self.dt, u_xl, u_xr, u_yl, u_yr, v_xl, v_xr, v_yl, v_yr) u_flux_x, u_flux_y, v_flux_x, v_flux_y = burgers_interface.construct_unsplit_fluxes(myg, u_xl, u_xr, u_yl, u_yr, v_xl, v_xr, v_yl, v_yr) """ do the differencing for the fluxes now. Here, we use slices so we avoid slow loops in python. This is equivalent to: myPatch.data[i,j] = myPatch.data[i,j] + \ dtdx*(flux_x[i,j] - flux_x[i+1,j]) + \ dtdy*(flux_y[i,j] - flux_y[i,j+1]) """ u.v()[:, :] = u.v() + dtdx*(u_flux_x.v() - u_flux_x.ip(1)) + \ dtdy*(u_flux_y.v() - u_flux_y.jp(1)) v.v()[:, :] = v.v() + dtdx*(v_flux_x.v() - v_flux_x.ip(1)) + \ dtdy*(v_flux_y.v() - v_flux_y.jp(1)) if self.particles is not None: u2d = u v2d = v self.particles.update_particles(self.dt, u2d, v2d) # increment the time self.cc_data.t += self.dt self.n += 1
[docs] def dovis(self): """ Do runtime visualization """ plt.clf() plt.rc("font", size=10) u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") myg = self.cc_data.grid _, axes, _ = plot_tools.setup_axes(myg, 2) fields = [u, v] field_names = ["u", "v"] for n in range(2): ax = axes[n] f = fields[n] img = ax.imshow(np.transpose(f.v()), interpolation="nearest", origin="lower", extent=[myg.xmin, myg.xmax, myg.ymin, myg.ymax], cmap=self.cm) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_title(field_names[n]) cb = axes.cbar_axes[n].colorbar(img) cb.solids.set_rasterized(True) cb.solids.set_edgecolor("face") if self.particles is not None: particle_positions = self.particles.get_positions() # dye particles colors = self.particles.get_init_positions()[:, 0] # plot particles ax.scatter(particle_positions[:, 0], particle_positions[:, 1], s=8, c=colors, cmap="Greys") ax.set_xlim([myg.xmin, myg.xmax]) ax.set_ylim([myg.ymin, myg.ymax]) plt.figtext(0.05, 0.0125, f"t = {self.cc_data.t:10.5f}") plt.pause(0.001) plt.draw()