def dovis(self): """ Do runtime visualization. """ plt.clf() plt.rc("font", size=10) # we do this even though ivars is in self, so this works when # we are plotting from a file ivars = Variables(self.cc_data) # access gamma from the cc_data object so we can use dovis # outside of a running simulation. gamma = self.cc_data.get_aux("gamma") q = cons_to_prim(self.cc_data.data, gamma, ivars, self.cc_data.grid) rho = q[:, :, ivars.irho] u = q[:, :, ivars.iu] v = q[:, :, ivars.iv] p = q[:, :, ivars.ip] e = eos.rhoe(gamma, p) / rho magvel = np.sqrt(u**2 + v**2) myg = self.cc_data.grid fields = [rho, magvel, p, e] field_names = [r"$\rho$", r"U", "p", "e"] f, axes, cbar_title = plot_tools.setup_axes(myg, len(fields)) for n, ax in enumerate(axes): v = fields[n] img = ax.imshow(np.transpose(v.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") # needed for PDF rendering cb = axes.cbar_axes[n].colorbar(img) cb.solids.set_rasterized(True) cb.solids.set_edgecolor("face") if cbar_title: cb.ax.set_title(field_names[n]) else: ax.set_title(field_names[n]) plt.figtext(0.05, 0.0125, "t = {:10.5g}".format(self.cc_data.t)) plt.pause(0.001) plt.draw()
def test_eos_consistency(): dens = 1.0 eint = 1.0 gamma = 1.4 p = eos.pres(gamma, dens, eint) dens_eos = eos.dens(gamma, p, eint) assert_equal(dens, dens_eos) rhoe_eos = eos.rhoe(gamma, p) assert_equal(dens * eint, rhoe_eos)
def test_eos_consistency(): dens = 1.0 eint = 1.0 gamma = 1.4 p = eos.pres(gamma, dens, eint) dens_eos = eos.dens(gamma, p, eint) assert dens == dens_eos rhoe_eos = eos.rhoe(gamma, p) assert dens*eint == rhoe_eos
def prim_to_cons(q, gamma, ivars, myg): """ convert an input vector of primitive variables to conserved variables """ U = myg.scratch_array(nvar=ivars.nvar) U[:, :, ivars.idens] = q[:, :, ivars.irho] U[:, :, ivars.ixmom] = q[:, :, ivars.iu] * U[:, :, ivars.idens] U[:, :, ivars.iymom] = q[:, :, ivars.iv] * U[:, :, ivars.idens] rhoe = eos.rhoe(gamma, q[:, :, ivars.ip]) U[:, :, ivars.iener] = rhoe + 0.5 * q[:, :, ivars.irho] * (q[:, :, ivars.iu]**2 + q[:, :, ivars.iv]**2) if ivars.naux > 0: U[:, :, ivars.irhox] = q[:, :, ivars.ix] * q[:, :, ivars.irho] return U
def prim_to_cons(q, gamma, ivars, myg): """ convert an input vector of primitive variables to conserved variables """ U = myg.scratch_array(nvar=ivars.nvar) U[:, :, ivars.idens] = q[:, :, ivars.irho] U[:, :, ivars.ixmom] = q[:, :, ivars.iu]*U[:, :, ivars.idens] U[:, :, ivars.iymom] = q[:, :, ivars.iv]*U[:, :, ivars.idens] rhoe = eos.rhoe(gamma, q[:, :, ivars.ip]) U[:, :, ivars.iener] = rhoe + 0.5*q[:, :, ivars.irho]*(q[:, :, ivars.iu]**2 + q[:, :, ivars.iv]**2) if ivars.naux > 0: for nq, nu in zip(range(ivars.ix, ivars.ix+ivars.naux), range(ivars.irhox, ivars.irhox+ivars.naux)): U[:, :, nu] = q[:, :, nq]*q[:, :, ivars.irho] return U
def unsplitFluxes(my_data, my_aux, rp, vars, solid, tc, dt): """ unsplitFluxes returns the fluxes through the x and y interfaces by doing an unsplit reconstruction of the interface values and then solving the Riemann problem through all the interfaces at once currently we assume a gamma-law EOS The runtime parameter grav is assumed to be the gravitational acceleration in the y-direction Parameters ---------- my_data : CellCenterData2d object The data object containing the grid and advective scalar that we are advecting. rp : RuntimeParameters object The runtime parameters for the simulation vars : Variables object The Variables object that tells us which indices refer to which variables tc : TimerCollection object The timers we are using to profile dt : float The timestep we are advancing through. Returns ------- out : ndarray, ndarray The fluxes on the x- and y-interfaces """ tm_flux = tc.timer("unsplitFluxes") tm_flux.begin() myg = my_data.grid gamma = rp.get_param("eos.gamma") #========================================================================= # compute the primitive variables #========================================================================= # Q = (rho, u, v, p) dens = my_data.get_var("density") xmom = my_data.get_var("x-momentum") ymom = my_data.get_var("y-momentum") ener = my_data.get_var("energy") r = dens # get the velocities u = xmom/dens v = ymom/dens # get the pressure e = (ener - 0.5*(xmom**2 + ymom**2)/dens)/dens p = eos.pres(gamma, dens, e) smallp = 1.e-10 p.d = p.d.clip(smallp) # apply a floor to the pressure #========================================================================= # compute the flattening coefficients #========================================================================= # there is a single flattening coefficient (xi) for all directions use_flattening = rp.get_param("compressible.use_flattening") if use_flattening: delta = rp.get_param("compressible.delta") z0 = rp.get_param("compressible.z0") z1 = rp.get_param("compressible.z1") xi_x = reconstruction_f.flatten(1, p.d, u.d, myg.qx, myg.qy, myg.ng, smallp, delta, z0, z1) xi_y = reconstruction_f.flatten(2, p.d, v.d, myg.qx, myg.qy, myg.ng, smallp, delta, z0, z1) xi = reconstruction_f.flatten_multid(xi_x, xi_y, p.d, myg.qx, myg.qy, myg.ng) else: xi = 1.0 # monotonized central differences in x-direction tm_limit = tc.timer("limiting") tm_limit.begin() limiter = rp.get_param("compressible.limiter") if limiter == 0: limitFunc = reconstruction_f.nolimit elif limiter == 1: limitFunc = reconstruction_f.limit2 else: limitFunc = reconstruction_f.limit4 ldelta_rx = xi*limitFunc(1, r.d, myg.qx, myg.qy, myg.ng) ldelta_ux = xi*limitFunc(1, u.d, myg.qx, myg.qy, myg.ng) ldelta_vx = xi*limitFunc(1, v.d, myg.qx, myg.qy, myg.ng) ldelta_px = xi*limitFunc(1, p.d, myg.qx, myg.qy, myg.ng) # monotonized central differences in y-direction ldelta_ry = xi*limitFunc(2, r.d, myg.qx, myg.qy, myg.ng) ldelta_uy = xi*limitFunc(2, u.d, myg.qx, myg.qy, myg.ng) ldelta_vy = xi*limitFunc(2, v.d, myg.qx, myg.qy, myg.ng) ldelta_py = xi*limitFunc(2, p.d, myg.qx, myg.qy, myg.ng) tm_limit.end() #========================================================================= # x-direction #========================================================================= # left and right primitive variable states tm_states = tc.timer("interfaceStates") tm_states.begin() V_l, V_r = interface_f.states(1, myg.qx, myg.qy, myg.ng, myg.dx, dt, vars.nvar, gamma, r.d, u.d, v.d, p.d, ldelta_rx, ldelta_ux, ldelta_vx, ldelta_px) tm_states.end() # transform interface states back into conserved variables U_xl = myg.scratch_array(vars.nvar) U_xr = myg.scratch_array(vars.nvar) U_xl.d[:,:,vars.idens] = V_l[:,:,vars.irho] U_xl.d[:,:,vars.ixmom] = V_l[:,:,vars.irho]*V_l[:,:,vars.iu] U_xl.d[:,:,vars.iymom] = V_l[:,:,vars.irho]*V_l[:,:,vars.iv] U_xl.d[:,:,vars.iener] = eos.rhoe(gamma, V_l[:,:,vars.ip]) + \ 0.5*V_l[:,:,vars.irho]*(V_l[:,:,vars.iu]**2 + V_l[:,:,vars.iv]**2) U_xr.d[:,:,vars.idens] = V_r[:,:,vars.irho] U_xr.d[:,:,vars.ixmom] = V_r[:,:,vars.irho]*V_r[:,:,vars.iu] U_xr.d[:,:,vars.iymom] = V_r[:,:,vars.irho]*V_r[:,:,vars.iv] U_xr.d[:,:,vars.iener] = eos.rhoe(gamma, V_r[:,:,vars.ip]) + \ 0.5*V_r[:,:,vars.irho]*(V_r[:,:,vars.iu]**2 + V_r[:,:,vars.iv]**2) #========================================================================= # y-direction #========================================================================= # left and right primitive variable states tm_states.begin() V_l, V_r = interface_f.states(2, myg.qx, myg.qy, myg.ng, myg.dy, dt, vars.nvar, gamma, r.d, u.d, v.d, p.d, ldelta_ry, ldelta_uy, ldelta_vy, ldelta_py) tm_states.end() # transform interface states back into conserved variables U_yl = myg.scratch_array(vars.nvar) U_yr = myg.scratch_array(vars.nvar) U_yl.d[:,:,vars.idens] = V_l[:,:,vars.irho] U_yl.d[:,:,vars.ixmom] = V_l[:,:,vars.irho]*V_l[:,:,vars.iu] U_yl.d[:,:,vars.iymom] = V_l[:,:,vars.irho]*V_l[:,:,vars.iv] U_yl.d[:,:,vars.iener] = eos.rhoe(gamma, V_l[:,:,vars.ip]) + \ 0.5*V_l[:,:,vars.irho]*(V_l[:,:,vars.iu]**2 + V_l[:,:,vars.iv]**2) U_yr.d[:,:,vars.idens] = V_r[:,:,vars.irho] U_yr.d[:,:,vars.ixmom] = V_r[:,:,vars.irho]*V_r[:,:,vars.iu] U_yr.d[:,:,vars.iymom] = V_r[:,:,vars.irho]*V_r[:,:,vars.iv] U_yr.d[:,:,vars.iener] = eos.rhoe(gamma, V_r[:,:,vars.ip]) + \ 0.5*V_r[:,:,vars.irho]*(V_r[:,:,vars.iu]**2 + V_r[:,:,vars.iv]**2) #========================================================================= # apply source terms #========================================================================= grav = rp.get_param("compressible.grav") ymom_src = my_aux.get_var("ymom_src") ymom_src.v()[:,:] = dens.v()*grav my_aux.fill_BC("ymom_src") E_src = my_aux.get_var("E_src") E_src.v()[:,:] = ymom.v()*grav my_aux.fill_BC("E_src") # ymom_xl[i,j] += 0.5*dt*dens[i-1,j]*grav U_xl.v(buf=1, n=vars.iymom)[:,:] += 0.5*dt*ymom_src.ip(-1, buf=1) U_xl.v(buf=1, n=vars.iener)[:,:] += 0.5*dt*E_src.ip(-1, buf=1) # ymom_xr[i,j] += 0.5*dt*dens[i,j]*grav U_xr.v(buf=1, n=vars.iymom)[:,:] += 0.5*dt*ymom_src.v(buf=1) U_xr.v(buf=1, n=vars.iener)[:,:] += 0.5*dt*E_src.v(buf=1) # ymom_yl[i,j] += 0.5*dt*dens[i,j-1]*grav U_yl.v(buf=1, n=vars.iymom)[:,:] += 0.5*dt*ymom_src.jp(-1, buf=1) U_yl.v(buf=1, n=vars.iener)[:,:] += 0.5*dt*E_src.jp(-1, buf=1) # ymom_yr[i,j] += 0.5*dt*dens[i,j]*grav U_yr.v(buf=1, n=vars.iymom)[:,:] += 0.5*dt*ymom_src.v(buf=1) U_yr.v(buf=1, n=vars.iener)[:,:] += 0.5*dt*E_src.v(buf=1) #========================================================================= # compute transverse fluxes #========================================================================= tm_riem = tc.timer("riemann") tm_riem.begin() riemann = rp.get_param("compressible.riemann") if riemann == "HLLC": riemannFunc = interface_f.riemann_hllc elif riemann == "CGF": riemannFunc = interface_f.riemann_cgf else: msg.fail("ERROR: Riemann solver undefined") _fx = riemannFunc(1, myg.qx, myg.qy, myg.ng, vars.nvar, vars.idens, vars.ixmom, vars.iymom, vars.iener, solid.xl, solid.xr, gamma, U_xl.d, U_xr.d) _fy = riemannFunc(2, myg.qx, myg.qy, myg.ng, vars.nvar, vars.idens, vars.ixmom, vars.iymom, vars.iener, solid.yl, solid.yr, gamma, U_yl.d, U_yr.d) F_x = patch.ArrayIndexer(d=_fx, grid=myg) F_y = patch.ArrayIndexer(d=_fy, grid=myg) tm_riem.end() #========================================================================= # construct the interface values of U now #========================================================================= """ finally, we can construct the state perpendicular to the interface by adding the central difference part to the trasverse flux difference. The states that we represent by indices i,j are shown below (1,2,3,4): j+3/2--+----------+----------+----------+ | | | | | | | | j+1 -+ | | | | | | | | | | | 1: U_xl[i,j,:] = U j+1/2--+----------XXXXXXXXXXXX----------+ i-1/2,j,L | X X | | X X | j -+ 1 X 2 X | 2: U_xr[i,j,:] = U | X X | i-1/2,j,R | X 4 X | j-1/2--+----------XXXXXXXXXXXX----------+ | | 3 | | 3: U_yl[i,j,:] = U | | | | i,j-1/2,L j-1 -+ | | | | | | | | | | | 4: U_yr[i,j,:] = U j-3/2--+----------+----------+----------+ i,j-1/2,R | | | | | | | i-1 i i+1 i-3/2 i-1/2 i+1/2 i+3/2 remember that the fluxes are stored on the left edge, so F_x[i,j,:] = F_x i-1/2, j F_y[i,j,:] = F_y i, j-1/2 """ tm_transverse = tc.timer("transverse flux addition") tm_transverse.begin() dtdx = dt/myg.dx dtdy = dt/myg.dy b = (2,1) for n in range(vars.nvar): # U_xl[i,j,:] = U_xl[i,j,:] - 0.5*dt/dy * (F_y[i-1,j+1,:] - F_y[i-1,j,:]) U_xl.v(buf=b, n=n)[:,:] += \ - 0.5*dtdy*(F_y.ip_jp(-1, 1, buf=b, n=n) - F_y.ip(-1, buf=b, n=n)) # U_xr[i,j,:] = U_xr[i,j,:] - 0.5*dt/dy * (F_y[i,j+1,:] - F_y[i,j,:]) U_xr.v(buf=b, n=n)[:,:] += \ - 0.5*dtdy*(F_y.jp(1, buf=b, n=n) - F_y.v(buf=b, n=n)) # U_yl[i,j,:] = U_yl[i,j,:] - 0.5*dt/dx * (F_x[i+1,j-1,:] - F_x[i,j-1,:]) U_yl.v(buf=b, n=n)[:,:] += \ - 0.5*dtdx*(F_x.ip_jp(1, -1, buf=b, n=n) - F_x.jp(-1, buf=b, n=n)) # U_yr[i,j,:] = U_yr[i,j,:] - 0.5*dt/dx * (F_x[i+1,j,:] - F_x[i,j,:]) U_yr.v(buf=b, n=n)[:,:] += \ - 0.5*dtdx*(F_x.ip(1, buf=b, n=n) - F_x.v(buf=b, n=n)) tm_transverse.end() #========================================================================= # construct the fluxes normal to the interfaces #========================================================================= # up until now, F_x and F_y stored the transverse fluxes, now we # overwrite with the fluxes normal to the interfaces tm_riem.begin() _fx = riemannFunc(1, myg.qx, myg.qy, myg.ng, vars.nvar, vars.idens, vars.ixmom, vars.iymom, vars.iener, solid.xl, solid.xr, gamma, U_xl.d, U_xr.d) _fy = riemannFunc(2, myg.qx, myg.qy, myg.ng, vars.nvar, vars.idens, vars.ixmom, vars.iymom, vars.iener, solid.yl, solid.yr, gamma, U_yl.d, U_yr.d) F_x = patch.ArrayIndexer(d=_fx, grid=myg) F_y = patch.ArrayIndexer(d=_fy, grid=myg) tm_riem.end() #========================================================================= # apply artificial viscosity #========================================================================= cvisc = rp.get_param("compressible.cvisc") _ax, _ay = interface_f.artificial_viscosity( myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, cvisc, u.d, v.d) avisco_x = patch.ArrayIndexer(d=_ax, grid=myg) avisco_y = patch.ArrayIndexer(d=_ay, grid=myg) b = (2,1) # F_x = F_x + avisco_x * (U(i-1,j) - U(i,j)) F_x.v(buf=b, n=vars.idens)[:,:] += \ avisco_x.v(buf=b)*(dens.ip(-1, buf=b) - dens.v(buf=b)) F_x.v(buf=b, n=vars.ixmom)[:,:] += \ avisco_x.v(buf=b)*(xmom.ip(-1, buf=b) - xmom.v(buf=b)) F_x.v(buf=b, n=vars.iymom)[:,:] += \ avisco_x.v(buf=b)*(ymom.ip(-1, buf=b) - ymom.v(buf=b)) F_x.v(buf=b, n=vars.iener)[:,:] += \ avisco_x.v(buf=b)*(ener.ip(-1, buf=b) - ener.v(buf=b)) # F_y = F_y + avisco_y * (U(i,j-1) - U(i,j)) F_y.v(buf=b, n=vars.idens)[:,:] += \ avisco_y.v(buf=b)*(dens.jp(-1, buf=b) - dens.v(buf=b)) F_y.v(buf=b, n=vars.ixmom)[:,:] += \ avisco_y.v(buf=b)*(xmom.jp(-1, buf=b) - xmom.v(buf=b)) F_y.v(buf=b, n=vars.iymom)[:,:] += \ avisco_y.v(buf=b)*(ymom.jp(-1, buf=b) - ymom.v(buf=b)) F_y.v(buf=b, n=vars.iener)[:,:] += \ avisco_y.v(buf=b)*(ener.jp(-1, buf=b) - ener.v(buf=b)) tm_flux.end() return F_x, F_y
def dovis(self): """ Do runtime visualization. """ plt.clf() plt.rc("font", size=10) # we do this even though ivars is in self, so this works when # we are plotting from a file ivars = Variables(self.cc_data) # access gamma from the cc_data object so we can use dovis # outside of a running simulation. gamma = self.cc_data.get_aux("gamma") q = cons_to_prim(self.cc_data.data, gamma, ivars, self.cc_data.grid) rho = q[:, :, ivars.irho] u = q[:, :, ivars.iu] v = q[:, :, ivars.iv] p = q[:, :, ivars.ip] e = eos.rhoe(gamma, p)/rho magvel = np.sqrt(u**2 + v**2) myg = self.cc_data.grid fields = [rho, magvel, p, e] field_names = [r"$\rho$", r"U", "p", "e"] _, axes, cbar_title = plot_tools.setup_axes(myg, len(fields)) for n, ax in enumerate(axes): v = fields[n] img = ax.imshow(np.transpose(v.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") # needed for PDF rendering cb = axes.cbar_axes[n].colorbar(img) cb.solids.set_rasterized(True) cb.solids.set_edgecolor("face") if cbar_title: cb.ax.set_title(field_names[n]) else: ax.set_title(field_names[n]) if self.particles is not None: ax = axes[0] 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=5, c=colors, alpha=0.8, cmap="Greys") ax.set_xlim([myg.xmin, myg.xmax]) ax.set_ylim([myg.ymin, myg.ymax]) plt.figtext(0.05, 0.0125, "t = {:10.5g}".format(self.cc_data.t)) plt.pause(0.001) plt.draw()
def user(bc_name, bc_edge, variable, my_data): """ A hydrostatic boundary. This integrates the equation of HSE into the ghost cells to get the pressure and density under the assumption that the specific internal energy is constant. Upon exit, the ghost cells for the input variable will be set Parameters ---------- bc_name : {'hse'} The descriptive name for the boundary condition -- this allows for pyro to have multiple types of user-supplied boundary conditions. For this module, it needs to be 'hse'. bc_edge : {'ylb', 'yrb'} The boundary to update: ylb = lower y boundary; yrb = upper y boundary. variable : {'density', 'x-momentum', 'y-momentum', 'energy'} The variable whose ghost cells we are filling my_data : CellCenterData2d object The data object """ dens = my_data.get_var("density") xmom = my_data.get_var("x-momentum") ymom = my_data.get_var("y-momentum") ener = my_data.get_var("energy") grav = my_data.get_aux("grav") gamma = my_data.get_aux("gamma") myg = my_data.grid if bc_name == "hse": if bc_edge == "ylb": # lower y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable == "density": j = myg.jlo - 1 while j >= 0: dens[:, j] = dens[:, myg.jlo] j -= 1 elif variable == "x-momentum": j = myg.jlo - 1 while j >= 0: xmom[:, j] = xmom[:, myg.jlo] j -= 1 elif variable == "y-momentum": j = myg.jlo - 1 while j >= 0: ymom[:, j] = ymom[:, myg.jlo] j -= 1 elif variable == "energy": dens_base = dens[:, myg.jlo] ke_base = 0.5 * (xmom[:, myg.jlo] ** 2 + ymom[:, myg.jlo] ** 2) / dens[:, myg.jlo] eint_base = (ener[:, myg.jlo] - ke_base) / dens[:, myg.jlo] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation j = myg.jlo - 1 while j >= 0: pres_below = pres_base - grav * dens_base * myg.dy rhoe = eos.rhoe(gamma, pres_below) ener[:, j] = rhoe + ke_base pres_base = pres_below.copy() j -= 1 else: msg.fail("error: variable not defined") elif bc_edge == "yrb": # upper y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable == "density": j = myg.jhi + 1 while j <= myg.jhi + myg.ng: dens[:, j] = dens[:, myg.jhi] j += 1 elif variable == "x-momentum": j = myg.jhi + 1 while j <= myg.jhi + myg.ng: xmom[:, j] = xmom[:, myg.jhi] j += 1 elif variable == "y-momentum": j = myg.jhi + 1 while j <= myg.jhi + myg.ng: ymom[:, j] = ymom[:, myg.jhi] j += 1 elif variable == "energy": dens_base = dens[:, myg.jhi] ke_base = 0.5 * (xmom[:, myg.jhi] ** 2 + ymom[:, myg.jhi] ** 2) / dens[:, myg.jhi] eint_base = (ener[:, myg.jhi] - ke_base) / dens[:, myg.jhi] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation j = myg.jhi + 1 while j <= myg.jhi + myg.ng: pres_above = pres_base + grav * dens_base * myg.dy rhoe = eos.rhoe(gamma, pres_above) ener[:, j] = rhoe + ke_base pres_base = pres_above.copy() j += 1 else: msg.fail("error: variable not defined") else: msg.fail("error: hse BC not supported for xlb or xrb") else: msg.fail("error: bc type %s not supported" % (bc_name))
def dovis(self): """ Do runtime visualization. """ plt.clf() plt.rc("font", size=10) # we do this even though ivars is in self, so this works when # we are plotting from a file ivars = Variables(self.cc_data) # access gamma from the cc_data object so we can use dovis # outside of a running simulation. gamma = self.cc_data.get_aux("gamma") q = cons_to_prim(self.cc_data.data, gamma, ivars, self.cc_data.grid) rho = q[:, :, ivars.irho] u = q[:, :, ivars.iu] v = q[:, :, ivars.iv] p = q[:, :, ivars.ip] e = eos.rhoe(gamma, p) / rho magvel = np.sqrt(u**2 + v**2) myg = self.cc_data.grid # figure out the geometry L_x = self.cc_data.grid.xmax - self.cc_data.grid.xmin L_y = self.cc_data.grid.ymax - self.cc_data.grid.ymin f = plt.figure(1) cbar_title = False if L_x > 2 * L_y: # we want 4 rows: axes = AxesGrid(f, 111, nrows_ncols=(4, 1), share_all=True, cbar_mode="each", cbar_location="top", cbar_pad="10%", cbar_size="25%", axes_pad=(0.25, 0.65), add_all=True, label_mode="L") cbar_title = True elif L_y > 2 * L_x: # we want 4 columns: rho |U| p e axes = AxesGrid(f, 111, nrows_ncols=(1, 4), share_all=True, cbar_mode="each", cbar_location="right", cbar_pad="10%", cbar_size="25%", axes_pad=(0.65, 0.25), add_all=True, label_mode="L") else: # 2x2 grid of plots axes = AxesGrid(f, 111, nrows_ncols=(2, 2), share_all=True, cbar_mode="each", cbar_location="right", cbar_pad="2%", axes_pad=(0.65, 0.25), add_all=True, label_mode="L") fields = [rho, magvel, p, e] field_names = [r"$\rho$", r"U", "p", "e"] for n in range(4): ax = axes[n] v = fields[n] img = ax.imshow(np.transpose(v.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") cb = axes.cbar_axes[n].colorbar(img) if cbar_title: cb.ax.set_title(field_names[n]) else: ax.set_title(field_names[n]) plt.figtext(0.05, 0.0125, "t = {:10.5g}".format(self.cc_data.t)) plt.pause(0.001) plt.draw()
def init_data(my_data, rp): """ initialize the shu-osher problem """ msg.bold("initializing the sod problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ERROR: patch invalid in shu_osher.py") print(my_data.__class__) sys.exit() # get the shu_osher parameters dens_left = rp.get_param("shu_osher.dens_left") u_left = rp.get_param("shu_osher.u_left") u_right = rp.get_param("shu_osher.u_right") p_left = rp.get_param("shu_osher.p_left") p_right = rp.get_param("shu_osher.p_right") # get the density, momenta, and energy as separate variables dens = my_data.get_var("density") xmom = my_data.get_var("x-momentum") ymom = my_data.get_var("y-momentum") ener = my_data.get_var("energy") # initialize the components, remember, that ener here is rho*eint # + 0.5*rho*v**2, where eint is the specific internal energy # (erg/g) xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") gamma = rp.get_param("eos.gamma") direction = rp.get_param("shu_osher.direction") #xctr = 0.5*(xmin + xmax) xctr = -4.0 yctr = 0.5 * (ymin + ymax) myg = my_data.grid if direction == "x": # left idxl = myg.x2d <= xctr dens[idxl] = dens_left xmom[idxl] = dens_left * u_left ymom[idxl] = 0.0 ener[idxl] = eos.rhoe(dens[idxl], p_left * np.ones(np.shape(dens[idxl]))) #/ dens[idxl] #ener[idxl] = p_left/(gamma - 1.0) + 0.5*xmom[idxl]*u_left # right idxr = myg.x2d > xctr xdat = idxr[:, 0] xall = myg.x2d[:, 0] rhocrit = dens_left / 3.857 for i in range(xdat.shape[0]): if idxr[i].all() == True: dens[i] = (1.0 + 0.2 * np.sin(5.0 * xall[i])) * rhocrit * np.ones(18) xmom[i] = (1.0 + 0.2 * np.sin(5.0 * xall[i]) ) * rhocrit * np.ones(18) * u_right ymom[i] = np.ones(18) * 0.0 ener[i] = eos.rhoe((1.0 + 0.2 * np.sin(5.0 * xall[i])) * rhocrit * np.ones(18), p_right * np.ones(18)) keyboard() #dens[idxr] = 1.0 + 0.2*np.sin(5.0*xall[xdat]) #xmom[idxr] = dens_right*u_right #ymom[idxr] = 0.0 #ener[idxr] = eos.rhoe(dens[idxr], p_right*np.ones(np.shape(dens[idxr]))) #/ dens[idxr] #ener[idxr] = p_right/(gamma - 1.0) + 0.5*xmom[idxr]*u_right else: # bottom idxb = myg.y2d <= yctr dens[idxb] = dens_left xmom[idxb] = 0.0 ymom[idxb] = dens_left * u_left ener[idxb] = eos.rhoe(dens[idxb], p_left * np.ones(np.shape(dens[idxb]))) #/ dens[idxb] #ener[idxb] = p_left/(gamma - 1.0) + 0.5*ymom[idxb]*u_left # top idxt = myg.y2d > yctr dens[idxt] = dens_right xmom[idxt] = 0.0 ymom[idxt] = dens_right * u_right ener[idxt] = eos.rhoe(dens[idxt], p_right * np.ones(np.shape(dens[idxt]))) #/ dens[idxt]
def init_data(my_data, rp): """ initialize the Kelvin-Helmholtz problem """ msg.bold("initializing the sedov problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print(my_data.__class__) msg.fail("ERROR: patch invalid in sedov.py") # get the density, momenta, and energy as separate variables dens = my_data.get_var("density") xmom = my_data.get_var("x-momentum") ymom = my_data.get_var("y-momentum") ener = my_data.get_var("energy") # initialize the components, remember, that ener here is rho*eint # + 0.5*rho*v**2, where eint is the specific internal energy # (erg/g) dens[:, :] = 1.0 xmom[:, :] = 0.0 ymom[:, :] = 0.0 rho_1 = rp.get_param("kh.rho_1") v_1 = rp.get_param("kh.v_1") rho_2 = rp.get_param("kh.rho_2") v_2 = rp.get_param("kh.v_2") gamma = rp.get_param("eos.gamma") xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") yctr = 0.5 * (ymin + ymax) L_x = xmax - xmin myg = my_data.grid idx_l = myg.y2d < yctr + 0.01 * np.sin(10.0 * np.pi * myg.x2d / L_x) idx_h = myg.y2d >= yctr + 0.01 * np.sin(10.0 * np.pi * myg.x2d / L_x) # lower half dens[idx_l] = rho_1 xmom[idx_l] = rho_1 * v_1 ymom[idx_l] = 0.0 # upper half dens[idx_h] = rho_2 xmom[idx_h] = rho_2 * v_2 ymom[idx_h] = 0.0 #p = 1.0 p = 6.9E06 * np.ones(np.shape(dens)) #ener[:,:] = p/(gamma - 1.0) + 0.5*(xmom[:,:]**2 + ymom[:,:]**2)/dens[:,:] ener[:, :] = eos.rhoe( dens[:, :], p) + 0.5 * (xmom[:, :]**2 + ymom[:, :]**2) / dens[:, :] keyboard()
def fluxes(my_data, rp, vars, solid, tc): """ unsplitFluxes returns the fluxes through the x and y interfaces by doing an unsplit reconstruction of the interface values and then solving the Riemann problem through all the interfaces at once currently we assume a gamma-law EOS Parameters ---------- my_data : CellCenterData2d object The data object containing the grid and advective scalar that we are advecting. rp : RuntimeParameters object The runtime parameters for the simulation vars : Variables object The Variables object that tells us which indices refer to which variables tc : TimerCollection object The timers we are using to profile Returns ------- out : ndarray, ndarray The fluxes on the x- and y-interfaces """ tm_flux = tc.timer("unsplitFluxes") tm_flux.begin() myg = my_data.grid gamma = rp.get_param("eos.gamma") #========================================================================= # compute the primitive variables #========================================================================= # Q = (rho, u, v, p) dens = my_data.get_var("density") xmom = my_data.get_var("x-momentum") ymom = my_data.get_var("y-momentum") ener = my_data.get_var("energy") r = dens # get the velocities u = xmom / dens v = ymom / dens # get the pressure e = (ener - 0.5 * (xmom**2 + ymom**2) / dens) / dens p = eos.pres(gamma, dens, e) smallp = 1.e-10 p = p.clip(smallp) # apply a floor to the pressure #========================================================================= # compute the flattening coefficients #========================================================================= # there is a single flattening coefficient (xi) for all directions use_flattening = rp.get_param("compressible.use_flattening") if use_flattening: delta = rp.get_param("compressible.delta") z0 = rp.get_param("compressible.z0") z1 = rp.get_param("compressible.z1") xi_x = reconstruction_f.flatten(1, p, u, myg.qx, myg.qy, myg.ng, smallp, delta, z0, z1) xi_y = reconstruction_f.flatten(2, p, v, myg.qx, myg.qy, myg.ng, smallp, delta, z0, z1) xi = reconstruction_f.flatten_multid(xi_x, xi_y, p, myg.qx, myg.qy, myg.ng) else: xi = 1.0 # monotonized central differences in x-direction tm_limit = tc.timer("limiting") tm_limit.begin() limiter = rp.get_param("compressible.limiter") if limiter == 0: limitFunc = reconstruction_f.nolimit elif limiter == 1: limitFunc = reconstruction_f.limit2 else: limitFunc = reconstruction_f.limit4 _ldelta_rx = xi * limitFunc(1, r, myg.qx, myg.qy, myg.ng) _ldelta_ux = xi * limitFunc(1, u, myg.qx, myg.qy, myg.ng) _ldelta_vx = xi * limitFunc(1, v, myg.qx, myg.qy, myg.ng) _ldelta_px = xi * limitFunc(1, p, myg.qx, myg.qy, myg.ng) # wrap these in ArrayIndexer objects ldelta_rx = ai.ArrayIndexer(d=_ldelta_rx, grid=myg) ldelta_ux = ai.ArrayIndexer(d=_ldelta_ux, grid=myg) ldelta_vx = ai.ArrayIndexer(d=_ldelta_vx, grid=myg) ldelta_px = ai.ArrayIndexer(d=_ldelta_px, grid=myg) # monotonized central differences in y-direction _ldelta_ry = xi * limitFunc(2, r, myg.qx, myg.qy, myg.ng) _ldelta_uy = xi * limitFunc(2, u, myg.qx, myg.qy, myg.ng) _ldelta_vy = xi * limitFunc(2, v, myg.qx, myg.qy, myg.ng) _ldelta_py = xi * limitFunc(2, p, myg.qx, myg.qy, myg.ng) ldelta_ry = ai.ArrayIndexer(d=_ldelta_ry, grid=myg) ldelta_uy = ai.ArrayIndexer(d=_ldelta_uy, grid=myg) ldelta_vy = ai.ArrayIndexer(d=_ldelta_vy, grid=myg) ldelta_py = ai.ArrayIndexer(d=_ldelta_py, grid=myg) tm_limit.end() #========================================================================= # x-direction #========================================================================= # left and right primitive variable states tm_states = tc.timer("interfaceStates") tm_states.begin() V_l = myg.scratch_array(vars.nvar) V_r = myg.scratch_array(vars.nvar) V_l.ip(1, n=vars.irho, buf=2)[:, :] = r.v(buf=2) + 0.5 * ldelta_rx.v(buf=2) V_r.v(n=vars.irho, buf=2)[:, :] = r.v(buf=2) - 0.5 * ldelta_rx.v(buf=2) V_l.ip(1, n=vars.iu, buf=2)[:, :] = u.v(buf=2) + 0.5 * ldelta_ux.v(buf=2) V_r.v(n=vars.iu, buf=2)[:, :] = u.v(buf=2) - 0.5 * ldelta_ux.v(buf=2) V_l.ip(1, n=vars.iv, buf=2)[:, :] = v.v(buf=2) + 0.5 * ldelta_vx.v(buf=2) V_r.v(n=vars.iv, buf=2)[:, :] = v.v(buf=2) - 0.5 * ldelta_vx.v(buf=2) V_l.ip(1, n=vars.ip, buf=2)[:, :] = p.v(buf=2) + 0.5 * ldelta_px.v(buf=2) V_r.v(n=vars.ip, buf=2)[:, :] = p.v(buf=2) - 0.5 * ldelta_px.v(buf=2) tm_states.end() # transform interface states back into conserved variables U_xl = myg.scratch_array(vars.nvar) U_xr = myg.scratch_array(vars.nvar) U_xl[:, :, vars.idens] = V_l[:, :, vars.irho] U_xl[:, :, vars.ixmom] = V_l[:, :, vars.irho] * V_l[:, :, vars.iu] U_xl[:, :, vars.iymom] = V_l[:, :, vars.irho] * V_l[:, :, vars.iv] U_xl[:,:,vars.iener] = eos.rhoe(gamma, V_l[:,:,vars.ip]) + \ 0.5*V_l[:,:,vars.irho]*(V_l[:,:,vars.iu]**2 + V_l[:,:,vars.iv]**2) U_xr[:, :, vars.idens] = V_r[:, :, vars.irho] U_xr[:, :, vars.ixmom] = V_r[:, :, vars.irho] * V_r[:, :, vars.iu] U_xr[:, :, vars.iymom] = V_r[:, :, vars.irho] * V_r[:, :, vars.iv] U_xr[:,:,vars.iener] = eos.rhoe(gamma, V_r[:,:,vars.ip]) + \ 0.5*V_r[:,:,vars.irho]*(V_r[:,:,vars.iu]**2 + V_r[:,:,vars.iv]**2) #========================================================================= # y-direction #========================================================================= # left and right primitive variable states tm_states.begin() V_l.jp(1, n=vars.irho, buf=2)[:, :] = r.v(buf=2) + 0.5 * ldelta_ry.v(buf=2) V_r.v(n=vars.irho, buf=2)[:, :] = r.v(buf=2) - 0.5 * ldelta_ry.v(buf=2) V_l.jp(1, n=vars.iu, buf=2)[:, :] = u.v(buf=2) + 0.5 * ldelta_uy.v(buf=2) V_r.v(n=vars.iu, buf=2)[:, :] = u.v(buf=2) - 0.5 * ldelta_uy.v(buf=2) V_l.jp(1, n=vars.iv, buf=2)[:, :] = v.v(buf=2) + 0.5 * ldelta_vy.v(buf=2) V_r.v(n=vars.iv, buf=2)[:, :] = v.v(buf=2) - 0.5 * ldelta_vy.v(buf=2) V_l.jp(1, n=vars.ip, buf=2)[:, :] = p.v(buf=2) + 0.5 * ldelta_py.v(buf=2) V_r.v(n=vars.ip, buf=2)[:, :] = p.v(buf=2) - 0.5 * ldelta_py.v(buf=2) tm_states.end() # transform interface states back into conserved variables U_yl = myg.scratch_array(vars.nvar) U_yr = myg.scratch_array(vars.nvar) U_yl[:, :, vars.idens] = V_l[:, :, vars.irho] U_yl[:, :, vars.ixmom] = V_l[:, :, vars.irho] * V_l[:, :, vars.iu] U_yl[:, :, vars.iymom] = V_l[:, :, vars.irho] * V_l[:, :, vars.iv] U_yl[:,:,vars.iener] = eos.rhoe(gamma, V_l[:,:,vars.ip]) + \ 0.5*V_l[:,:,vars.irho]*(V_l[:,:,vars.iu]**2 + V_l[:,:,vars.iv]**2) U_yr[:, :, vars.idens] = V_r[:, :, vars.irho] U_yr[:, :, vars.ixmom] = V_r[:, :, vars.irho] * V_r[:, :, vars.iu] U_yr[:, :, vars.iymom] = V_r[:, :, vars.irho] * V_r[:, :, vars.iv] U_yr[:,:,vars.iener] = eos.rhoe(gamma, V_r[:,:,vars.ip]) + \ 0.5*V_r[:,:,vars.irho]*(V_r[:,:,vars.iu]**2 + V_r[:,:,vars.iv]**2) #========================================================================= # construct the fluxes normal to the interfaces #========================================================================= tm_riem = tc.timer("Riemann") tm_riem.begin() riemann = rp.get_param("compressible.riemann") if riemann == "HLLC": riemannFunc = interface_f.riemann_hllc elif riemann == "CGF": riemannFunc = interface_f.riemann_cgf else: msg.fail("ERROR: Riemann solver undefined") _fx = riemannFunc(1, myg.qx, myg.qy, myg.ng, vars.nvar, vars.idens, vars.ixmom, vars.iymom, vars.iener, solid.xl, solid.xr, gamma, U_xl, U_xr) _fy = riemannFunc(2, myg.qx, myg.qy, myg.ng, vars.nvar, vars.idens, vars.ixmom, vars.iymom, vars.iener, solid.yl, solid.yr, gamma, U_yl, U_yr) F_x = ai.ArrayIndexer(d=_fx, grid=myg) F_y = ai.ArrayIndexer(d=_fy, grid=myg) tm_riem.end() #========================================================================= # apply artificial viscosity #========================================================================= cvisc = rp.get_param("compressible.cvisc") _ax, _ay = interface_f.artificial_viscosity(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, cvisc, u, v) avisco_x = ai.ArrayIndexer(d=_ax, grid=myg) avisco_y = ai.ArrayIndexer(d=_ay, grid=myg) b = (2, 1) # F_x = F_x + avisco_x * (U(i-1,j) - U(i,j)) F_x.v(buf=b, n=vars.idens)[:,:] += \ avisco_x.v(buf=b)*(dens.ip(-1, buf=b) - dens.v(buf=b)) F_x.v(buf=b, n=vars.ixmom)[:,:] += \ avisco_x.v(buf=b)*(xmom.ip(-1, buf=b) - xmom.v(buf=b)) F_x.v(buf=b, n=vars.iymom)[:,:] += \ avisco_x.v(buf=b)*(ymom.ip(-1, buf=b) - ymom.v(buf=b)) F_x.v(buf=b, n=vars.iener)[:,:] += \ avisco_x.v(buf=b)*(ener.ip(-1, buf=b) - ener.v(buf=b)) # F_y = F_y + avisco_y * (U(i,j-1) - U(i,j)) F_y.v(buf=b, n=vars.idens)[:,:] += \ avisco_y.v(buf=b)*(dens.jp(-1, buf=b) - dens.v(buf=b)) F_y.v(buf=b, n=vars.ixmom)[:,:] += \ avisco_y.v(buf=b)*(xmom.jp(-1, buf=b) - xmom.v(buf=b)) F_y.v(buf=b, n=vars.iymom)[:,:] += \ avisco_y.v(buf=b)*(ymom.jp(-1, buf=b) - ymom.v(buf=b)) F_y.v(buf=b, n=vars.iener)[:,:] += \ avisco_y.v(buf=b)*(ener.jp(-1, buf=b) - ener.v(buf=b)) tm_flux.end() return F_x, F_y
def user(bc_name, bc_edge, variable, ccdata): """ A hydrostatic boundary. This integrates the equation of HSE into the ghost cells to get the pressure and density under the assumption that the specific internal energy is constant. Upon exit, the ghost cells for the input variable will be set Parameters ---------- bc_name : {'hse'} The descriptive name for the boundary condition -- this allows for pyro to have multiple types of user-supplied boundary conditions. For this module, it needs to be 'hse'. bc_edge : {'ylb', 'yrb'} The boundary to update: ylb = lower y boundary; yrb = upper y boundary. variable : {'density', 'x-momentum', 'y-momentum', 'energy'} The variable whose ghost cells we are filling ccdata : CellCenterData2d object The data object """ myg = ccdata.grid if bc_name == "hse": if bc_edge == "ylb": # lower y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable in ["density", "x-momentum", "y-momentum", "ymom_src", "E_src", "fuel", "ash"]: v = ccdata.get_var(variable) j = myg.jlo-1 while j >= 0: v[:, j] = v[:, myg.jlo] j -= 1 elif variable == "energy": dens = ccdata.get_var("density") xmom = ccdata.get_var("x-momentum") ymom = ccdata.get_var("y-momentum") ener = ccdata.get_var("energy") grav = ccdata.get_aux("grav") gamma = ccdata.get_aux("gamma") dens_base = dens[:, myg.jlo] ke_base = 0.5*(xmom[:, myg.jlo]**2 + ymom[:, myg.jlo]**2) / \ dens[:, myg.jlo] eint_base = (ener[:, myg.jlo] - ke_base)/dens[:, myg.jlo] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation j = myg.jlo-1 while j >= 0: pres_below = pres_base - grav*dens_base*myg.dy rhoe = eos.rhoe(gamma, pres_below) ener[:, j] = rhoe + ke_base pres_base = pres_below.copy() j -= 1 else: raise NotImplementedError("variable not defined") elif bc_edge == "yrb": # upper y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable in ["density", "x-momentum", "y-momentum", "ymom_src", "E_src", "fuel", "ash"]: v = ccdata.get_var(variable) for j in range(myg.jhi+1, myg.jhi+myg.ng+1): v[:, j] = v[:, myg.jhi] elif variable == "energy": dens = ccdata.get_var("density") xmom = ccdata.get_var("x-momentum") ymom = ccdata.get_var("y-momentum") ener = ccdata.get_var("energy") grav = ccdata.get_aux("grav") gamma = ccdata.get_aux("gamma") dens_base = dens[:, myg.jhi] ke_base = 0.5*(xmom[:, myg.jhi]**2 + ymom[:, myg.jhi]**2) / \ dens[:, myg.jhi] eint_base = (ener[:, myg.jhi] - ke_base)/dens[:, myg.jhi] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation for j in range(myg.jhi+1, myg.jhi+myg.ng+1): pres_above = pres_base + grav*dens_base*myg.dy rhoe = eos.rhoe(gamma, pres_above) ener[:, j] = rhoe + ke_base pres_base = pres_above.copy() else: raise NotImplementedError("variable not defined") else: msg.fail("error: hse BC not supported for xlb or xrb") elif bc_name == "ramp": # Boundary conditions for double Mach reflection problem gamma = ccdata.get_aux("gamma") if bc_edge == "xlb": # lower x boundary # inflow condition with post shock setup v = ccdata.get_var(variable) i = myg.ilo - 1 if variable in ["density", "x-momentum", "y-momentum", "energy"]: val = inflow_post_bc(variable, gamma) while i >= 0: v[i, :] = val i = i - 1 else: v[:, :] = 0.0 # no source term elif bc_edge == "ylb": # lower y boundary # for x > 1./6., reflective boundary # for x < 1./6., inflow with post shock setup if variable in ["density", "x-momentum", "y-momentum", "energy"]: v = ccdata.get_var(variable) j = myg.jlo - 1 jj = 0 while j >= 0: xcen_l = myg.x < 1.0/6.0 xcen_r = myg.x >= 1.0/6.0 v[xcen_l, j] = inflow_post_bc(variable, gamma) if variable == "y-momentum": v[xcen_r, j] = -1.0*v[xcen_r, myg.jlo+jj] else: v[xcen_r, j] = v[xcen_r, myg.jlo+jj] j = j - 1 jj = jj + 1 else: v = ccdata.get_var(variable) v[:, :] = 0.0 # no source term elif bc_edge == "yrb": # upper y boundary # time-dependent boundary, the shockfront moves with a 10 mach velocity forming an angle # to the x-axis of 30 degrees clockwise. # x coordinate of the grid is used to judge whether the cell belongs to pure post shock area, # the pure pre shock area or the mixed area. if variable in ["density", "x-momentum", "y-momentum", "energy"]: v = ccdata.get_var(variable) for j in range(myg.jhi+1, myg.jhi+myg.ng+1): shockfront_up = 1.0/6.0 + (myg.y[j] + 0.5*myg.dy*math.sqrt(3))/math.tan(math.pi/3.0) \ + (10.0/math.sin(math.pi/3.0))*ccdata.t shockfront_down = 1.0/6.0 + (myg.y[j] - 0.5*myg.dy*math.sqrt(3))/math.tan(math.pi/3.0) \ + (10.0/math.sin(math.pi/3.0))*ccdata.t shockfront = np.array([shockfront_down, shockfront_up]) for i in range(myg.ihi+myg.ng+1): v[i, j] = 0.0 cx_down = myg.x[i] - 0.5*myg.dx*math.sqrt(3) cx_up = myg.x[i] + 0.5*myg.dx*math.sqrt(3) cx = np.array([cx_down, cx_up]) for sf in shockfront: for x in cx: if x < sf: v[i, j] = v[i, j] + 0.25*inflow_post_bc(variable, gamma) else: v[i, j] = v[i, j] + 0.25*inflow_pre_bc(variable, gamma) else: v = ccdata.get_var(variable) v[:, :] = 0.0 # no source term else: msg.fail("error: bc type %s not supported" % (bc_name))
def user(bc_name, bc_edge, variable, ccdata): """ A hydrostatic boundary. This integrates the equation of HSE into the ghost cells to get the pressure and density under the assumption that the specific internal energy is constant. Upon exit, the ghost cells for the input variable will be set Parameters ---------- bc_name : {'hse'} The descriptive name for the boundary condition -- this allows for pyro to have multiple types of user-supplied boundary conditions. For this module, it needs to be 'hse'. bc_edge : {'ylb', 'yrb'} The boundary to update: ylb = lower y boundary; yrb = upper y boundary. variable : {'density', 'x-momentum', 'y-momentum', 'energy'} The variable whose ghost cells we are filling ccdata : CellCenterData2d object The data object """ myg = ccdata.grid if bc_name == "hse": if bc_edge == "ylb": # lower y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable in [ "density", "x-momentum", "y-momentum", "ymom_src", "E_src", "fuel", "ash" ]: v = ccdata.get_var(variable) j = myg.jlo - 1 while j >= 0: v[:, j] = v[:, myg.jlo] j -= 1 elif variable == "energy": dens = ccdata.get_var("density") xmom = ccdata.get_var("x-momentum") ymom = ccdata.get_var("y-momentum") ener = ccdata.get_var("energy") grav = ccdata.get_aux("grav") gamma = ccdata.get_aux("gamma") dens_base = dens[:, myg.jlo] ke_base = 0.5*(xmom[:, myg.jlo]**2 + ymom[:, myg.jlo]**2) / \ dens[:, myg.jlo] eint_base = (ener[:, myg.jlo] - ke_base) / dens[:, myg.jlo] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation j = myg.jlo - 1 while j >= 0: pres_below = pres_base - grav * dens_base * myg.dy rhoe = eos.rhoe(gamma, pres_below) ener[:, j] = rhoe + ke_base pres_base = pres_below.copy() j -= 1 else: raise NotImplementedError("variable not defined") elif bc_edge == "yrb": # upper y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable in [ "density", "x-momentum", "y-momentum", "ymom_src", "E_src", "fuel", "ash" ]: v = ccdata.get_var(variable) for j in range(myg.jhi + 1, myg.jhi + myg.ng + 1): v[:, j] = v[:, myg.jhi] elif variable == "energy": dens = ccdata.get_var("density") xmom = ccdata.get_var("x-momentum") ymom = ccdata.get_var("y-momentum") ener = ccdata.get_var("energy") grav = ccdata.get_aux("grav") gamma = ccdata.get_aux("gamma") dens_base = dens[:, myg.jhi] ke_base = 0.5*(xmom[:, myg.jhi]**2 + ymom[:, myg.jhi]**2) / \ dens[:, myg.jhi] eint_base = (ener[:, myg.jhi] - ke_base) / dens[:, myg.jhi] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation for j in range(myg.jhi + 1, myg.jhi + myg.ng + 1): pres_above = pres_base + grav * dens_base * myg.dy rhoe = eos.rhoe(gamma, pres_above) ener[:, j] = rhoe + ke_base pres_base = pres_above.copy() else: raise NotImplementedError("variable not defined") else: msg.fail("error: hse BC not supported for xlb or xrb") elif bc_name == "ramp": # Boundary conditions for double Mach reflection problem gamma = ccdata.get_aux("gamma") if bc_edge == "xlb": # lower x boundary # inflow condition with post shock setup v = ccdata.get_var(variable) i = myg.ilo - 1 if variable in ["density", "x-momentum", "y-momentum", "energy"]: val = inflow_post_bc(variable, gamma) while i >= 0: v[i, :] = val i = i - 1 else: v[:, :] = 0.0 # no source term elif bc_edge == "ylb": # lower y boundary # for x > 1./6., reflective boundary # for x < 1./6., inflow with post shock setup if variable in ["density", "x-momentum", "y-momentum", "energy"]: v = ccdata.get_var(variable) j = myg.jlo - 1 jj = 0 while j >= 0: xcen_l = myg.x < 1.0 / 6.0 xcen_r = myg.x >= 1.0 / 6.0 v[xcen_l, j] = inflow_post_bc(variable, gamma) if variable == "y-momentum": v[xcen_r, j] = -1.0 * v[xcen_r, myg.jlo + jj] else: v[xcen_r, j] = v[xcen_r, myg.jlo + jj] j = j - 1 jj = jj + 1 else: v = ccdata.get_var(variable) v[:, :] = 0.0 # no source term elif bc_edge == "yrb": # upper y boundary # time-dependent boundary, the shockfront moves with a 10 mach velocity forming an angle # to the x-axis of 30 degrees clockwise. # x coordinate of the grid is used to judge whether the cell belongs to pure post shock area, # the pure pre shock area or the mixed area. if variable in ["density", "x-momentum", "y-momentum", "energy"]: v = ccdata.get_var(variable) for j in range(myg.jhi + 1, myg.jhi + myg.ng + 1): shockfront_up = 1.0/6.0 + (myg.y[j] + 0.5*myg.dy*math.sqrt(3))/math.tan(math.pi/3.0) \ + (10.0/math.sin(math.pi/3.0))*ccdata.t shockfront_down = 1.0/6.0 + (myg.y[j] - 0.5*myg.dy*math.sqrt(3))/math.tan(math.pi/3.0) \ + (10.0/math.sin(math.pi/3.0))*ccdata.t shockfront = np.array([shockfront_down, shockfront_up]) for i in range(myg.ihi + myg.ng + 1): v[i, j] = 0.0 cx_down = myg.x[i] - 0.5 * myg.dx * math.sqrt(3) cx_up = myg.x[i] + 0.5 * myg.dx * math.sqrt(3) cx = np.array([cx_down, cx_up]) for sf in shockfront: for x in cx: if x < sf: v[i, j] = v[i, j] + 0.25 * inflow_post_bc( variable, gamma) else: v[i, j] = v[i, j] + 0.25 * inflow_pre_bc( variable, gamma) else: v = ccdata.get_var(variable) v[:, :] = 0.0 # no source term else: msg.fail("error: bc type %s not supported" % (bc_name))
def user(bc_name, bc_edge, variable, my_data): """ A hydrostatic boundary. This integrates the equation of HSE into the ghost cells to get the pressure and density under the assumption that the specific internal energy is constant. Upon exit, the ghost cells for the input variable will be set Parameters ---------- bc_name : {'hse'} The descriptive name for the boundary condition -- this allows for pyro to have multiple types of user-supplied boundary conditions. For this module, it needs to be 'hse'. bc_edge : {'ylb', 'yrb'} The boundary to update: ylb = lower y boundary; yrb = upper y boundary. variable : {'density', 'x-momentum', 'y-momentum', 'energy'} The variable whose ghost cells we are filling my_data : CellCenterData2d object The data object """ dens = my_data.get_var("density") xmom = my_data.get_var("x-momentum") ymom = my_data.get_var("y-momentum") ener = my_data.get_var("energy") grav = my_data.get_aux("grav") gamma = my_data.get_aux("gamma") myg = my_data.grid if bc_name == "hse": if bc_edge == "ylb": # lower y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable == "density": j = myg.jlo - 1 while j >= 0: dens.d[:, j] = dens.d[:, myg.jlo] j -= 1 elif variable == "x-momentum": j = myg.jlo - 1 while j >= 0: xmom.d[:, j] = xmom.d[:, myg.jlo] j -= 1 elif variable == "y-momentum": j = myg.jlo - 1 while j >= 0: ymom.d[:, j] = ymom.d[:, myg.jlo] j -= 1 elif variable == "energy": dens_base = dens.d[:, myg.jlo] ke_base = 0.5*(xmom.d[:,myg.jlo]**2 + ymom.d[:,myg.jlo]**2) / \ dens.d[:,myg.jlo] eint_base = (ener.d[:, myg.jlo] - ke_base) / dens.d[:, myg.jlo] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation j = myg.jlo - 1 while (j >= 0): pres_below = pres_base - grav * dens_base * myg.dy rhoe = eos.rhoe(gamma, pres_below) ener.d[:, j] = rhoe + ke_base pres_base = pres_below.copy() j -= 1 else: msg.fail("error: variable not defined") elif bc_edge == "yrb": # upper y boundary # we will take the density to be constant, the velocity to # be outflow, and the pressure to be in HSE if variable == "density": for j in range(myg.jhi + 1, myg.jhi + myg.ng + 1): dens.d[:, j] = dens.d[:, myg.jhi] elif variable == "x-momentum": for j in range(myg.jhi + 1, myg.jhi + myg.ng + 1): xmom.d[:, j] = xmom.d[:, myg.jhi] elif variable == "y-momentum": for j in range(myg.jhi + 1, myg.jhi + myg.ng + 1): ymom.d[:, j] = ymom.d[:, myg.jhi] elif variable == "energy": dens_base = dens.d[:, myg.jhi] ke_base = 0.5*(xmom.d[:,myg.jhi]**2 + ymom.d[:,myg.jhi]**2) / \ dens.d[:,myg.jhi] eint_base = (ener.d[:, myg.jhi] - ke_base) / dens.d[:, myg.jhi] pres_base = eos.pres(gamma, dens_base, eint_base) # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation for j in range(myg.jhi + 1, myg.jhi + myg.ng + 1): pres_above = pres_base + grav * dens_base * myg.dy rhoe = eos.rhoe(gamma, pres_above) ener.d[:, j] = rhoe + ke_base pres_base = pres_above.copy() else: msg.fail("error: variable not defined") else: msg.fail("error: hse BC not supported for xlb or xrb") else: msg.fail("error: bc type %s not supported" % (bc_name))