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 = q[:, :, ivars.iu] v = q[:, :, ivars.iv] try: W = 1 / np.sqrt(1 - u**2 - v**2) except FloatingPointError: u[np.isnan(u)] = 0 v[np.isnan(v)] = 0 W = np.ones_like(u) rhoh = eos.rhoh_from_rho_p(gamma, q[:, :, ivars.irho], q[:, :, ivars.ip]) U[:, :, ivars.idens] = q[:, :, ivars.irho] * W U[:, :, ivars.ixmom] = u * rhoh * W**2 U[:, :, ivars.iymom] = v * rhoh * W**2 U[:, :, ivars.iener] = rhoh * W**2 - q[:, :, ivars.ip] - U[:, :, ivars.idens] 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]*W return U
def init_data(my_data, rp): """ an init routine for unit testing """ # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ERROR: patch invalid in sedov.py") print(my_data.__class__) sys.exit() # 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") gamma = rp.get_param("eos.gamma") # 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 # ener[:, :] = 2.5 p = 1.0 rhoh = eos.rhoh_from_rho_p(gamma, dens, p) # print(f'rhoh = {rhoh}') # u, v = 0 so W = 1 ener[:, :] = rhoh[:, :] - p - dens[:, :]
def init_data(my_data, rp): """ initialize the HSE problem """ msg.bold("initializing the HSE problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ERROR: patch invalid in hse.py") print(my_data.__class__) sys.exit() # 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") gamma = rp.get_param("eos.gamma") grav = rp.get_param("compressible.grav") dens0 = rp.get_param("hse.dens0") print("dens0 = ", dens0) H = rp.get_param("hse.h") # isothermal sound speed (squared) cs2 = H * abs(grav) # initialize the components, remember, that ener here is # rho*eint + 0.5*rho*v**2, where eint is the specific # internal energy (erg/g) xmom[:, :] = 0.0 ymom[:, :] = 0.0 dens[:, :] = 0.0 # set the density to be stratified in the y-direction myg = my_data.grid p = myg.scratch_array() for j in range(myg.jlo, myg.jhi + 1): dens[:, j] = dens0 * np.exp(-myg.y[j] / H) if j == myg.jlo: p[:, j] = dens[:, j] * cs2 else: p[:, j] = p[:, j - 1] + 0.5 * myg.dy * (dens[:, j] + dens[:, j - 1]) * grav # # set the energy # ener[:, :] = p[:, :]/(gamma - 1.0) + \ # 0.5*(xmom[:, :]**2 + ymom[:, :]**2)/dens[:, :] # W = 1 rhoh = eos.rhoh_from_rho_p(gamma, dens, p) ener[:, :] = rhoh - p - dens
def init_data(my_data, rp): """ initialize a smooth advection problem for testing convergence """ msg.bold("initializing the advect problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ERROR: patch invalid in advect.py") print(my_data.__class__) sys.exit() # 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[:, :] = 0.2 xmom[:, :] = 0.0 ymom[:, :] = 0.0 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") xctr = 0.5 * (xmin + xmax) yctr = 0.5 * (ymin + ymax) # this is identical to the advection/smooth problem dens[:, :] = 0.2 * (1 + np.exp(-60.0 * ((my_data.grid.x2d - xctr)**2 + (my_data.grid.y2d - yctr)**2))) # velocity is diagonal u = 0.4 v = 0.4 # pressure is constant p = 0.2 rhoh = eos.rhoh_from_rho_p(gamma, dens, p) W = 1. / np.sqrt(1 - u**2 - v**2) dens[:, :] *= W xmom[:, :] = rhoh[:, :] * u * W**2 ymom[:, :] = rhoh[:, :] * v * W**2 ener[:, :] = rhoh[:, :] * W**2 - p - dens[:, :]
def init_data(myd, rp): """initialize the acoustic_pulse problem. This comes from McCourquodale & Coella 2011""" msg.bold("initializing the acoustic pulse problem...") # make sure that we are passed a valid patch object # if not isinstance(myd, fv.FV2d): # print("ERROR: patch invalid in acoustic_pulse.py") # print(myd.__class__) # sys.exit() # get the density, momenta, and energy as separate variables dens = myd.get_var("density") xmom = myd.get_var("x-momentum") ymom = myd.get_var("y-momentum") ener = myd.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) xmom[:, :] = 0.0 ymom[:, :] = 0.0 gamma = rp.get_param("eos.gamma") rho0 = rp.get_param("acoustic_pulse.rho0") drho0 = rp.get_param("acoustic_pulse.drho0") xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") xctr = 0.5 * (xmin + xmax) yctr = 0.5 * (ymin + ymax) dist = np.sqrt((myd.grid.x2d - xctr)**2 + (myd.grid.y2d - yctr)**2) dens[:, :] = rho0 idx = dist <= 0.5 dens[idx] = rho0 + drho0 * np.exp(-16 * dist[idx]**2) * np.cos( np.pi * dist[idx])**6 p = (dens / rho0)**gamma ener[:, :] = p / (gamma - 1) rhoh = eos.rhoh_from_rho_p(gamma, dens, p) ener[:, :] = rhoh[:, :] - p - dens[:, :]
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 h = eos.h_from_eps(gamma, eint) assert (1 + gamma*eint) == h rhoh = eos.rhoh_from_rho_p(gamma, dens, p) assert dens*h == rhoh
def init_data(my_data, rp): """ initialize the bubble problem """ msg.bold("initializing the bubble problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ERROR: patch invalid in bubble.py") print(my_data.__class__) sys.exit() # 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") gamma = rp.get_param("eos.gamma") grav = rp.get_param("compressible.grav") scale_height = rp.get_param("bubble.scale_height") dens_base = rp.get_param("bubble.dens_base") dens_cutoff = rp.get_param("bubble.dens_cutoff") x_pert = rp.get_param("bubble.x_pert") y_pert = rp.get_param("bubble.y_pert") r_pert = rp.get_param("bubble.r_pert") pert_amplitude_factor = rp.get_param("bubble.pert_amplitude_factor") # initialize the components, remember, that ener here is # rho*eint + 0.5*rho*v**2, where eint is the specific # internal energy (erg/g) xmom[:, :] = 0.0 ymom[:, :] = 0.0 dens[:, :] = dens_cutoff # set the density to be stratified in the y-direction myg = my_data.grid p = myg.scratch_array() cs2 = scale_height * abs(grav) for j in range(myg.jlo, myg.jhi + 1): dens[:, j] = max(dens_base * np.exp(-myg.y[j] / scale_height), dens_cutoff) if j == myg.jlo: p[:, j] = dens[:, j] * cs2 else: p[:, j] = p[:, j - 1] + 0.5 * myg.dy * (dens[:, j] + dens[:, j - 1]) * grav # set the energy (P = cs2*dens) ener[:, :] = p[:, :]/(gamma - 1.0) + \ 0.5*(xmom[:, :]**2 + ymom[:, :]**2)/dens[:, :] r = np.sqrt((myg.x2d - x_pert)**2 + (myg.y2d - y_pert)**2) idx = r <= r_pert # boost the specific internal energy, keeping the pressure # constant, by dropping the density eint = (ener[idx] - 0.5 * (xmom[idx]**2 - ymom[idx]**2) / dens[idx]) / dens[idx] pres = dens[idx] * eint * (gamma - 1.0) eint = eint * pert_amplitude_factor dens[idx] = pres / (eint * (gamma - 1.0)) ener[idx] = dens[idx] * eint + 0.5 * (xmom[idx]**2 + ymom[idx]**2) / dens[idx] # p[idx] = pres rhoh = eos.rhoh_from_rho_p(gamma, dens, p) W = 1 / (np.sqrt(1 - (xmom**2 - ymom**2) / dens)) dens[:, :] *= W xmom[:, :] *= rhoh[:, :] / dens * W**2 ymom[:, :] *= rhoh[:, :] / dens * W**2 # HACK: didn't work but W = 1 so shall cheat ener[:, :] = rhoh[:, :] * W**2 - p - dens[:, :]
def init_data(my_data, rp): """ initialize the sedov problem """ msg.bold("initializing the logo problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ERROR: patch invalid in sedov.py") print(my_data.__class__) sys.exit() # create the logo myg = my_data.grid fig = plt.figure(2, (0.64, 0.64), dpi=100 * myg.nx / 64) fig.add_subplot(111) fig.text(0.5, 0.5, "pyro", transform=fig.transFigure, fontsize="16", horizontalalignment="center", verticalalignment="center") plt.axis("off") fig.canvas.draw() data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='') data = data.reshape(fig.canvas.get_width_height()[::-1] + (3, )) logo = np.rot90(np.rot90(np.rot90((256 - data[:, :, 1]) / 255.0))) # 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") myg = my_data.grid # initialize the components, remember, that ener here is rho*eint # + 0.5*rho*v**2, where eint is the specific internal energy # (erg/g) xmom[:, :] = 0.0 ymom[:, :] = 0.0 # set the density in the logo zones to be really large logo_dens = 0.1 dens[:, :] = logo_dens * (0.5 + logo[0, 0]) dens.v()[:, :] = (0.5 + logo[:, :]) * logo_dens # pressure equilibrium gamma = rp.get_param("eos.gamma") p_ambient = 1.e-1 p = myg.scratch_array(nvar=1) p[:, :] = p_ambient * (0.8 + logo[0, 0]) p.v()[:, :] *= (0.8 + logo[:, :]) # ener[:, :] = p/(gamma - 1.0) # ener.v()[:, :] *= (0.2 + logo[:, :]) rhoh = eos.rhoh_from_rho_p(gamma, dens, p) u = xmom / dens v = ymom / dens W = 1. / np.sqrt(1 - u**2 - v**2) dens[:, :] *= W xmom[:, :] = rhoh[:, :] * u * W**2 ymom[:, :] = rhoh[:, :] * v * W**2 ener[:, :] = rhoh[:, :] * W**2 - p - dens[:, :]
def init_data(my_data, rp): """ initialize the sedov 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("ERROR: patch invalid in sedov.py") print(my_data.__class__) sys.exit() # 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 E_sedov = 2.0e-3 r_init = rp.get_param("sedov.r_init") gamma = rp.get_param("eos.gamma") pi = math.pi xmin = rp.get_param("mesh.xmin") xmax = rp.get_param("mesh.xmax") ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") xctr = 0.5 * (xmin + xmax) yctr = 0.5 * (ymin + ymax) # initialize the pressure by putting the explosion energy into a # volume of constant pressure. Then compute the energy in a zone # from this. nsub = rp.get_param("sedov.nsub") dist = np.sqrt((my_data.grid.x2d - xctr)**2 + (my_data.grid.y2d - yctr)**2) p = 1.e-5 ener[:, :] = p / (gamma - 1.0) for i, j in np.transpose(np.nonzero(dist < 2.0 * r_init)): xsub = my_data.grid.xl[i] + (my_data.grid.dx / nsub) * (np.arange(nsub) + 0.5) ysub = my_data.grid.yl[j] + (my_data.grid.dy / nsub) * (np.arange(nsub) + 0.5) xx, yy = np.meshgrid(xsub, ysub, indexing="ij") dist = np.sqrt((xx - xctr)**2 + (yy - yctr)**2) n_in_pert = np.count_nonzero(dist <= r_init) p = n_in_pert*(gamma - 1.0)*E_sedov/(pi*r_init*r_init) + \ (nsub*nsub - n_in_pert)*1.e-5 p = p / (nsub * nsub) # # ener[i, j] = p/(gamma - 1.0) # W = 1 rhoh = eos.rhoh_from_rho_p(gamma, dens[i, j], p) ener[i, j] = rhoh - p - dens[i, j]
def init_data(my_data, rp): """ initialize the Gresho vortex problem """ msg.bold("initializing the Gresho vortex problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ErrrrOrr: patch invalid in bubble.py") print(my_data.__class__) sys.exit() # get the density and velocities 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") gamma = rp.get_param("eos.gamma") dens_base = rp.get_param("gresho.dens_base") rr = rp.get_param("gresho.r") u0 = rp.get_param("gresho.u0") p0 = rp.get_param("gresho.p0") # initialize the components -- we'll get a psure too # but that is used only to initialize the base state xmom[:, :] = 0.0 ymom[:, :] = 0.0 # set the density to be stratified in the y-direction myg = my_data.grid pres = myg.scratch_array() dens[:, :] = dens_base pres[:, :] = p0 x_centre = 0.5 * (myg.x[0] + myg.x[-1]) y_centre = 0.5 * (myg.y[0] + myg.y[-1]) rad = np.sqrt((myg.x2d - x_centre)**2 + (myg.y2d - y_centre)**2) pres[rad <= rr] += 0.5 * (u0 * rad[rad <= rr] / rr)**2 pres[(rad > rr) & (rad <= 2*rr)] += u0**2 * \ (0.5 * (rad[(rad > rr) & (rad <= 2*rr)]/rr)**2 + 4 * (1 - rad[(rad > rr) & (rad <= 2*rr)]/rr + np.log(rad[(rad > rr) & (rad <= 2*rr)]/rr))) pres[rad > 2 * rr] += u0**2 * (4 * np.log(2) - 2) # print(p[rad > 2*rr]) # uphi = np.zeros_like(pres) uphi[rad <= rr] = u0 * rad[rad <= rr] / rr uphi[(rad > rr) & (rad <= 2 * rr)] = u0 * (2 - rad[(rad > rr) & (rad <= 2 * rr)] / rr) xmom[:, :] = -uphi[:, :] * (myg.y2d - y_centre) / rad[:, :] ymom[:, :] = uphi[:, :] * (myg.x2d - x_centre) / rad[:, :] # rhoe # enerad[:, :] = p[:, :]/(gamma - 1.0) + \ # 0.5*(xmom[:, :]**2 + ymom[:, :]**2)/dens[:, :] # dens[:, :] = p[:, :]/(eint[:, :]*(gamma - 1.0)) rhoh = eos.rhoh_from_rho_p(gamma, dens, pres) w_lor = 1. / np.sqrt(1. - xmom**2 - ymom**2) dens[:, :] *= w_lor xmom[:, :] *= rhoh * w_lor**2 ymom[:, :] *= rhoh * w_lor**2 ener[:, :] = rhoh * w_lor**2 - pres - dens
def init_data(my_data, rp): """ initialize the sod 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 sod.py") print(my_data.__class__) sys.exit() # get the sod parameters dens_left = rp.get_param("sod.dens_left") dens_right = rp.get_param("sod.dens_right") u_left = rp.get_param("sod.u_left") u_right = rp.get_param("sod.u_right") p_left = rp.get_param("sod.p_left") p_right = rp.get_param("sod.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("sod.direction") xctr = 0.5 * (xmin + xmax) yctr = 0.5 * (ymin + ymax) myg = my_data.grid p = np.ones_like(dens) * p_left dens[:, :] = dens_left if direction == "x": # left idxl = myg.x2d <= xctr dens[idxl] = dens_left xmom[idxl] = u_left ymom[idxl] = 0.0 # ener[idxl] = p_left/(gamma - 1.0) + 0.5*xmom[idxl]*u_left p[idxl] = p_left # right idxr = myg.x2d > xctr dens[idxr] = dens_right xmom[idxr] = u_right ymom[idxr] = 0.0 # ener[idxr] = p_right/(gamma - 1.0) + 0.5*xmom[idxr]*u_right p[idxr] = p_right else: # bottom idxb = myg.y2d <= yctr dens[idxb] = dens_left xmom[idxb] = 0.0 ymom[idxb] = u_left # ener[idxb] = p_left/(gamma - 1.0) + 0.5*ymom[idxb]*u_left p[idxb] = p_left # top idxt = myg.y2d > yctr dens[idxt] = dens_right xmom[idxt] = 0.0 ymom[idxt] = u_right # ener[idxt] = p_right/(gamma - 1.0) + 0.5*ymom[idxt]*u_right p[idxt] = p_right rhoh = eos.rhoh_from_rho_p(gamma, dens, p) W = 1. / np.sqrt(1 - xmom**2 - ymom**2) dens[:, :] *= W xmom[:, :] *= rhoh * W**2 ymom[:, :] *= rhoh * W**2 ener[:, :] = rhoh * W**2 - p - dens
def init_data(my_data, rp): """ initialize the Kelvin-Helmholtz problem """ msg.bold("initializing the Kelvin-Helmholtz 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 kh.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") myg = my_data.grid dy = 0.025 w0 = 0.01 vm = 0.5 * (v_1 - v_2) rhom = 0.5 * (rho_1 - rho_2) idx1 = myg.y2d < 0.25 idx2 = np.logical_and(myg.y2d >= 0.25, myg.y2d < 0.5) idx3 = np.logical_and(myg.y2d >= 0.5, myg.y2d < 0.75) idx4 = myg.y2d >= 0.75 # we will initialize momemum as velocity for now # lower quarter dens[idx1] = rho_1 - rhom * np.exp((myg.y2d[idx1] - 0.25) / dy) xmom[idx1] = v_1 - vm * np.exp((myg.y2d[idx1] - 0.25) / dy) # second quarter dens[idx2] = rho_2 + rhom * np.exp((0.25 - myg.y2d[idx2]) / dy) xmom[idx2] = v_2 + vm * np.exp((0.25 - myg.y2d[idx2]) / dy) # third quarter dens[idx3] = rho_2 + rhom * np.exp((myg.y2d[idx3] - 0.75) / dy) xmom[idx3] = v_2 + vm * np.exp((myg.y2d[idx3] - 0.75) / dy) # fourth quarter dens[idx4] = rho_1 - rhom * np.exp((0.75 - myg.y2d[idx4]) / dy) xmom[idx4] = v_1 - vm * np.exp((0.75 - myg.y2d[idx4]) / dy) # upper half xmom[:, :] *= dens ymom[:, :] = dens * w0 * np.sin(4 * np.pi * myg.x2d) p = 2.5 ener[:, :] = p / (gamma - 1.0) + 0.5 * (xmom[:, :]**2 + ymom[:, :]**2) / dens[:, :] rhoh = eos.rhoh_from_rho_p(gamma, dens, p) u = xmom / dens v = ymom / dens W = 1. / np.sqrt(1 - u**2 - v**2) dens[:, :] *= W xmom[:, :] = rhoh[:, :] * u * W**2 ymom[:, :] = rhoh[:, :] * v * W**2 ener[:, :] = rhoh[:, :] * W**2 - p - dens[:, :]
def user(bc_name, bc_edge, variable, ccdata, ivars): """ 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") q = flx.cons_to_prim_wrapper(ccdata.data, gamma, ivars, myg) rho = q[:, :, ivars.irho] u = q[:, myg.jlo, ivars.iu] v = q[:, myg.jlo, ivars.iv] p = q[:, :, ivars.ip] dens_base = rho[:, myg.jlo] # ke_base = 0.5*(u[:, myg.jlo]**2 + v[:, myg.jlo]**2) * rho[:, myg.jlo] # eint_base = (ener[:, myg.jlo] - ke_base)/dens[:, myg.jlo] # pres_base = eos.pres(gamma, dens_base, eint_base) pres_base = p[:, myg.jlo] # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation W = np.sqrt(1 - u**2 - v**2) j = myg.jlo - 1 while j >= 0: pres_below = pres_base - grav * dens_base * myg.dy rhoh = eos.rhoh_from_rho_p(gamma, dens_base, pres_below) ener[:, j] = rhoh * W**2 - pres_below - dens_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") q = flx.cons_to_prim_wrapper(ccdata.data, gamma, ivars, myg) rho = q[:, :, ivars.irho] u = q[:, myg.jhi, ivars.iu] v = q[:, myg.jhi, ivars.iv] p = q[:, :, ivars.ip] dens_base = rho[:, 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) pres_base = p[:, myg.jhi] # we are assuming that the density is constant in this # formulation of HSE, so the pressure comes simply from # differencing the HSE equation W = np.sqrt(1 - u**2 - v**2) 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) rhoh = eos.rhoh_from_rho_p(gamma, dens_base, pres_above) # ener[:, j] = rhoe + ke_base ener[:, j] = rhoh * W**2 - pres_above - dens_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 init_data(my_data, rp): """ initialize the rt problem """ msg.bold("initializing the rt problem...") # make sure that we are passed a valid patch object if not isinstance(my_data, patch.CellCenterData2d): print("ERROR: patch invalid in rt.py") print(my_data.__class__) sys.exit() # 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") gamma = rp.get_param("eos.gamma") grav = rp.get_param("compressible.grav") dens1 = rp.get_param("rt.dens1") dens2 = rp.get_param("rt.dens2") p0 = rp.get_param("rt.p0") amp = rp.get_param("rt.amp") sigma = rp.get_param("rt.sigma") # initialize the components, remember, that ener here is # rho*eint + 0.5*rho*v**2, where eint is the specific # internal energy (erg/g) xmom[:, :] = 0.0 ymom[:, :] = 0.0 dens[:, :] = 0.0 # set the density to be stratified in the y-direction myg = my_data.grid ycenter = 0.5 * (myg.ymin + myg.ymax) p = myg.scratch_array() p[:, :] = p0 dens[:, :] = dens1 for j in range(myg.jlo, myg.jhi + 1): if (myg.y[j] < ycenter): dens[:, j] = dens1 p[:, j] = p0 + dens1 * grav * myg.y[j] else: dens[:, j] = dens2 p[:, j] = p0 + dens1 * grav * ycenter + dens2 * grav * (myg.y[j] - ycenter) ymom[:, :] = amp * np.cos(2.0 * np.pi * myg.x2d / (myg.xmax - myg.xmin)) * np.exp( -(myg.y2d - ycenter)**2 / sigma**2) rhoh = eos.rhoh_from_rho_p(gamma, dens, p) u = xmom v = ymom W = 1. / np.sqrt(1 - u**2 - v**2) dens[:, :] *= W xmom[:, :] *= rhoh[:, :] * W**2 ymom[:, :] *= rhoh[:, :] * W**2 ener[:, :] = rhoh[:, :] * W**2 - p - dens[:, :]