From c14b4196536f4f6c435195f7757ef315c2485b50 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Mon, 25 Feb 2019 16:59:35 -0500 Subject: [PATCH 01/21] mapped grids --- compressible/interface.py | 4 ++-- mesh/__init__.py | 2 +- pyro.py | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compressible/interface.py b/compressible/interface.py index 7862ea807..2b9ccfc9c 100644 --- a/compressible/interface.py +++ b/compressible/interface.py @@ -419,7 +419,7 @@ def riemann_cgf(idir, ng, lambdastar_r = ustar + cstar_r if (pstar > p_r): - # the wave if a shock -- find the shock speed + # the wave is a shock -- find the shock speed sigma = (lambda_r + lambdastar_r) / 2.0 if (sigma > 0.0): @@ -713,7 +713,7 @@ def riemann_prim(idir, ng, lambdastar_r = ustar + cstar_r if (pstar > p_r): - # the wave if a shock -- find the shock speed + # the wave is a shock -- find the shock speed sigma = (lambda_r + lambdastar_r) / 2.0 if (sigma > 0.0): diff --git a/mesh/__init__.py b/mesh/__init__.py index a6ebd9498..3ad171429 100644 --- a/mesh/__init__.py +++ b/mesh/__init__.py @@ -3,4 +3,4 @@ necessary to work with finite-volume data. """ -__all__ = ['patch', 'integration', 'reconstruction'] +__all__ = ['integration', 'mapped', 'patch', 'reconstruction'] diff --git a/pyro.py b/pyro.py index 67de7b688..a2dcc1657 100755 --- a/pyro.py +++ b/pyro.py @@ -19,6 +19,7 @@ "compressible", "compressible_rk", "compressible_fv4", + "compressible_mapped", "compressible_sdc", "compressible_react", "diffusion", From a6fb2b152fd81b790de3e30f08333bc927e955ab Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Mon, 25 Feb 2019 17:00:04 -0500 Subject: [PATCH 02/21] mapped grids --- compressible_mapped/__init__.py | 8 ++ compressible_mapped/_defaults | 28 +++++ compressible_mapped/fluxes.py | 201 ++++++++++++++++++++++++++++++ compressible_mapped/problems | 1 + compressible_mapped/simulation.py | 100 +++++++++++++++ 5 files changed, 338 insertions(+) create mode 100644 compressible_mapped/__init__.py create mode 100644 compressible_mapped/_defaults create mode 100644 compressible_mapped/fluxes.py create mode 120000 compressible_mapped/problems create mode 100644 compressible_mapped/simulation.py diff --git a/compressible_mapped/__init__.py b/compressible_mapped/__init__.py new file mode 100644 index 000000000..8e9910c89 --- /dev/null +++ b/compressible_mapped/__init__.py @@ -0,0 +1,8 @@ +"""A method-of-lines compressible hydrodynamics solver. Piecewise +constant reconstruction is done in space and a Runge-Kutta time +integration is used to advance the solutiion. + +""" +__all__ = ["simulation"] + +from .simulation import Simulation diff --git a/compressible_mapped/_defaults b/compressible_mapped/_defaults new file mode 100644 index 000000000..be64a2995 --- /dev/null +++ b/compressible_mapped/_defaults @@ -0,0 +1,28 @@ +[driver] +cfl = 0.8 + + +[eos] +gamma = 1.4 ; pres = rho ener (gamma - 1) + + +[compressible] +use_flattening = 1 ; apply flattening at shocks (1) + +z0 = 0.75 ; flattening z0 parameter +z1 = 0.85 ; flattening z1 parameter +delta = 0.33 ; flattening delta parameter + +cvisc = 0.1 ; artifical viscosity coefficient + +limiter = 2 ; limiter (0 = none, 1 = 2nd order, 2 = 4th order) + +temporal_method = RK4 ; integration method (see mesh/integration.py) + +grav = 0.0 ; gravitational acceleration (in y-direction) + +riemann = HLLC ; HLLC or CGF + +well_balanced = 0 ; use a well-balanced scheme to keep the model in hydrostatic equilibrium + + diff --git a/compressible_mapped/fluxes.py b/compressible_mapped/fluxes.py new file mode 100644 index 000000000..6f3428e55 --- /dev/null +++ b/compressible_mapped/fluxes.py @@ -0,0 +1,201 @@ +""" +This is a 2nd-order PLM method for a method-of-lines integration +(i.e., no characteristic tracing). + +We wish to solve + +.. math:: + + U_t + F^x_x + F^y_y = H + +we want U_{i+1/2} -- the interface values that are input to +the Riemann problem through the faces for each zone. + +Taylor expanding *in space only* yields:: + + dU + U = U + 0.5 dx -- + i+1/2,j,L i,j dx + +""" + +import compressible.interface as interface +import compressible as comp +import mesh.reconstruction as reconstruction +import mesh.array_indexer as ai + +from util import msg + + +def fluxes(my_data, rp, ivars, 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 + U = my_data.data + + # ========================================================================= + # transform by rotating the velocity components + # ========================================================================= + + U_xl = myg.R_fcy * U.ip(-1) + U_xr = myg.R_fcy * U.v() + + U_yl = myg.R_fcx * U.jp(-1) + U_yr = myg.R_fcx * U.v() + + gamma = rp.get_param("eos.gamma") + # + # # ========================================================================= + # # compute the primitive variables + # # ========================================================================= + # # Q = (rho, u, v, p) + # + # q = comp.cons_to_prim(my_data.data, gamma, ivars, myg) + # + # # ========================================================================= + # # 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: + # xi_x = reconstruction.flatten(myg, q, 1, ivars, rp) + # xi_y = reconstruction.flatten(myg, q, 2, ivars, rp) + # + # xi = reconstruction.flatten_multid(myg, q, xi_x, xi_y, ivars) + # else: + # xi = 1.0 + # + # # monotonized central differences in x-direction + # tm_limit = tc.timer("limiting") + # tm_limit.begin() + # + # limiter = rp.get_param("compressible.limiter") + # + # ldx = myg.scratch_array(nvar=ivars.nvar) + # ldy = myg.scratch_array(nvar=ivars.nvar) + # + # for n in range(ivars.nvar): + # ldx[:, :, n] = xi * reconstruction.limit(q[:, :, n], myg, 1, limiter) + # ldy[:, :, n] = xi * reconstruction.limit(q[:, :, n], myg, 2, limiter) + # + # tm_limit.end() + # + # # ========================================================================= + # # x-direction + # # ========================================================================= + # + # # left and right primitive variable states + # tm_states = tc.timer("interfaceStates") + # tm_states.begin() + # + # V_l = myg.scratch_array(ivars.nvar) + # V_r = myg.scratch_array(ivars.nvar) + # + # for n in range(ivars.nvar): + # V_l.ip(1, n=n, buf=2)[:, :] = q.v(n=n, buf=2) + 0.5 * ldx.v(n=n, buf=2) + # V_r.v(n=n, buf=2)[:, :] = q.v(n=n, buf=2) - 0.5 * ldx.v(n=n, buf=2) + # + # tm_states.end() + # + # # transform interface states back into conserved variables + # U_xl = comp.prim_to_cons(V_l, gamma, ivars, myg) + # U_xr = comp.prim_to_cons(V_r, gamma, ivars, myg) + # + # # ========================================================================= + # # y-direction + # # ========================================================================= + # + # # left and right primitive variable states + # tm_states.begin() + # + # for n in range(ivars.nvar): + # V_l.jp(1, n=n, buf=2)[:, :] = q.v(n=n, buf=2) + 0.5 * ldy.v(n=n, buf=2) + # V_r.v(n=n, buf=2)[:, :] = q.v(n=n, buf=2) - 0.5 * ldy.v(n=n, buf=2) + # + # tm_states.end() + # + # # transform interface states back into conserved variables + # U_yl = comp.prim_to_cons(V_l, gamma, ivars, myg) + # U_yr = comp.prim_to_cons(V_r, gamma, ivars, myg) + + # ========================================================================= + # 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.riemann_hllc + elif riemann == "CGF": + riemannFunc = interface.riemann_cgf + else: + msg.fail("ERROR: Riemann solver undefined") + + _fx = riemannFunc(1, myg.ng, + ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux, + solid.xl, solid.xr, + gamma, U_xl, U_xr) + + _fy = riemannFunc(2, myg.ng, + ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux, + 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() + + # ========================================================================= + # transform back + # ========================================================================= + + q_star_x = U_xl[:, :, :] + F_x[:, :, :] + + A_plus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ + (interface.consFlux(U_xr) - interface.consFlux(q_star_x)) + A_minus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ + (interface.consFlux(q_star_x) - interface.consFlux(U_xl)) + + q_star_y = U_yl[:, :, :] + F_y[:, :, :] + + A_plus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ + (interface.consFlux(U_yr) - interface.consFlux(q_star_y)) + A_minus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ + (interface.consFlux(q_star_y) - interface.consFlux(U_yl)) + + tm_flux.end() + + return A_plus_delta_q_x, A_minus_delta_q_x, A_plus_delta_q_y, A_minus_delta_q_y diff --git a/compressible_mapped/problems b/compressible_mapped/problems new file mode 120000 index 000000000..cd5a359e2 --- /dev/null +++ b/compressible_mapped/problems @@ -0,0 +1 @@ +compressible/problems/ \ No newline at end of file diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py new file mode 100644 index 000000000..88aaeb18b --- /dev/null +++ b/compressible_mapped/simulation.py @@ -0,0 +1,100 @@ +from __future__ import print_function + +import numpy as np + +import mesh.integration as integration +import compressible +import compressible_mapped.fluxes as flx + + +class Simulation(compressible.Simulation): + """The main simulation class for the method of lines compressible + hydrodynamics solver""" + + def substep(self, myd): + """ + take a single substep in the RK timestepping starting with the + conservative state defined as part of myd + """ + + myg = myd.grid + grav = self.rp.get_param("compressible.grav") + + # compute the source terms + dens = myd.get_var("density") + ymom = myd.get_var("y-momentum") + + ymom_src = myg.scratch_array() + ymom_src.v()[:, :] = dens.v()[:, :]*grav + + E_src = myg.scratch_array() + E_src.v()[:, :] = ymom.v()[:, :]*grav + + k = myg.scratch_array(nvar=self.ivars.nvar) + + flux_x, flux_y = flx.fluxes(myd, self.rp, + self.ivars, self.solid, self.tc) + + for n in range(self.ivars.nvar): + k.v(n=n)[:, :] = \ + (flux_x.v(n=n) - flux_x.ip(1, n=n))/(myg.dx * myg.kappa) + \ + (flux_y.v(n=n) - flux_y.jp(1, n=n))/(myg.dy * myg.kappa) + + k.v(n=self.ivars.iymom)[:, :] += ymom_src.v()[:, :] + k.v(n=self.ivars.iener)[:, :] += E_src.v()[:, :] + + return k + + 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") + + # get the variables we need + u, v, cs = self.cc_data.get_var(["velocity", "soundspeed"]) + + # the timestep is min(dx/(|u| + cs), dy/(|v| + cs)) + xtmp = (abs(u) + cs)/self.cc_data.grid.dx + ytmp = (abs(v) + cs)/self.cc_data.grid.dy + + self.dt = cfl*float(np.min(1.0/(xtmp + ytmp))) + + 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 + + method = self.rp.get_param("compressible.temporal_method") + + rk = integration.RKIntegrator(myd.t, self.dt, method=method) + rk.set_start(myd) + + for s in range(rk.nstages()): + ytmp = rk.get_stage_start(s) + ytmp.fill_BC_all() + k = self.substep(ytmp) + rk.store_increment(s, k) + + rk.compute_final_update() + + 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() From 9c3270c703635e09594a978510e5445bd3618ccf Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Tue, 26 Feb 2019 09:29:05 -0500 Subject: [PATCH 03/21] mapped grids works with all cartesian metric --- compressible/problems/acoustic_pulse.py | 10 +- compressible_mapped/fluxes.py | 81 ++++++++++--- compressible_mapped/problems | 2 +- compressible_mapped/simulation.py | 148 ++++++++++++++++++++---- 4 files changed, 196 insertions(+), 45 deletions(-) diff --git a/compressible/problems/acoustic_pulse.py b/compressible/problems/acoustic_pulse.py index 1f98e5ada..37e75ac04 100644 --- a/compressible/problems/acoustic_pulse.py +++ b/compressible/problems/acoustic_pulse.py @@ -12,11 +12,11 @@ def init_data(myd, rp): 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() + # # 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") diff --git a/compressible_mapped/fluxes.py b/compressible_mapped/fluxes.py index 6f3428e55..d3e02f614 100644 --- a/compressible_mapped/fluxes.py +++ b/compressible_mapped/fluxes.py @@ -19,6 +19,8 @@ """ +import numpy as np + import compressible.interface as interface import compressible as comp import mesh.reconstruction as reconstruction @@ -65,11 +67,19 @@ def fluxes(my_data, rp, ivars, solid, tc): # transform by rotating the velocity components # ========================================================================= - U_xl = myg.R_fcy * U.ip(-1) - U_xr = myg.R_fcy * U.v() + U_xl = myg.scratch_array(nvar=ivars.nvar) + U_xr = myg.scratch_array(nvar=ivars.nvar) + + U_yl = myg.scratch_array(nvar=ivars.nvar) + U_yr = myg.scratch_array(nvar=ivars.nvar) + + b = 3 - U_yl = myg.R_fcx * U.jp(-1) - U_yr = myg.R_fcx * U.v() + for n in range(ivars.nvar): + U_xl.v(n=n, buf=b)[:, :] = myg.R_fcy.v(buf=b) * U.ip(-1, n=n, buf=b) + U_xr.v(n=n, buf=b)[:, :] = myg.R_fcy.v(buf=b) * U.v(n=n, buf=b) + U_yl.v(n=n, buf=b)[:, :] = myg.R_fcx.v(buf=b) * U.jp(-1, n=n, buf=b) + U_yr.v(n=n, buf=b)[:, :] = myg.R_fcx.v(buf=b) * U.v(n=n, buf=b) gamma = rp.get_param("eos.gamma") # @@ -182,19 +192,56 @@ def fluxes(my_data, rp, ivars, solid, tc): # transform back # ========================================================================= - q_star_x = U_xl[:, :, :] + F_x[:, :, :] - - A_plus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ - (interface.consFlux(U_xr) - interface.consFlux(q_star_x)) - A_minus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ - (interface.consFlux(q_star_x) - interface.consFlux(U_xl)) - - q_star_y = U_yl[:, :, :] + F_y[:, :, :] - - A_plus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ - (interface.consFlux(U_yr) - interface.consFlux(q_star_y)) - A_minus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ - (interface.consFlux(q_star_y) - interface.consFlux(U_yl)) + nx = myg.qx - 2 * myg.ng + ny = myg.qy - 2 * myg.ng + ilo = myg.ng + ihi = myg.ng + nx + jlo = myg.ng + jhi = myg.ng + ny + + A_plus_delta_q_x = myg.scratch_array(nvar=ivars.nvar) + A_minus_delta_q_x = myg.scratch_array(nvar=ivars.nvar) + A_plus_delta_q_y = myg.scratch_array(nvar=ivars.nvar) + A_minus_delta_q_y = myg.scratch_array(nvar=ivars.nvar) + + for i in range(ilo - 1, ihi + 1): + for j in range(jlo - 1, jhi + 1): + + A_plus_delta_q_x[i, j, :] = myg.gamma_fcy[i,j] * myg.R_T_fcy[i,j] * (interface.consFlux(1, gamma, ivars.idens, + ivars.ixmom, ivars.iymom, + ivars.iener, ivars.irhox, + ivars.naux, U_xr[i, j, :]) + - F_x[i, j, :]) + A_minus_delta_q_x[i, j, :] = myg.gamma_fcy[i,j] * myg.R_T_fcy[i,j] * (F_x[i, j, :] - + interface.consFlux(1, gamma, ivars.idens, + ivars.ixmom, ivars.iymom, ivars.iener, + ivars.irhox, ivars.naux, + U_xl[i, j, :])) + + A_plus_delta_q_y[i, j, :] = myg.gamma_fcx[i,j] * myg.R_T_fcx[i,j] * (interface.consFlux(2, gamma, ivars.idens, + ivars.ixmom, ivars.iymom, + ivars.iener, ivars.irhox, + ivars.naux, U_yr[i, j, :]) + - F_y[i, j, :]) + A_minus_delta_q_y[i, j, :] = myg.gamma_fcx[i,j] * myg.R_T_fcx[i,j] * (F_y[i, j, :] - + interface.consFlux(2, gamma, ivars.idens, + ivars.ixmom, ivars.iymom, + ivars.iener, ivars.irhox, + ivars.naux, U_yl[i, j, :])) + + # q_star_x = U_xl[:, :, :] + F_x[:, :, :] + # + # A_plus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ + # (interface.consFlux(U_xr) - interface.consFlux(q_star_x)) + # A_minus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ + # (interface.consFlux(q_star_x) - interface.consFlux(U_xl)) + # + # q_star_y = U_yl[:, :, :] + F_y[:, :, :] + # + # A_plus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ + # (interface.consFlux(U_yr) - interface.consFlux(q_star_y)) + # A_minus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ + # (interface.consFlux(q_star_y) - interface.consFlux(U_yl)) tm_flux.end() diff --git a/compressible_mapped/problems b/compressible_mapped/problems index cd5a359e2..37685ab1b 120000 --- a/compressible_mapped/problems +++ b/compressible_mapped/problems @@ -1 +1 @@ -compressible/problems/ \ No newline at end of file +../compressible/problems \ No newline at end of file diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 88aaeb18b..15c79bec4 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -1,16 +1,122 @@ from __future__ import print_function import numpy as np +import importlib import mesh.integration as integration import compressible import compressible_mapped.fluxes as flx +from util import msg +from mesh.mapped import MappedGrid2d +import mesh.boundary as bnd +import compressible.BC as BC +from simulation_null import bc_setup +import particles.particles as particles +import compressible.derives as derives + + +def mapped_grid_setup(rp, ng=1): + nx = rp.get_param("mesh.nx") + ny = rp.get_param("mesh.ny") + + try: + xmin = rp.get_param("mesh.xmin") + except KeyError: + xmin = 0.0 + msg.warning("mesh.xmin not set, defaulting to 0.0") + + try: + xmax = rp.get_param("mesh.xmax") + except KeyError: + xmax = 1.0 + msg.warning("mesh.xmax not set, defaulting to 1.0") + + try: + ymin = rp.get_param("mesh.ymin") + except KeyError: + ymin = 0.0 + msg.warning("mesh.ymin not set, defaulting to 0.0") + + try: + ymax = rp.get_param("mesh.ymax") + except KeyError: + ymax = 1.0 + msg.warning("mesh.ynax not set, defaulting to 1.0") + + my_grid = MappedGrid2d(nx, ny, + xmin=xmin, xmax=xmax, + ymin=ymin, ymax=ymax, ng=ng) + return my_grid class Simulation(compressible.Simulation): """The main simulation class for the method of lines compressible hydrodynamics solver""" + def initialize(self, extra_vars=None, ng=4): + """ + Initialize the grid and variables for compressible flow and set + the initial conditions for the chosen problem. + """ + my_grid = mapped_grid_setup(self.rp, ng=ng) + my_data = self.data_class(my_grid) + + # define solver specific boundary condition routines + bnd.define_bc("hse", BC.user, is_solid=False) + # for double mach reflection problem + bnd.define_bc("ramp", BC.user, is_solid=False) + + bc, bc_xodd, bc_yodd = bc_setup(self.rp) + + # are we dealing with solid boundaries? we'll use these for + # the Riemann solver + self.solid = bnd.bc_is_solid(bc) + + # density and energy + my_data.register_var("density", bc) + my_data.register_var("energy", bc) + my_data.register_var("x-momentum", bc_xodd) + my_data.register_var("y-momentum", bc_yodd) + + # any extras? + if extra_vars is not None: + for v in extra_vars: + my_data.register_var(v, bc) + + # store the EOS gamma as an auxillary quantity so we can have a + # self-contained object stored in output files to make plots. + # store grav because we'll need that in some BCs + my_data.set_aux("gamma", self.rp.get_param("eos.gamma")) + my_data.set_aux("grav", self.rp.get_param("compressible.grav")) + + my_data.create() + + self.cc_data = my_data + + if self.rp.get_param("particles.do_particles") == 1: + self.particles = particles.Particles(self.cc_data, bc, self.rp) + + # some auxillary data that we'll need to fill GC in, but isn't + # really part of the main solution + aux_data = self.data_class(my_grid) + aux_data.register_var("ymom_src", bc_yodd) + aux_data.register_var("E_src", bc) + aux_data.create() + self.aux_data = aux_data + + self.ivars = compressible.Variables(my_data) + + # derived variables + self.cc_data.add_derived(derives.derive_primitives) + + # initial conditions for the problem + problem = importlib.import_module("{}.problems.{}".format( + self.solver_name, self.problem_name)) + problem.init_data(self.cc_data, self.rp) + + if self.verbose > 0: + print(my_data) + def substep(self, myd): """ take a single substep in the RK timestepping starting with the @@ -18,32 +124,25 @@ def substep(self, myd): """ myg = myd.grid - grav = self.rp.get_param("compressible.grav") - - # compute the source terms - dens = myd.get_var("density") - ymom = myd.get_var("y-momentum") - - ymom_src = myg.scratch_array() - ymom_src.v()[:, :] = dens.v()[:, :]*grav + k = myg.scratch_array(nvar=self.ivars.nvar) - E_src = myg.scratch_array() - E_src.v()[:, :] = ymom.v()[:, :]*grav + flux_xp, flux_xm, flux_yp, flux_ym = flx.fluxes(myd, self.rp, + self.ivars, self.solid, self.tc) - k = myg.scratch_array(nvar=self.ivars.nvar) + # flux_x, _, flux_y, _ = flx.fluxes(myd, self.rp, + # self.ivars, self.solid, self.tc) - flux_x, flux_y = flx.fluxes(myd, self.rp, - self.ivars, self.solid, self.tc) + # for n in range(self.ivars.nvar): + # k.v(n=n)[:, :] = \ + # (flux_x.v(n=n) - flux_x.ip(1, n=n))/(myg.dx * myg.kappa) + \ + # (flux_y.v(n=n) - flux_y.jp(1, n=n))/(myg.dy * myg.kappa) for n in range(self.ivars.nvar): k.v(n=n)[:, :] = \ - (flux_x.v(n=n) - flux_x.ip(1, n=n))/(myg.dx * myg.kappa) + \ - (flux_y.v(n=n) - flux_y.jp(1, n=n))/(myg.dy * myg.kappa) + (flux_xp.v(n=n) + flux_xm.ip(1, n=n)) / (myg.dx * myg.kappa.v()) + \ + (flux_yp.v(n=n) + flux_ym.jp(1, n=n)) / (myg.dy * myg.kappa.v()) - k.v(n=self.ivars.iymom)[:, :] += ymom_src.v()[:, :] - k.v(n=self.ivars.iener)[:, :] += E_src.v()[:, :] - - return k + return -k def method_compute_timestep(self): """ @@ -61,10 +160,10 @@ def method_compute_timestep(self): u, v, cs = self.cc_data.get_var(["velocity", "soundspeed"]) # the timestep is min(dx/(|u| + cs), dy/(|v| + cs)) - xtmp = (abs(u) + cs)/self.cc_data.grid.dx - ytmp = (abs(v) + cs)/self.cc_data.grid.dy + xtmp = (abs(u) + cs) / self.cc_data.grid.dx + ytmp = (abs(v) + cs) / self.cc_data.grid.dy - self.dt = cfl*float(np.min(1.0/(xtmp + ytmp))) + self.dt = cfl * float(np.min(1.0 / (xtmp + ytmp))) def evolve(self): """ @@ -77,6 +176,11 @@ def evolve(self): myd = self.cc_data + # k = self.substep(myd) + + # for n in range(self.ivars.nvar): + # myd.data.v(n=n)[:, :] -= k.v(n=n) * self.dt + method = self.rp.get_param("compressible.temporal_method") rk = integration.RKIntegrator(myd.t, self.dt, method=method) From 3eeb16b5c4058325382cd0329b1c408d919a3ea5 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Tue, 26 Feb 2019 11:20:56 -0500 Subject: [PATCH 04/21] area, line element and rotation matrices can now be passed in --- compressible_mapped/fluxes.py | 156 ++++++--------------- compressible_mapped/simulation.py | 50 ++++--- mesh/array_indexer.py | 16 ++- mesh/integration.py | 4 +- mesh/mapped.py | 219 ++++++++++++++++++++++++++++++ 5 files changed, 303 insertions(+), 142 deletions(-) create mode 100644 mesh/mapped.py diff --git a/compressible_mapped/fluxes.py b/compressible_mapped/fluxes.py index d3e02f614..fe3ab4638 100644 --- a/compressible_mapped/fluxes.py +++ b/compressible_mapped/fluxes.py @@ -22,8 +22,8 @@ import numpy as np import compressible.interface as interface -import compressible as comp -import mesh.reconstruction as reconstruction +# import compressible as comp +# import mesh.reconstruction as reconstruction import mesh.array_indexer as ai from util import msg @@ -37,6 +37,8 @@ def fluxes(my_data, rp, ivars, solid, tc): currently we assume a gamma-law EOS + We use the method of Calhoun, D. A., Helzel, C., & LeVeque, R. J. (2008). SIAM review, 50(4), 723-752 for the mapped grids. + Parameters ---------- my_data : CellCenterData2d object @@ -75,88 +77,20 @@ def fluxes(my_data, rp, ivars, solid, tc): b = 3 - for n in range(ivars.nvar): - U_xl.v(n=n, buf=b)[:, :] = myg.R_fcy.v(buf=b) * U.ip(-1, n=n, buf=b) - U_xr.v(n=n, buf=b)[:, :] = myg.R_fcy.v(buf=b) * U.v(n=n, buf=b) - U_yl.v(n=n, buf=b)[:, :] = myg.R_fcx.v(buf=b) * U.jp(-1, n=n, buf=b) - U_yr.v(n=n, buf=b)[:, :] = myg.R_fcx.v(buf=b) * U.v(n=n, buf=b) + nx, ny, _ = np.shape(U_xl.v(buf=b)) + + for i in range(nx): + for j in range(ny): + U_xl.v(buf=b)[i, j] = (my_data.R_fcy.v(buf=b)[i, j] @ + U.ip(-1, buf=b)[i, j]) + U_xr.v(buf=b)[i, j] = (my_data.R_fcy.v(buf=b)[i, j] @ + U.v(buf=b)[i, j]) + U_yl.v(buf=b)[i, j] = (my_data.R_fcx.v(buf=b)[i, j] @ + U.jp(-1, buf=b)[i, j]) + U_yr.v(buf=b)[i, j] = (my_data.R_fcx.v(buf=b)[i, j] @ + U.v(buf=b)[i, j]) gamma = rp.get_param("eos.gamma") - # - # # ========================================================================= - # # compute the primitive variables - # # ========================================================================= - # # Q = (rho, u, v, p) - # - # q = comp.cons_to_prim(my_data.data, gamma, ivars, myg) - # - # # ========================================================================= - # # 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: - # xi_x = reconstruction.flatten(myg, q, 1, ivars, rp) - # xi_y = reconstruction.flatten(myg, q, 2, ivars, rp) - # - # xi = reconstruction.flatten_multid(myg, q, xi_x, xi_y, ivars) - # else: - # xi = 1.0 - # - # # monotonized central differences in x-direction - # tm_limit = tc.timer("limiting") - # tm_limit.begin() - # - # limiter = rp.get_param("compressible.limiter") - # - # ldx = myg.scratch_array(nvar=ivars.nvar) - # ldy = myg.scratch_array(nvar=ivars.nvar) - # - # for n in range(ivars.nvar): - # ldx[:, :, n] = xi * reconstruction.limit(q[:, :, n], myg, 1, limiter) - # ldy[:, :, n] = xi * reconstruction.limit(q[:, :, n], myg, 2, limiter) - # - # tm_limit.end() - # - # # ========================================================================= - # # x-direction - # # ========================================================================= - # - # # left and right primitive variable states - # tm_states = tc.timer("interfaceStates") - # tm_states.begin() - # - # V_l = myg.scratch_array(ivars.nvar) - # V_r = myg.scratch_array(ivars.nvar) - # - # for n in range(ivars.nvar): - # V_l.ip(1, n=n, buf=2)[:, :] = q.v(n=n, buf=2) + 0.5 * ldx.v(n=n, buf=2) - # V_r.v(n=n, buf=2)[:, :] = q.v(n=n, buf=2) - 0.5 * ldx.v(n=n, buf=2) - # - # tm_states.end() - # - # # transform interface states back into conserved variables - # U_xl = comp.prim_to_cons(V_l, gamma, ivars, myg) - # U_xr = comp.prim_to_cons(V_r, gamma, ivars, myg) - # - # # ========================================================================= - # # y-direction - # # ========================================================================= - # - # # left and right primitive variable states - # tm_states.begin() - # - # for n in range(ivars.nvar): - # V_l.jp(1, n=n, buf=2)[:, :] = q.v(n=n, buf=2) + 0.5 * ldy.v(n=n, buf=2) - # V_r.v(n=n, buf=2)[:, :] = q.v(n=n, buf=2) - 0.5 * ldy.v(n=n, buf=2) - # - # tm_states.end() - # - # # transform interface states back into conserved variables - # U_yl = comp.prim_to_cons(V_l, gamma, ivars, myg) - # U_yr = comp.prim_to_cons(V_r, gamma, ivars, myg) # ========================================================================= # construct the fluxes normal to the interfaces @@ -207,41 +141,29 @@ def fluxes(my_data, rp, ivars, solid, tc): for i in range(ilo - 1, ihi + 1): for j in range(jlo - 1, jhi + 1): - A_plus_delta_q_x[i, j, :] = myg.gamma_fcy[i,j] * myg.R_T_fcy[i,j] * (interface.consFlux(1, gamma, ivars.idens, - ivars.ixmom, ivars.iymom, - ivars.iener, ivars.irhox, - ivars.naux, U_xr[i, j, :]) - - F_x[i, j, :]) - A_minus_delta_q_x[i, j, :] = myg.gamma_fcy[i,j] * myg.R_T_fcy[i,j] * (F_x[i, j, :] - - interface.consFlux(1, gamma, ivars.idens, - ivars.ixmom, ivars.iymom, ivars.iener, - ivars.irhox, ivars.naux, - U_xl[i, j, :])) - - A_plus_delta_q_y[i, j, :] = myg.gamma_fcx[i,j] * myg.R_T_fcx[i,j] * (interface.consFlux(2, gamma, ivars.idens, - ivars.ixmom, ivars.iymom, - ivars.iener, ivars.irhox, - ivars.naux, U_yr[i, j, :]) - - F_y[i, j, :]) - A_minus_delta_q_y[i, j, :] = myg.gamma_fcx[i,j] * myg.R_T_fcx[i,j] * (F_y[i, j, :] - - interface.consFlux(2, gamma, ivars.idens, - ivars.ixmom, ivars.iymom, - ivars.iener, ivars.irhox, - ivars.naux, U_yl[i, j, :])) - - # q_star_x = U_xl[:, :, :] + F_x[:, :, :] - # - # A_plus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ - # (interface.consFlux(U_xr) - interface.consFlux(q_star_x)) - # A_minus_delta_q_x = myg.gamma_fcy * myg.R_T_fcy * \ - # (interface.consFlux(q_star_x) - interface.consFlux(U_xl)) - # - # q_star_y = U_yl[:, :, :] + F_y[:, :, :] - # - # A_plus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ - # (interface.consFlux(U_yr) - interface.consFlux(q_star_y)) - # A_minus_delta_q_y = myg.gamma_fcx * myg.R_T_fcx * \ - # (interface.consFlux(q_star_y) - interface.consFlux(U_yl)) + A_plus_delta_q_x[i, j, :] = myg.gamma_fcy[i, j] * \ + (my_data.R_fcy[i, j]).T @ \ + (interface.consFlux(1, gamma, ivars.idens, ivars.ixmom, ivars.iymom, + ivars.iener, ivars.irhox, ivars.naux, + U_xr[i, j, :]) - F_x[i, j, :]) + A_minus_delta_q_x[i, j, :] = myg.gamma_fcy[i, j] * \ + (my_data.R_fcy[i, j]).T @ \ + (F_x[i, j, :] - interface.consFlux(1, gamma, ivars.idens, ivars.ixmom, + ivars.iymom, ivars.iener, + ivars.irhox, ivars.naux, + U_xl[i, j, :])) + + A_plus_delta_q_y[i, j, :] = myg.gamma_fcx[i, j] * \ + (my_data.R_fcx[i, j]).T @ \ + (interface.consFlux(2, gamma, ivars.idens, ivars.ixmom, ivars.iymom, + ivars.iener, ivars.irhox, ivars.naux, + U_yr[i, j, :]) - F_y[i, j, :]) + A_minus_delta_q_y[i, j, :] = myg.gamma_fcx[i, j] * \ + (my_data.R_fcx[i, j]).T @ \ + (F_y[i, j, :] - interface.consFlux(2, gamma, ivars.idens, ivars.ixmom, + ivars.iymom, ivars.iener, + ivars.irhox, ivars.naux, + U_yl[i, j, :])) tm_flux.end() diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 15c79bec4..0fad0f0ba 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -7,7 +7,7 @@ import compressible import compressible_mapped.fluxes as flx from util import msg -from mesh.mapped import MappedGrid2d +import mesh.mapped as mapped import mesh.boundary as bnd import compressible.BC as BC from simulation_null import bc_setup @@ -43,9 +43,30 @@ def mapped_grid_setup(rp, ng=1): ymax = 1.0 msg.warning("mesh.ynax not set, defaulting to 1.0") - my_grid = MappedGrid2d(nx, ny, + def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i,j,:,:] = R_mat + + return R_fc + + my_grid = mapped.MappedGrid2d(nx, ny, xmin=xmin, xmax=xmax, - ymin=ymin, ymax=ymax, ng=ng) + ymin=ymin, ymax=ymax, ng=ng, + area_func=area, h_func=h, R_func=R) return my_grid @@ -53,6 +74,11 @@ class Simulation(compressible.Simulation): """The main simulation class for the method of lines compressible hydrodynamics solver""" + def __init__(self, solver_name, problem_name, rp, timers=None): + + super().__init__(solver_name, problem_name, rp, timers=timers, + data_class=mapped.MappedCellCenterData2d) + def initialize(self, extra_vars=None, ng=4): """ Initialize the grid and variables for compressible flow and set @@ -106,6 +132,9 @@ def initialize(self, extra_vars=None, ng=4): self.ivars = compressible.Variables(my_data) + # make rotation matrices + my_data.make_rotation_matrices(self.ivars) + # derived variables self.cc_data.add_derived(derives.derive_primitives) @@ -129,14 +158,6 @@ def substep(self, myd): flux_xp, flux_xm, flux_yp, flux_ym = flx.fluxes(myd, self.rp, self.ivars, self.solid, self.tc) - # flux_x, _, flux_y, _ = flx.fluxes(myd, self.rp, - # self.ivars, self.solid, self.tc) - - # for n in range(self.ivars.nvar): - # k.v(n=n)[:, :] = \ - # (flux_x.v(n=n) - flux_x.ip(1, n=n))/(myg.dx * myg.kappa) + \ - # (flux_y.v(n=n) - flux_y.jp(1, n=n))/(myg.dy * myg.kappa) - for n in range(self.ivars.nvar): k.v(n=n)[:, :] = \ (flux_xp.v(n=n) + flux_xm.ip(1, n=n)) / (myg.dx * myg.kappa.v()) + \ @@ -176,18 +197,13 @@ def evolve(self): myd = self.cc_data - # k = self.substep(myd) - - # for n in range(self.ivars.nvar): - # myd.data.v(n=n)[:, :] -= k.v(n=n) * self.dt - method = self.rp.get_param("compressible.temporal_method") rk = integration.RKIntegrator(myd.t, self.dt, method=method) rk.set_start(myd) for s in range(rk.nstages()): - ytmp = rk.get_stage_start(s) + ytmp = rk.get_stage_start(s, clone_function=mapped.mapped_cell_center_data_clone) ytmp.fill_BC_all() k = self.substep(ytmp) rk.store_increment(s, k) diff --git a/mesh/array_indexer.py b/mesh/array_indexer.py index 200c04c94..03c178ccf 100644 --- a/mesh/array_indexer.py +++ b/mesh/array_indexer.py @@ -46,14 +46,14 @@ def __array_finalize__(self, obj): def __array_wrap__(self, out_arr, context=None): return np.ndarray.__array_wrap__(self, out_arr, context) - def v(self, buf=0, n=0, s=1): + def v(self, buf=0, n=None, s=1): """return a view of the valid data region for component n, with stride s, and a buffer of ghost cells given by buf """ return self.ip_jp(0, 0, buf=buf, n=n, s=s) - def ip(self, shift, buf=0, n=0, s=1): + def ip(self, shift, buf=0, n=None, s=1): """return a view of the data shifted by shift in the x direction. By default the view is the same size as the valid region, but the buf can specify how many ghost cells on each side to include. @@ -62,7 +62,7 @@ def ip(self, shift, buf=0, n=0, s=1): """ return self.ip_jp(shift, 0, buf=buf, n=n, s=s) - def jp(self, shift, buf=0, n=0, s=1): + def jp(self, shift, buf=0, n=None, s=1): """return a view of the data shifted by shift in the y direction. By default the view is the same size as the valid region, but the buf can specify how many ghost cells on each side to include. @@ -71,7 +71,7 @@ def jp(self, shift, buf=0, n=0, s=1): """ return self.ip_jp(0, shift, buf=buf, n=n, s=s) - def ip_jp(self, ishift, jshift, buf=0, n=0, s=1): + def ip_jp(self, ishift, jshift, buf=0, n=None, s=1): """return a view of the data shifted by ishift in the x direction and jshift in the y direction. By default the view is the same size as the valid region, but the buf can specify how many @@ -86,8 +86,12 @@ def ip_jp(self, ishift, jshift, buf=0, n=0, s=1): return np.asarray(self[self.g.ilo-bxlo+ishift:self.g.ihi+1+bxhi+ishift:s, self.g.jlo-bylo+jshift:self.g.jhi+1+byhi+jshift:s]) else: - return np.asarray(self[self.g.ilo-bxlo+ishift:self.g.ihi+1+bxhi+ishift:s, - self.g.jlo-bylo+jshift:self.g.jhi+1+byhi+jshift:s, n]) + if n is not None: + return np.asarray(self[self.g.ilo-bxlo+ishift:self.g.ihi+1+bxhi+ishift:s, + self.g.jlo-bylo+jshift:self.g.jhi+1+byhi+jshift:s, n]) + else: + return np.asarray(self[self.g.ilo-bxlo+ishift:self.g.ihi+1+bxhi+ishift:s, + self.g.jlo-bylo+jshift:self.g.jhi+1+byhi+jshift:s,]) def lap(self, n=0, buf=0): """return the 5-point Laplacian""" diff --git a/mesh/integration.py b/mesh/integration.py index 7448c1c93..682560eef 100644 --- a/mesh/integration.py +++ b/mesh/integration.py @@ -101,13 +101,13 @@ def store_increment(self, istage, k_stage): weighting""" self.k[istage] = k_stage - def get_stage_start(self, istage): + def get_stage_start(self, istage, clone_function=patch.cell_center_data_clone): """get the starting conditions (a CellCenterData2d object) for stage istage""" if istage == 0: ytmp = self.start else: - ytmp = patch.cell_center_data_clone(self.start) + ytmp = clone_function(self.start) for n in range(ytmp.nvar): var = ytmp.get_var_by_index(n) for s in range(istage): diff --git a/mesh/mapped.py b/mesh/mapped.py new file mode 100644 index 000000000..3c7fe2f7b --- /dev/null +++ b/mesh/mapped.py @@ -0,0 +1,219 @@ +""" +The patch module defines the classes necessary to describe finite-volume +data and the grid that it lives on. + +Typical usage: + +* create the grid:: + + grid = Grid2d(nx, ny) + +* create the data that lives on that grid:: + + data = CellCenterData2d(grid) + + bc = BC(xlb="reflect", xrb="reflect", + ylb="outflow", yrb="outflow") + data.register_var("density", bc) + ... + + data.create() + +* initialize some data:: + + dens = data.get_var("density") + dens[:, :] = ... + + +* fill the ghost cells:: + + data.fill_BC("density") + +""" +from __future__ import print_function + +import numpy as np +# +# import h5py +# +from util import msg +# +# import mesh.boundary as bnd +import mesh.array_indexer as ai +from functools import partial +from mesh.patch import Grid2d, CellCenterData2d + + +class MappedGrid2d(Grid2d): + """ + the mapped 2-d grid class. The grid object will contain the coordinate + information (at various centerings). + + A basic (1-d) representation of the layout is:: + + | | | X | | | | X | | | + +--*--+- // -+--*--X--*--+--*--+- // -+--*--+--*--X--*--+- // -+--*--+ + 0 ng-1 ng ng+1 ... ng+nx-1 ng+nx 2ng+nx-1 + + ilo ihi + + |<- ng guardcells->|<---- nx interior zones ----->|<- ng guardcells->| + + The '*' marks the data locations. + """ + + # pylint: disable=too-many-instance-attributes + + def __init__(self, nx, ny, ng=1, + xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, + area_func=None, h_func=None, R_func=None): + """ + Create a Grid2d object. + + The only data that we require is the number of points that + make up the mesh in each direction. Optionally we take the + extrema of the domain (default is [0,1]x[0,1]) and number of + ghost cells (default is 1). + + Note that the Grid2d object only defines the discretization, + it does not know about the boundary conditions, as these can + vary depending on the variable. + + Parameters + ---------- + nx : int + Number of zones in the x-direction + ny : int + Number of zones in the y-direction + ng : int, optional + Number of ghost cells + xmin : float, optional + Physical coordinate at the lower x boundary + xmax : float, optional + Physical coordinate at the upper x boundary + ymin : float, optional + Physical coordinate at the lower y boundary + ymax : float, optional + Physical coordinate at the upper y boundary + """ + + super().__init__(nx, ny, ng, xmin, xmax, ymin, ymax) + + self.kappa, self.gamma_fcx, self.gamma_fcy = self.calculate_metric_elements( + area_func, h_func) + + self.R_fcx, self.R_fcy = self.calculate_rotation_matrices(R_func) + + # self.R_fcx = self.scratch_array() + 1.0 + # self.R_fcy = self.scratch_array() + 1.0 + # self.R_T_fcx = self.scratch_array() + 1.0 + # self.R_T_fcy = self.scratch_array() + 1.0 + + def calculate_metric_elements(self, area, h): + """ + Given the functions for the area and line elements, calculate them on + the grid. + """ + + kappa = self.scratch_array() + + kappa[:, :] = area(self) / (self.dx * self.dy) + + hx = self.scratch_array() + hy = self.scratch_array() + + hx[:, :] = h(1, self) + hy[:, :] = h(2, self) + + return kappa, hx / self.dy, hy / self.dx + + def calculate_rotation_matrices(self, R): + """ + We're going to use partial functions here as the grid knows nothing of + the variables. + """ + + R_fcx = partial(R, 1, self) + R_fcy = partial(R, 2, self) + + return R_fcx, R_fcy + + def scratch_array(self, nvar=1): + """ + return a standard numpy array dimensioned to have the size + and number of ghostcells as the parent grid + """ + + def isTuple(x): + return isinstance(x, tuple) + + def flatten(t): + if not isTuple(t): + return (t, ) + elif len(t) == 0: + return () + else: + return flatten(t[0]) + flatten(t[1:]) + + if nvar == 1: + _tmp = np.zeros((self.qx, self.qy), dtype=np.float64) + else: + _tmp = np.zeros((self.qx, self.qy) + flatten(nvar), dtype=np.float64) + return ai.ArrayIndexer(d=_tmp, grid=self) + +class MappedCellCenterData2d(CellCenterData2d): + + def __init__(self, grid, dtype=np.float64): + + super().__init__(grid, dtype=dtype) + + # self.R_fcx = [] + # self.R_fcy = [] + + def make_rotation_matrices(self, ivars): + """ + The grid knows nothing of the variables, so we're going to define + the actual rotation matrices here by passing in the variable data + to the rotation matrix function. + """ + + self.R_fcx = self.grid.R_fcx(ivars.nvar, ivars.ixmom, ivars.iymom) + self.R_fcy = self.grid.R_fcy(ivars.nvar, ivars.ixmom, ivars.iymom) + +def mapped_cell_center_data_clone(old): + """ + Create a new CellCenterData2d object that is a copy of an existing + one + + Parameters + ---------- + old : CellCenterData2d object + The CellCenterData2d object we wish to copy + + Note + ---- + It may be that this whole thing can be replaced with a copy.deepcopy() + + """ + + if not isinstance(old, MappedCellCenterData2d): + msg.fail("Can't clone object") + + # we may be a type derived from CellCenterData2d, so use the same + # type + myt = type(old) + new = myt(old.grid, dtype=old.dtype) + + for n in range(old.nvar): + new.register_var(old.names[n], old.BCs[old.names[n]]) + + new.create() + + new.aux = old.aux.copy() + new.data = old.data.copy() + new.derives = old.derives.copy() + + new.R_fcx = old.R_fcx.copy() + new.R_fcy = old.R_fcy.copy() + + return new From c63321bb7cff5567eabb7192d90d2f0abac0eb1a Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Tue, 26 Feb 2019 12:48:34 -0500 Subject: [PATCH 05/21] added problems to mapped directory --- compressible/problems/acoustic_pulse.py | 11 +- compressible/problems/advect.py | 15 +- compressible_mapped/problems | 1 - compressible_mapped/problems/__init__.py | 2 + .../problems/_acoustic_pulse.defaults | 5 + compressible_mapped/problems/_advect.defaults | 3 + compressible_mapped/problems/_bubble.defaults | 11 ++ compressible_mapped/problems/_hse.defaults | 4 + compressible_mapped/problems/_kh.defaults | 8 + compressible_mapped/problems/_logo.defaults | 1 + compressible_mapped/problems/_quad.defaults | 33 ++++ compressible_mapped/problems/_ramp.defaults | 19 +++ compressible_mapped/problems/_rt.defaults | 10 ++ compressible_mapped/problems/_rt2.defaults | 10 ++ compressible_mapped/problems/_sedov.defaults | 4 + compressible_mapped/problems/_sod.defaults | 13 ++ .../problems/acoustic_pulse.py | 86 +++++++++++ compressible_mapped/problems/advect.py | 88 +++++++++++ compressible_mapped/problems/bubble.py | 109 ++++++++++++++ compressible_mapped/problems/hse.py | 85 +++++++++++ .../problems/inputs.acoustic_pulse | 37 +++++ .../problems/inputs.acoustic_pulse.256 | 39 +++++ .../problems/inputs.acoustic_pulse.512 | 39 +++++ .../problems/inputs.acoustic_pulse.64 | 37 +++++ .../problems/inputs.advect.128 | 36 +++++ .../problems/inputs.advect.256 | 36 +++++ compressible_mapped/problems/inputs.advect.64 | 36 +++++ compressible_mapped/problems/inputs.bubble | 39 +++++ compressible_mapped/problems/inputs.hse | 34 +++++ compressible_mapped/problems/inputs.kh | 43 ++++++ compressible_mapped/problems/inputs.logo | 34 +++++ compressible_mapped/problems/inputs.quad | 52 +++++++ compressible_mapped/problems/inputs.ramp | 40 +++++ compressible_mapped/problems/inputs.rt | 33 ++++ compressible_mapped/problems/inputs.rt2 | 33 ++++ .../problems/inputs.rt_gravity_waves | 37 +++++ compressible_mapped/problems/inputs.sedov | 38 +++++ compressible_mapped/problems/inputs.sod.x | 32 ++++ compressible_mapped/problems/inputs.sod.y | 29 ++++ compressible_mapped/problems/kh.py | 103 +++++++++++++ compressible_mapped/problems/logo.py | 104 +++++++++++++ compressible_mapped/problems/logo.txt | 21 +++ compressible_mapped/problems/quad.py | 119 +++++++++++++++ compressible_mapped/problems/ramp.py | 113 ++++++++++++++ compressible_mapped/problems/rt.py | 99 ++++++++++++ compressible_mapped/problems/rt2.py | 112 ++++++++++++++ compressible_mapped/problems/sedov.py | 115 ++++++++++++++ compressible_mapped/problems/sod.py | 124 +++++++++++++++ compressible_mapped/problems/test.py | 57 +++++++ compressible_mapped/simulation.py | 142 +++++++++++------- mesh/array_indexer.py | 2 +- 51 files changed, 2267 insertions(+), 66 deletions(-) delete mode 120000 compressible_mapped/problems create mode 100644 compressible_mapped/problems/__init__.py create mode 100644 compressible_mapped/problems/_acoustic_pulse.defaults create mode 100644 compressible_mapped/problems/_advect.defaults create mode 100644 compressible_mapped/problems/_bubble.defaults create mode 100644 compressible_mapped/problems/_hse.defaults create mode 100644 compressible_mapped/problems/_kh.defaults create mode 100644 compressible_mapped/problems/_logo.defaults create mode 100644 compressible_mapped/problems/_quad.defaults create mode 100644 compressible_mapped/problems/_ramp.defaults create mode 100644 compressible_mapped/problems/_rt.defaults create mode 100644 compressible_mapped/problems/_rt2.defaults create mode 100644 compressible_mapped/problems/_sedov.defaults create mode 100644 compressible_mapped/problems/_sod.defaults create mode 100644 compressible_mapped/problems/acoustic_pulse.py create mode 100644 compressible_mapped/problems/advect.py create mode 100644 compressible_mapped/problems/bubble.py create mode 100644 compressible_mapped/problems/hse.py create mode 100644 compressible_mapped/problems/inputs.acoustic_pulse create mode 100644 compressible_mapped/problems/inputs.acoustic_pulse.256 create mode 100644 compressible_mapped/problems/inputs.acoustic_pulse.512 create mode 100644 compressible_mapped/problems/inputs.acoustic_pulse.64 create mode 100644 compressible_mapped/problems/inputs.advect.128 create mode 100644 compressible_mapped/problems/inputs.advect.256 create mode 100644 compressible_mapped/problems/inputs.advect.64 create mode 100644 compressible_mapped/problems/inputs.bubble create mode 100644 compressible_mapped/problems/inputs.hse create mode 100644 compressible_mapped/problems/inputs.kh create mode 100644 compressible_mapped/problems/inputs.logo create mode 100644 compressible_mapped/problems/inputs.quad create mode 100644 compressible_mapped/problems/inputs.ramp create mode 100644 compressible_mapped/problems/inputs.rt create mode 100644 compressible_mapped/problems/inputs.rt2 create mode 100644 compressible_mapped/problems/inputs.rt_gravity_waves create mode 100644 compressible_mapped/problems/inputs.sedov create mode 100644 compressible_mapped/problems/inputs.sod.x create mode 100644 compressible_mapped/problems/inputs.sod.y create mode 100644 compressible_mapped/problems/kh.py create mode 100644 compressible_mapped/problems/logo.py create mode 100644 compressible_mapped/problems/logo.txt create mode 100644 compressible_mapped/problems/quad.py create mode 100644 compressible_mapped/problems/ramp.py create mode 100644 compressible_mapped/problems/rt.py create mode 100644 compressible_mapped/problems/rt2.py create mode 100644 compressible_mapped/problems/sedov.py create mode 100644 compressible_mapped/problems/sod.py create mode 100644 compressible_mapped/problems/test.py diff --git a/compressible/problems/acoustic_pulse.py b/compressible/problems/acoustic_pulse.py index 37e75ac04..a9c98c2dd 100644 --- a/compressible/problems/acoustic_pulse.py +++ b/compressible/problems/acoustic_pulse.py @@ -41,18 +41,19 @@ def init_data(myd, rp): ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") - xctr = 0.5*(xmin + xmax) - yctr = 0.5*(ymin + 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 + 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) + p = (dens / rho0)**gamma + ener[:, :] = p / (gamma - 1) def finalize(): diff --git a/compressible/problems/advect.py b/compressible/problems/advect.py index 491338c2f..625d2e29b 100644 --- a/compressible/problems/advect.py +++ b/compressible/problems/advect.py @@ -38,22 +38,23 @@ def init_data(my_data, rp): ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") - xctr = 0.5*(xmin + xmax) - yctr = 0.5*(ymin + ymax) + xctr = 0.5 * (xmin + xmax) + yctr = 0.5 * (ymin + ymax) # this is identical to the advection/smooth problem - dens[:, :] = 1.0 + np.exp(-60.0*((my_data.grid.x2d-xctr)**2 + - (my_data.grid.y2d-yctr)**2)) + dens[:, :] = 1.0 + np.exp(-60.0 * ((my_data.grid.x2d - xctr)**2 + + (my_data.grid.y2d - yctr)**2)) # velocity is diagonal u = 1.0 v = 1.0 - xmom[:, :] = dens[:, :]*u - ymom[:, :] = dens[:, :]*v + xmom[:, :] = dens[:, :] * u + ymom[:, :] = dens[:, :] * v # pressure is constant p = 1.0 - ener[:, :] = p/(gamma - 1.0) + 0.5*(xmom[:, :]**2 + ymom[:, :]**2)/dens[:, :] + ener[:, :] = p / (gamma - 1.0) + 0.5 * (xmom[:, :] + ** 2 + ymom[:, :]**2) / dens[:, :] def finalize(): diff --git a/compressible_mapped/problems b/compressible_mapped/problems deleted file mode 120000 index 37685ab1b..000000000 --- a/compressible_mapped/problems +++ /dev/null @@ -1 +0,0 @@ -../compressible/problems \ No newline at end of file diff --git a/compressible_mapped/problems/__init__.py b/compressible_mapped/problems/__init__.py new file mode 100644 index 000000000..fd7367b35 --- /dev/null +++ b/compressible_mapped/problems/__init__.py @@ -0,0 +1,2 @@ +__all__ = ['acoustic_pulse', 'advect', 'bubble', 'hse', 'kh', 'logo', 'quad', 'rt', 'rt2', 'sedov', 'sod', + 'test', 'ramp'] diff --git a/compressible_mapped/problems/_acoustic_pulse.defaults b/compressible_mapped/problems/_acoustic_pulse.defaults new file mode 100644 index 000000000..e1f6fd0ff --- /dev/null +++ b/compressible_mapped/problems/_acoustic_pulse.defaults @@ -0,0 +1,5 @@ +[acoustic_pulse] +rho0 = 1.4 +drho0 = 0.14 + + diff --git a/compressible_mapped/problems/_advect.defaults b/compressible_mapped/problems/_advect.defaults new file mode 100644 index 000000000..726cc5844 --- /dev/null +++ b/compressible_mapped/problems/_advect.defaults @@ -0,0 +1,3 @@ +[advect] + + diff --git a/compressible_mapped/problems/_bubble.defaults b/compressible_mapped/problems/_bubble.defaults new file mode 100644 index 000000000..d5d7a40ff --- /dev/null +++ b/compressible_mapped/problems/_bubble.defaults @@ -0,0 +1,11 @@ +[bubble] +dens_base = 10.0 ; density at the base of the atmosphere +scale_height = 2.0 ; scale height of the isothermal atmosphere + +x_pert = 2.0 +y_pert = 2.0 +r_pert = 0.25 +pert_amplitude_factor = 5.0 + +dens_cutoff = 0.01 + diff --git a/compressible_mapped/problems/_hse.defaults b/compressible_mapped/problems/_hse.defaults new file mode 100644 index 000000000..56ef80d2b --- /dev/null +++ b/compressible_mapped/problems/_hse.defaults @@ -0,0 +1,4 @@ +[hse] +dens0 = 1.0 +h = 1.0 + diff --git a/compressible_mapped/problems/_kh.defaults b/compressible_mapped/problems/_kh.defaults new file mode 100644 index 000000000..d2709ebe0 --- /dev/null +++ b/compressible_mapped/problems/_kh.defaults @@ -0,0 +1,8 @@ +[kh] +rho_1 = 1 +v_1 = -1.0 + +rho_2 = 2 +v_2 = 1.0 + + diff --git a/compressible_mapped/problems/_logo.defaults b/compressible_mapped/problems/_logo.defaults new file mode 100644 index 000000000..39647231c --- /dev/null +++ b/compressible_mapped/problems/_logo.defaults @@ -0,0 +1 @@ +[logo] diff --git a/compressible_mapped/problems/_quad.defaults b/compressible_mapped/problems/_quad.defaults new file mode 100644 index 000000000..30918f7d1 --- /dev/null +++ b/compressible_mapped/problems/_quad.defaults @@ -0,0 +1,33 @@ +# these defaults seem to be equivalent to Configuration 3 from +# Shulz-Rinne et al. SIAM J. Sci. Comput., 14, 6, 1394-1414, 1993 +# +# Also, with the numbers written out, this is Configuration 3 from +# Lax and Liu, SIAM J. Sci. Comput., 19, 2, 319-340, 1998 +# +# See also LeVeque JCP 131, 327-353, 1997 + +[quadrant] +rho1 = 1.5 ; quadrant 1 initial density +u1 = 0.0 ; quadrant 1 initial x-velocity +v1 = 0.0 ; quadrant 1 initial y-velocity +p1 = 1.5 ; quadrant 1 initial pressure + +rho2 = 0.532258064516129 ; quadrant 2 initial density +u2 = 1.206045378311055 ; quadrant 2 initial x-velocity +v2 = 0.0 ; quadrant 2 initial y-velocity +p2 = 0.3 ; quadrant 2 initial pressure + +rho3 = 0.137992831541219 ; quadrant 3 initial density +u3 = 1.206045378311055 ; quadrant 3 initial x-velocity +v3 = 1.206045378311055 ; quadrant 3 initial y-velocity +p3 = 0.029032258064516 ; quadrant 3 initial pressure + +rho4 = 0.532258064516129 ; quadrant 4 initial density +u4 = 0.0 ; quadrant 4 initial x-velocity +v4 = 1.206045378311055 ; quadrant 4 initial y-velocity +p4 = 0.3 ; quadrant 4 initial pressure + +cx = 0.5 ; corner x position +cy = 0.5 ; corner y position + + diff --git a/compressible_mapped/problems/_ramp.defaults b/compressible_mapped/problems/_ramp.defaults new file mode 100644 index 000000000..bc7975170 --- /dev/null +++ b/compressible_mapped/problems/_ramp.defaults @@ -0,0 +1,19 @@ +# these defaults comes from the third test problem in +# Woodward and Colella. Journal of Computational Physics, 54, 115-174, 1984 +# +# Also, the numbers is consitent with the ones in Castro +# + + +[ramp] +rhol = 8.0 ; post-shock initial density +ul = 7.1447096 ; post-shock initial x-velocity +vl = -4.125 ; post-shock initial y-velocity +pl = 116.5 ; post-shock initial pressure + +rhor = 1.4 ; pre-shock initial density +ur = 0.0 ; pre-shock initial x-velocity +vr = 0.0 ; pre-shock initial y-velocity +pr = 1.0 ; pre-shock initial pressure + + diff --git a/compressible_mapped/problems/_rt.defaults b/compressible_mapped/problems/_rt.defaults new file mode 100644 index 000000000..5fb52e497 --- /dev/null +++ b/compressible_mapped/problems/_rt.defaults @@ -0,0 +1,10 @@ +[rt] +dens1 = 1.0 +dens2 = 2.0 + +amp = 1.0 +sigma = 0.1 + +p0 = 10.0 + + diff --git a/compressible_mapped/problems/_rt2.defaults b/compressible_mapped/problems/_rt2.defaults new file mode 100644 index 000000000..a7daabef3 --- /dev/null +++ b/compressible_mapped/problems/_rt2.defaults @@ -0,0 +1,10 @@ +[rt2] +dens1 = 1.0 +dens2 = 2.0 + +amp = 1.0 +sigma = 0.1 + +p0 = 10.0 + + diff --git a/compressible_mapped/problems/_sedov.defaults b/compressible_mapped/problems/_sedov.defaults new file mode 100644 index 000000000..21fbd398a --- /dev/null +++ b/compressible_mapped/problems/_sedov.defaults @@ -0,0 +1,4 @@ +[sedov] +r_init = 0.1 ; radius for the initial perturbation +nsub = 4 + diff --git a/compressible_mapped/problems/_sod.defaults b/compressible_mapped/problems/_sod.defaults new file mode 100644 index 000000000..80b86ad80 --- /dev/null +++ b/compressible_mapped/problems/_sod.defaults @@ -0,0 +1,13 @@ +[sod] + +direction = x ; direction of the flow + +dens_left = 1.0 +dens_right = 0.125 + +u_left = 0.0 +u_right = 0.0 + +p_left = 1.0 +p_right = 0.1 + diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py new file mode 100644 index 000000000..5690ee44f --- /dev/null +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -0,0 +1,86 @@ +from __future__ import print_function + +import sys +import mesh.fv as fv +import numpy as np +from util import msg + + +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") + + myg = myd.grid + + xctr = 0.5 * (xmin + xmax) * myg.gamma_fcy + yctr = 0.5 * (ymin + ymax) * myg.gamma_fcx + + dist = np.sqrt((myd.grid.x2d * myg.gamma_fcy - xctr)**2 + + (myd.grid.y2d * myg.gamma_fcx - 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) + + +def area(myg): + return 2 * myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return 2 * myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/advect.py b/compressible_mapped/problems/advect.py new file mode 100644 index 000000000..4523524af --- /dev/null +++ b/compressible_mapped/problems/advect.py @@ -0,0 +1,88 @@ +from __future__ import print_function + +import sys +import mesh.patch as patch +import numpy as np +from util import msg + + +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[:, :] = 1.0 + 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[:, :] = 1.0 + np.exp(-60.0*((my_data.grid.x2d-xctr)**2 + + (my_data.grid.y2d-yctr)**2)) + + # velocity is diagonal + u = 1.0 + v = 1.0 + xmom[:, :] = dens[:, :]*u + ymom[:, :] = dens[:, :]*v + + # pressure is constant + p = 1.0 + ener[:, :] = p/(gamma - 1.0) + 0.5*(xmom[:, :]**2 + ymom[:, :]**2)/dens[:, :] + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + + msg = """ + """ + + print(msg) diff --git a/compressible_mapped/problems/bubble.py b/compressible_mapped/problems/bubble.py new file mode 100644 index 000000000..e22979ff2 --- /dev/null +++ b/compressible_mapped/problems/bubble.py @@ -0,0 +1,109 @@ +from __future__ import print_function + +import numpy as np +import sys + +import mesh.patch as patch +from util import msg + + +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] + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/hse.py b/compressible_mapped/problems/hse.py new file mode 100644 index 000000000..981e164ec --- /dev/null +++ b/compressible_mapped/problems/hse.py @@ -0,0 +1,85 @@ +from __future__ import print_function + +import numpy as np + +import sys +import mesh.patch as patch +from util import msg + + +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[:, :] + + def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/inputs.acoustic_pulse b/compressible_mapped/problems/inputs.acoustic_pulse new file mode 100644 index 000000000..b1dfaef26 --- /dev/null +++ b/compressible_mapped/problems/inputs.acoustic_pulse @@ -0,0 +1,37 @@ +[driver] +max_steps = 5000 +tmax = 0.24 +# 0.192 * dx +fix_dt = 1.5e-3 + +[compressible] +cvisc = 0.1 + + +[io] +basename = acoustic_pulse_ +dt_out = 0.03 + +[eos] +gamma = 1.4 + + +[mesh] +nx = 128 +ny = 128 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[acoustic_pulse] +rho0 = 1.4 +drho0 = 0.14 + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.acoustic_pulse.256 b/compressible_mapped/problems/inputs.acoustic_pulse.256 new file mode 100644 index 000000000..13743d11e --- /dev/null +++ b/compressible_mapped/problems/inputs.acoustic_pulse.256 @@ -0,0 +1,39 @@ +[driver] +max_steps = 5000 +tmax = 0.24 +# 0.192 * dx +fix_dt = 7.5e-4 + + +[compressible] +cvisc = 0.1 + + +[io] +basename = acoustic_pulse_256_ +dt_out = 0.03 + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 256 +ny = 256 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[acoustic_pulse] +rho0 = 1.4 +drho0 = 0.14 + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.acoustic_pulse.512 b/compressible_mapped/problems/inputs.acoustic_pulse.512 new file mode 100644 index 000000000..610d8b039 --- /dev/null +++ b/compressible_mapped/problems/inputs.acoustic_pulse.512 @@ -0,0 +1,39 @@ +[driver] +max_steps = 5000 +tmax = 0.24 +# 0.192 * dx +fix_dt = 3.75e-4 + + +[compressible] +cvisc = 0.1 + + +[io] +basename = acoustic_pulse_512_ +dt_out = 0.03 + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 512 +ny = 512 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[acoustic_pulse] +rho0 = 1.4 +drho0 = 0.14 + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.acoustic_pulse.64 b/compressible_mapped/problems/inputs.acoustic_pulse.64 new file mode 100644 index 000000000..f2ca50e65 --- /dev/null +++ b/compressible_mapped/problems/inputs.acoustic_pulse.64 @@ -0,0 +1,37 @@ +[driver] +max_steps = 5000 +tmax = 0.24 +# 0.192 * dx +fix_dt = 3.0e-3 + +[compressible] +cvisc = 0.1 + + +[io] +basename = acoustic_pulse_64_ +dt_out = 0.03 + +[eos] +gamma = 1.4 + + +[mesh] +nx = 64 +ny = 64 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[acoustic_pulse] +rho0 = 1.4 +drho0 = 0.14 + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.advect.128 b/compressible_mapped/problems/inputs.advect.128 new file mode 100644 index 000000000..c657a646a --- /dev/null +++ b/compressible_mapped/problems/inputs.advect.128 @@ -0,0 +1,36 @@ +[driver] +max_steps = 500 +tmax = 1.0 + +init_tstep_factor = 1.0 +fix_dt = 0.0025 + + +[compressible] +limiter = 0 +cvisc = 0.1 + + +[io] +basename = advect_ + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 128 +ny = 128 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.advect.256 b/compressible_mapped/problems/inputs.advect.256 new file mode 100644 index 000000000..77cec1857 --- /dev/null +++ b/compressible_mapped/problems/inputs.advect.256 @@ -0,0 +1,36 @@ +[driver] +max_steps = 1000 +tmax = 1.0 + +init_tstep_factor = 1.0 +fix_dt = 0.00125 + + +[compressible] +limiter = 0 +cvisc = 0.1 + + +[io] +basename = advect_ + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 256 +ny = 256 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.advect.64 b/compressible_mapped/problems/inputs.advect.64 new file mode 100644 index 000000000..8e99c8ff1 --- /dev/null +++ b/compressible_mapped/problems/inputs.advect.64 @@ -0,0 +1,36 @@ +[driver] +max_steps = 500 +tmax = 1.0 + +init_tstep_factor = 1.0 +fix_dt = 0.005 + + +[compressible] +limiter = 0 +cvisc = 0.1 + + +[io] +basename = advect_ + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 64 +ny = 64 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.bubble b/compressible_mapped/problems/inputs.bubble new file mode 100644 index 000000000..f25179261 --- /dev/null +++ b/compressible_mapped/problems/inputs.bubble @@ -0,0 +1,39 @@ +# simple inputs files for the four-corner problem. + +[driver] +max_steps = 1000 +tmax = 100.0 + + +[io] +basename = bubble_ +n_out = 100 + + +[mesh] +nx = 128 +ny = 256 +xmax = 4.0 +ymax = 8.0 + +xlboundary = outflow +xrboundary = outflow + +ylboundary = hse +yrboundary = hse + + +[bubble] +scale_height = 1.0 +dens_base = 1000.0 + +x_pert = 2.0 +y_pert = 2.0 +r_pert = 0.25 +pert_amplitude_factor = 2.0 + + +[compressible] +grav = -2.0 + +limiter = 2 diff --git a/compressible_mapped/problems/inputs.hse b/compressible_mapped/problems/inputs.hse new file mode 100644 index 000000000..08eef9473 --- /dev/null +++ b/compressible_mapped/problems/inputs.hse @@ -0,0 +1,34 @@ +# simple inputs files for the four-corner problem. + +[driver] +max_steps = 10000 +tmax = 3.0 + + +[io] +basename = rt_ +n_out = 100 + + +[mesh] +nx = 64 +ny = 192 +xmax = 1.0 +ymax = 3.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = hse +yrboundary = hse + + +[hse] +dens0 = 1.0 +H = 1.0 + + +[compressible] +grav = -1.0 + +limiter = 2 diff --git a/compressible_mapped/problems/inputs.kh b/compressible_mapped/problems/inputs.kh new file mode 100644 index 000000000..386094c28 --- /dev/null +++ b/compressible_mapped/problems/inputs.kh @@ -0,0 +1,43 @@ +[driver] +max_steps = 5000 +tmax = 2.0 +splitting = unsplit + + +[compressible] +limiter = 2 +cvisc = 0.1 + + +[io] +basename = kh_ +tplot = 0.01 + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 64 +ny = 64 +xmax = 1.0 +ymax = 1.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = periodic +yrboundary = periodic + + +[kh] +rho_1 = 1 +v_1 = -0.5 + +rho_2 = 2 +v_2 = 0.5 + + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.logo b/compressible_mapped/problems/inputs.logo new file mode 100644 index 000000000..3d6aa18e5 --- /dev/null +++ b/compressible_mapped/problems/inputs.logo @@ -0,0 +1,34 @@ +[driver] +max_steps = 5000 +tmax = 30.0 + + +[compressible] +limiter = 2 +cvisc = 0.1 + + +[io] +basename = logo_ +dt_out = 0.02 + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 64 +ny = 64 +xmax = 1.0 +ymax = 1.0 + +xlboundary = outflow +xrboundary = outflow + +ylboundary = outflow +yrboundary = outflow + + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.quad b/compressible_mapped/problems/inputs.quad new file mode 100644 index 000000000..51723d29a --- /dev/null +++ b/compressible_mapped/problems/inputs.quad @@ -0,0 +1,52 @@ +# simple inputs files for the four-corner problem. + +[driver] +max_steps = 1000 +tmax = 0.8 + + +[compressible] +limiter = 2 +cvisc = 0.1 + +[io] +basename = quad_unsplit_ +dt_out = 0.1 + + +[mesh] +nx = 256 +ny = 256 +xmax = 1.0 +ymax = 1.0 + +xlboundary = outflow +xrboundary = outflow + +ylboundary = outflow +yrboundary = outflow + + +[quadrant] +rho1 = 1.4 +u1 = 0.0 +v1 = 0.0 +p1 = 1.5 + +rho2 = 0.532258064516129 +u2 = 1.206045378311055 +v2 = 0.0 +p2 = 0.3 + +rho3 = 0.137992831541219 +u3 = 1.206045378311055 +v3 = 1.206045378311055 +p3 = 0.029032258064516 + +rho4 = 0.532258064516129 +u4 = 0.0 +v4 = 1.206045378311055 +p4 = 0.3 + +cx = 0.8 +cy = 0.8 diff --git a/compressible_mapped/problems/inputs.ramp b/compressible_mapped/problems/inputs.ramp new file mode 100644 index 000000000..e047d8f83 --- /dev/null +++ b/compressible_mapped/problems/inputs.ramp @@ -0,0 +1,40 @@ +# simple inputs files for the double Mach reflection problem. + +[driver] +max_steps = 12500 +tmax = 0.25 + + +[compressible] +limiter = 2 +cvisc = 0.1 + +[io] +basename = double_mach_reflection_ +dt_out = 0.1 + + +[mesh] +nx = 1024 +ny = 256 +xmax = 4.0 +ymax = 1.0 + +xlboundary = ramp +xrboundary = outflow + +ylboundary = ramp +yrboundary = ramp + + +[ramp] +rhol = 8.0 +ul = 7.1447096 +vl = -4.125 +pl = 116.5 + +rhor = 1.4 +ur = 0.0 +vr = 0.0 +pr = 1.0 + diff --git a/compressible_mapped/problems/inputs.rt b/compressible_mapped/problems/inputs.rt new file mode 100644 index 000000000..b8e7cf3de --- /dev/null +++ b/compressible_mapped/problems/inputs.rt @@ -0,0 +1,33 @@ +# simple inputs files for the four-corner problem. + +[driver] +max_steps = 10000 +tmax = 3.0 + + +[io] +basename = rt_ +n_out = 100 + + +[mesh] +nx = 64 +ny = 192 +xmax = 1.0 +ymax = 3.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = hse +yrboundary = hse + + +[rt] +amp = 0.25 + + +[compressible] +grav = -1.0 + +limiter = 2 diff --git a/compressible_mapped/problems/inputs.rt2 b/compressible_mapped/problems/inputs.rt2 new file mode 100644 index 000000000..6f76e907c --- /dev/null +++ b/compressible_mapped/problems/inputs.rt2 @@ -0,0 +1,33 @@ +# simple inputs files for the four-corner problem. + +[driver] +max_steps = 10000 +tmax = 5.0 + + +[io] +basename = rt_ +n_out = 10000 +dt_out = 0.025 + +[mesh] +nx = 384 +ny = 192 +xmax = 6.0 +ymax = 3.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = hse +yrboundary = hse + + +[rt2] +amp = 0.1 +sigma = 0.025 + +[compressible] +grav = -1.0 + +limiter = 2 diff --git a/compressible_mapped/problems/inputs.rt_gravity_waves b/compressible_mapped/problems/inputs.rt_gravity_waves new file mode 100644 index 000000000..f34d41857 --- /dev/null +++ b/compressible_mapped/problems/inputs.rt_gravity_waves @@ -0,0 +1,37 @@ +# simple inputs files for the four-corner problem. + +[driver] +max_steps = 10000 +tmax = 3.0 + + +[io] +basename = rt_ +n_out = 3 +dt_out = 1000000 + + +[mesh] +nx = 64 +ny = 192 +xmax = 1.0 +ymax = 3.0 + +xlboundary = periodic +xrboundary = periodic + +ylboundary = hse +yrboundary = hse + + +[rt] +amp = 0.25 + +dens1 = 2.0 +dens2 = 1.0 + + +[compressible] +grav = -1.0 + +limiter = 2 diff --git a/compressible_mapped/problems/inputs.sedov b/compressible_mapped/problems/inputs.sedov new file mode 100644 index 000000000..1dabca855 --- /dev/null +++ b/compressible_mapped/problems/inputs.sedov @@ -0,0 +1,38 @@ +[driver] +max_steps = 5000 +tmax = 0.1 + + +[compressible] +limiter = 2 +cvisc = 0.1 + + +[io] +basename = sedov_unsplit_ +dt_out = 0.0125 + + +[eos] +gamma = 1.4 + + +[mesh] +nx = 128 +ny = 128 +xmax = 1.0 +ymax = 1.0 + +xlboundary = outflow +xrboundary = outflow + +ylboundary = outflow +yrboundary = outflow + + +[sedov] +r_init = 0.01 + + +[vis] +dovis = 1 diff --git a/compressible_mapped/problems/inputs.sod.x b/compressible_mapped/problems/inputs.sod.x new file mode 100644 index 000000000..bae148fdc --- /dev/null +++ b/compressible_mapped/problems/inputs.sod.x @@ -0,0 +1,32 @@ +# simple inputs files for the unsplit CTU hydro scheme + +[driver] +max_steps = 200 +tmax = 0.2 + +[compressible] +limiter = 1 + +[io] +basename = sod_x_ +dt_out = 0.05 + +[mesh] +nx = 128 +ny = 10 +xmax = 1.0 +ymax = .05 +xlboundary = outflow +xrboundary = outflow + +[sod] +direction = x + +dens_left = 1.0 +dens_right = 0.125 + +u_left = 0.0 +u_right = 0.0 + +p_left = 1.0 +p_right = 0.1 diff --git a/compressible_mapped/problems/inputs.sod.y b/compressible_mapped/problems/inputs.sod.y new file mode 100644 index 000000000..9e952fd5d --- /dev/null +++ b/compressible_mapped/problems/inputs.sod.y @@ -0,0 +1,29 @@ +# simple inputs files for the unsplit CTU hydro scheme + +[driver] +max_steps = 200 +tmax = 0.2 + +[io] +basename = sod_y_ +dt_out = 0.05 + +[mesh] +nx = 10 +ny = 128 +xmax = .05 +ymax = 1.0 +ylboundary = outflow +yrboundary = outflow + +[sod] +direction = y + +dens_left = 1.0 +dens_right = 0.125 + +u_left = 0.0 +u_right = 0.0 + +p_left = 1.0 +p_right = 0.1 diff --git a/compressible_mapped/problems/kh.py b/compressible_mapped/problems/kh.py new file mode 100644 index 000000000..060fb56fd --- /dev/null +++ b/compressible_mapped/problems/kh.py @@ -0,0 +1,103 @@ +from __future__ import print_function + +import numpy as np + +import mesh.patch as patch +from util import msg + + +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[:, :] + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/logo.py b/compressible_mapped/problems/logo.py new file mode 100644 index 000000000..9d0b0ba8f --- /dev/null +++ b/compressible_mapped/problems/logo.py @@ -0,0 +1,104 @@ +from __future__ import print_function + +import sys +import mesh.patch as patch +import numpy as np +from util import msg +import matplotlib.pyplot as plt + + +def init_data(my_data, rp): + """ initialize the logo 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 logo.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) + dens[:, :] = 1.0 + xmom[:, :] = 0.0 + ymom[:, :] = 0.0 + + # set the density in the logo zones to be really large + logo_dens = 50.0 + + dens.v()[:, :] = logo[:, :] * logo_dens + + # pressure equilibrium + gamma = rp.get_param("eos.gamma") + + p_ambient = 1.e-5 + ener[:, :] = p_ambient / (gamma - 1.0) + + # explosion + ener[myg.ilo, myg.jlo] = 1.0 + ener[myg.ilo, myg.jhi] = 1.0 + ener[myg.ihi, myg.jlo] = 1.0 + ener[myg.ihi, myg.jhi] = 1.0 + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + + msg = """ + The script analysis/sedov_compare.py can be used to analyze these + results. That will perform an average at constant radius and + compare the radial profiles to the exact solution. Sample exact + data is provided as analysis/cylindrical-sedov.out + """ + + print(msg) diff --git a/compressible_mapped/problems/logo.txt b/compressible_mapped/problems/logo.txt new file mode 100644 index 000000000..e57926259 --- /dev/null +++ b/compressible_mapped/problems/logo.txt @@ -0,0 +1,21 @@ +xxxxxxx +xxxxxxxx +xx xx +xx xx +xx xx +xx xxx +xxxxxxx xx xx xx xxxx xxxx +xxxxx xx xx xx xxxxx xxxxxx +xx xx xx xxxx xxx xxx +xx xx xx xxx xx xx +xx xx xx xx xx xx +xx xxx xx xx xxx xxx +xx xxxxxx xx xxxxxx +xx xxxx xx xxxx + xx + xx + xx + xx + xx + xxxx + xxx diff --git a/compressible_mapped/problems/quad.py b/compressible_mapped/problems/quad.py new file mode 100644 index 000000000..889393cf2 --- /dev/null +++ b/compressible_mapped/problems/quad.py @@ -0,0 +1,119 @@ +from __future__ import print_function + +import sys + +import numpy as np + +import mesh.patch as patch +from util import msg + + +def init_data(my_data, rp): + """ initialize the quadrant problem """ + + msg.bold("initializing the quadrant problem...") + + # make sure that we are passed a valid patch object + if not isinstance(my_data, patch.CellCenterData2d): + print("ERROR: patch invalid in quad.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) + r1 = rp.get_param("quadrant.rho1") + u1 = rp.get_param("quadrant.u1") + v1 = rp.get_param("quadrant.v1") + p1 = rp.get_param("quadrant.p1") + + r2 = rp.get_param("quadrant.rho2") + u2 = rp.get_param("quadrant.u2") + v2 = rp.get_param("quadrant.v2") + p2 = rp.get_param("quadrant.p2") + + r3 = rp.get_param("quadrant.rho3") + u3 = rp.get_param("quadrant.u3") + v3 = rp.get_param("quadrant.v3") + p3 = rp.get_param("quadrant.p3") + + r4 = rp.get_param("quadrant.rho4") + u4 = rp.get_param("quadrant.u4") + v4 = rp.get_param("quadrant.v4") + p4 = rp.get_param("quadrant.p4") + + cx = rp.get_param("quadrant.cx") + cy = rp.get_param("quadrant.cy") + + gamma = rp.get_param("eos.gamma") + + # there is probably an easier way to do this, but for now, we + # will just do an explicit loop. Also, we really want to set + # the pressue and get the internal energy from that, and then + # compute the total energy (which is what we store). For now + # we will just fake this + + myg = my_data.grid + + iq1 = np.logical_and(myg.x2d >= cx, myg.y2d >= cy) + iq2 = np.logical_and(myg.x2d < cx, myg.y2d >= cy) + iq3 = np.logical_and(myg.x2d < cx, myg.y2d < cy) + iq4 = np.logical_and(myg.x2d >= cx, myg.y2d < cy) + + # quadrant 1 + dens[iq1] = r1 + xmom[iq1] = r1 * u1 + ymom[iq1] = r1 * v1 + ener[iq1] = p1 / (gamma - 1.0) + 0.5 * r1 * (u1 * u1 + v1 * v1) + + # quadrant 2 + dens[iq2] = r2 + xmom[iq2] = r2 * u2 + ymom[iq2] = r2 * v2 + ener[iq2] = p2 / (gamma - 1.0) + 0.5 * r2 * (u2 * u2 + v2 * v2) + + # quadrant 3 + dens[iq3] = r3 + xmom[iq3] = r3 * u3 + ymom[iq3] = r3 * v3 + ener[iq3] = p3 / (gamma - 1.0) + 0.5 * r3 * (u3 * u3 + v3 * v3) + + # quadrant 4 + dens[iq4] = r4 + xmom[iq4] = r4 * u4 + ymom[iq4] = r4 * v4 + ener[iq4] = p4 / (gamma - 1.0) + 0.5 * r4 * (u4 * u4 + v4 * v4) + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/ramp.py b/compressible_mapped/problems/ramp.py new file mode 100644 index 000000000..b421d5a77 --- /dev/null +++ b/compressible_mapped/problems/ramp.py @@ -0,0 +1,113 @@ +from __future__ import print_function + +import sys + +import numpy as np +import math + +import mesh.patch as patch +from util import msg + + +def init_data(my_data, rp): + """ initialize the double Mach reflection problem """ + + msg.bold("initializing the double Mach reflection problem...") + + # make sure that we are passed a valid patch object + if not isinstance(my_data, patch.CellCenterData2d): + print("ERROR: patch invalid in ramp.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) + + r_l = rp.get_param("ramp.rhol") + u_l = rp.get_param("ramp.ul") + v_l = rp.get_param("ramp.vl") + p_l = rp.get_param("ramp.pl") + + r_r = rp.get_param("ramp.rhor") + u_r = rp.get_param("ramp.ur") + v_r = rp.get_param("ramp.vr") + p_r = rp.get_param("ramp.pr") + + gamma = rp.get_param("eos.gamma") + + energy_l = p_l / (gamma - 1.0) + 0.5 * r_l * (u_l * u_l + v_l * v_l) + energy_r = p_r / (gamma - 1.0) + 0.5 * r_r * (u_r * u_r + v_r * v_r) + + # there is probably an easier way to do this, but for now, we + # will just do an explicit loop. Also, we really want to set + # the pressue and get the internal energy from that, and then + # compute the total energy (which is what we store). For now + # we will just fake this + + myg = my_data.grid + dens[:, :] = 1.4 + + for j in range(myg.jlo, myg.jhi + 1): + cy_up = myg.y[j] + 0.5 * myg.dy * math.sqrt(3) + cy_down = myg.y[j] - 0.5 * myg.dy * math.sqrt(3) + cy = np.array([cy_down, cy_up]) + + for i in range(myg.ilo, myg.ihi + 1): + dens[i, j] = 0.0 + xmom[i, j] = 0.0 + ymom[i, j] = 0.0 + ener[i, j] = 0.0 + + sf_up = math.tan(math.pi / 3.0) * \ + (myg.x[i] + 0.5 * myg.dx * math.sqrt(3) - 1.0 / 6.0) + sf_down = math.tan(math.pi / 3.0) * \ + (myg.x[i] - 0.5 * myg.dx * math.sqrt(3) - 1.0 / 6.0) + sf = np.array([sf_down, sf_up]) # initial shock front + + for y in cy: + for shockfront in sf: + if y >= shockfront: + dens[i, j] = dens[i, j] + 0.25 * r_l + xmom[i, j] = xmom[i, j] + 0.25 * r_l * u_l + ymom[i, j] = ymom[i, j] + 0.25 * r_l * v_l + ener[i, j] = ener[i, j] + 0.25 * energy_l + else: + dens[i, j] = dens[i, j] + 0.25 * r_r + xmom[i, j] = xmom[i, j] + 0.25 * r_r * u_r + ymom[i, j] = ymom[i, j] + 0.25 * r_r * v_r + ener[i, j] = ener[i, j] + 0.25 * energy_r + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/rt.py b/compressible_mapped/problems/rt.py new file mode 100644 index 000000000..122885e01 --- /dev/null +++ b/compressible_mapped/problems/rt.py @@ -0,0 +1,99 @@ +from __future__ import print_function + +import numpy as np + +import sys +import mesh.patch as patch +from util import msg + + +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() + + j = myg.jlo + while j <= myg.jhi: + 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) + + j += 1 + + ymom[:, :] = amp * np.cos(2.0 * np.pi * myg.x2d / (myg.xmax - myg.xmin) + ) * np.exp(-(myg.y2d - ycenter)**2 / sigma**2) + + ymom *= dens + + # set the energy (P = cs2*dens) + ener[:, :] = p[:, :] / (gamma - 1.0) + \ + 0.5 * (xmom[:, :]**2 + ymom[:, :]**2) / dens[:, :] + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/rt2.py b/compressible_mapped/problems/rt2.py new file mode 100644 index 000000000..725b701b8 --- /dev/null +++ b/compressible_mapped/problems/rt2.py @@ -0,0 +1,112 @@ +"""A RT problem with two distinct modes: short wave length on the +left and long wavelenght on the right. This allows one to see +how the growth rate depends on wavenumber. +""" + +from __future__ import print_function + +import numpy as np + +import sys +import mesh.patch as patch +from util import msg + + +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 rt2.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("rt2.dens1") + dens2 = rp.get_param("rt2.dens2") + p0 = rp.get_param("rt2.p0") + amp = rp.get_param("rt2.amp") + sigma = rp.get_param("rt2.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 + + f_l = 18 + f_r = 3 + + # 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() + + j = myg.jlo + while j <= myg.jhi: + 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) + + j += 1 + + idx_l = myg.x2d < (myg.xmax - myg.xmin) / 3.0 + idx_r = myg.x2d >= (myg.xmax - myg.xmin) / 3.0 + + ymom[idx_l] = amp * np.sin(4.0 * np.pi * f_l * myg.x2d[idx_l] / + (myg.xmax - myg.xmin)) * np.exp(-(myg.y2d[idx_l] - ycenter)**2 / sigma**2) + ymom[idx_r] = amp * np.sin(4.0 * np.pi * f_r * myg.x2d[idx_r] / + (myg.xmax - myg.xmin)) * np.exp(-(myg.y2d[idx_r] - ycenter)**2 / sigma**2) + + ymom *= dens + + # set the energy (P = cs2*dens) + ener[:, :] = p[:, :] / (gamma - 1.0) + \ + 0.5 * (xmom[:, :]**2 + ymom[:, :]**2) / dens[:, :] + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/problems/sedov.py b/compressible_mapped/problems/sedov.py new file mode 100644 index 000000000..59fea1498 --- /dev/null +++ b/compressible_mapped/problems/sedov.py @@ -0,0 +1,115 @@ +from __future__ import print_function + +import sys +import mesh.patch as patch +import numpy as np +from util import msg +import math + + +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 = 1.0 + + 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) + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + + msg = """ + The script analysis/sedov_compare.py can be used to analyze these + results. That will perform an average at constant radius and + compare the radial profiles to the exact solution. Sample exact + data is provided as analysis/cylindrical-sedov.out + """ + + print(msg) diff --git a/compressible_mapped/problems/sod.py b/compressible_mapped/problems/sod.py new file mode 100644 index 000000000..60c859378 --- /dev/null +++ b/compressible_mapped/problems/sod.py @@ -0,0 +1,124 @@ +from __future__ import print_function + +import sys +import numpy as np + +import mesh.patch as patch +from util import msg + + +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 + + if direction == "x": + + # left + idxl = myg.x2d <= xctr + + dens[idxl] = dens_left + xmom[idxl] = dens_left * u_left + ymom[idxl] = 0.0 + ener[idxl] = p_left / (gamma - 1.0) + 0.5 * xmom[idxl] * u_left + + # right + idxr = myg.x2d > xctr + + dens[idxr] = dens_right + xmom[idxr] = dens_right * u_right + ymom[idxr] = 0.0 + 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] = 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] = p_right / (gamma - 1.0) + 0.5 * ymom[idxt] * u_right + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + + msg = """ + The script analysis/sod_compare.py can be used to compare + this output to the exact solution. Some sample exact solution + data is present as analysis/sod-exact.out + """ + + print(msg) diff --git a/compressible_mapped/problems/test.py b/compressible_mapped/problems/test.py new file mode 100644 index 000000000..016989421 --- /dev/null +++ b/compressible_mapped/problems/test.py @@ -0,0 +1,57 @@ +from __future__ import print_function + +import sys +import mesh.patch as patch +import numpy as np + + +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") + + # 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 + + +def area(myg): + return myg.dx * myg.dy + myg.scratch_array() + + +def h(idir, myg): + if idir == 1: + return myg.dy + myg.scratch_array() + else: + return myg.dx + myg.scratch_array() + + +def R(iface, myg, nvar, ixmom, iymom): + R_fc = myg.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(myg.qx): + for j in range(myg.qy): + R_fc[i, j, :, :] = R_mat + + return R_fc + + +def finalize(): + """ print out any information to the user at the end of the run """ + pass diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 0fad0f0ba..00810ea8a 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -2,20 +2,23 @@ import numpy as np import importlib +import matplotlib.pyplot as plt import mesh.integration as integration import compressible +import compressible_rk import compressible_mapped.fluxes as flx -from util import msg +from util import msg, plot_tools import mesh.mapped as mapped import mesh.boundary as bnd import compressible.BC as BC +import compressible.eos as eos from simulation_null import bc_setup import particles.particles as particles import compressible.derives as derives -def mapped_grid_setup(rp, ng=1): +def mapped_grid_setup(rp, area, h, R, ng=1): nx = rp.get_param("mesh.nx") ny = rp.get_param("mesh.ny") @@ -43,48 +46,32 @@ def mapped_grid_setup(rp, ng=1): ymax = 1.0 msg.warning("mesh.ynax not set, defaulting to 1.0") - def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i,j,:,:] = R_mat - - return R_fc - my_grid = mapped.MappedGrid2d(nx, ny, - xmin=xmin, xmax=xmax, - ymin=ymin, ymax=ymax, ng=ng, - area_func=area, h_func=h, R_func=R) + xmin=xmin, xmax=xmax, + ymin=ymin, ymax=ymax, ng=ng, + area_func=area, h_func=h, R_func=R) return my_grid -class Simulation(compressible.Simulation): +class Simulation(compressible_rk.Simulation): """The main simulation class for the method of lines compressible hydrodynamics solver""" def __init__(self, solver_name, problem_name, rp, timers=None): super().__init__(solver_name, problem_name, rp, timers=timers, - data_class=mapped.MappedCellCenterData2d) + data_class=mapped.MappedCellCenterData2d) def initialize(self, extra_vars=None, ng=4): """ Initialize the grid and variables for compressible flow and set the initial conditions for the chosen problem. """ - my_grid = mapped_grid_setup(self.rp, ng=ng) + problem = importlib.import_module("{}.problems.{}".format( + self.solver_name, self.problem_name)) + + my_grid = mapped_grid_setup( + self.rp, problem.area, problem.h, problem.R, ng=ng) my_data = self.data_class(my_grid) # define solver specific boundary condition routines @@ -139,8 +126,6 @@ def initialize(self, extra_vars=None, ng=4): self.cc_data.add_derived(derives.derive_primitives) # initial conditions for the problem - problem = importlib.import_module("{}.problems.{}".format( - self.solver_name, self.problem_name)) problem.init_data(self.cc_data, self.rp) if self.verbose > 0: @@ -165,27 +150,6 @@ def substep(self, myd): return -k - 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") - - # get the variables we need - u, v, cs = self.cc_data.get_var(["velocity", "soundspeed"]) - - # the timestep is min(dx/(|u| + cs), dy/(|v| + cs)) - xtmp = (abs(u) + cs) / self.cc_data.grid.dx - ytmp = (abs(v) + cs) / self.cc_data.grid.dy - - self.dt = cfl * float(np.min(1.0 / (xtmp + ytmp))) - def evolve(self): """ Evolve the equations of compressible hydrodynamics through a @@ -203,7 +167,8 @@ def evolve(self): rk.set_start(myd) for s in range(rk.nstages()): - ytmp = rk.get_stage_start(s, clone_function=mapped.mapped_cell_center_data_clone) + ytmp = rk.get_stage_start( + s, clone_function=mapped.mapped_cell_center_data_clone) ytmp.fill_BC_all() k = self.substep(ytmp) rk.store_increment(s, k) @@ -218,3 +183,76 @@ def evolve(self): self.n += 1 tm_evolve.end() + + 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 = compressible.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 = compressible.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] + + X = myg.x2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcy.v() + Y = myg.y2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcx.v() + + img = ax.pcolormesh(X, Y, v.v(), 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() diff --git a/mesh/array_indexer.py b/mesh/array_indexer.py index 03c178ccf..5dd7a6661 100644 --- a/mesh/array_indexer.py +++ b/mesh/array_indexer.py @@ -91,7 +91,7 @@ def ip_jp(self, ishift, jshift, buf=0, n=None, s=1): self.g.jlo-bylo+jshift:self.g.jhi+1+byhi+jshift:s, n]) else: return np.asarray(self[self.g.ilo-bxlo+ishift:self.g.ihi+1+bxhi+ishift:s, - self.g.jlo-bylo+jshift:self.g.jhi+1+byhi+jshift:s,]) + self.g.jlo-bylo+jshift:self.g.jhi+1+byhi+jshift:s]) def lap(self, n=0, buf=0): """return the 5-point Laplacian""" From cbbd037712113e9cabb2a1c15b73add0c87875a4 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Tue, 26 Feb 2019 13:38:36 -0500 Subject: [PATCH 06/21] fixed bug so acoustic_pulse now works for rectilinear grids --- compressible_mapped/fluxes.py | 24 ++++++++++++------------ mesh/mapped.py | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compressible_mapped/fluxes.py b/compressible_mapped/fluxes.py index fe3ab4638..ea9257222 100644 --- a/compressible_mapped/fluxes.py +++ b/compressible_mapped/fluxes.py @@ -81,13 +81,13 @@ def fluxes(my_data, rp, ivars, solid, tc): for i in range(nx): for j in range(ny): - U_xl.v(buf=b)[i, j] = (my_data.R_fcy.v(buf=b)[i, j] @ + U_xl.v(buf=b)[i, j] = (my_data.R_fcx.v(buf=b)[i, j] @ U.ip(-1, buf=b)[i, j]) - U_xr.v(buf=b)[i, j] = (my_data.R_fcy.v(buf=b)[i, j] @ + U_xr.v(buf=b)[i, j] = (my_data.R_fcx.v(buf=b)[i, j] @ U.v(buf=b)[i, j]) - U_yl.v(buf=b)[i, j] = (my_data.R_fcx.v(buf=b)[i, j] @ + U_yl.v(buf=b)[i, j] = (my_data.R_fcy.v(buf=b)[i, j] @ U.jp(-1, buf=b)[i, j]) - U_yr.v(buf=b)[i, j] = (my_data.R_fcx.v(buf=b)[i, j] @ + U_yr.v(buf=b)[i, j] = (my_data.R_fcy.v(buf=b)[i, j] @ U.v(buf=b)[i, j]) gamma = rp.get_param("eos.gamma") @@ -141,25 +141,25 @@ def fluxes(my_data, rp, ivars, solid, tc): for i in range(ilo - 1, ihi + 1): for j in range(jlo - 1, jhi + 1): - A_plus_delta_q_x[i, j, :] = myg.gamma_fcy[i, j] * \ - (my_data.R_fcy[i, j]).T @ \ + A_plus_delta_q_x[i, j, :] = myg.gamma_fcx[i, j] * \ + (my_data.R_fcx[i, j]).T @ \ (interface.consFlux(1, gamma, ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux, U_xr[i, j, :]) - F_x[i, j, :]) - A_minus_delta_q_x[i, j, :] = myg.gamma_fcy[i, j] * \ - (my_data.R_fcy[i, j]).T @ \ + A_minus_delta_q_x[i, j, :] = myg.gamma_fcx[i, j] * \ + (my_data.R_fcx[i, j]).T @ \ (F_x[i, j, :] - interface.consFlux(1, gamma, ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux, U_xl[i, j, :])) - A_plus_delta_q_y[i, j, :] = myg.gamma_fcx[i, j] * \ - (my_data.R_fcx[i, j]).T @ \ + A_plus_delta_q_y[i, j, :] = myg.gamma_fcy[i, j] * \ + (my_data.R_fcy[i, j]).T @ \ (interface.consFlux(2, gamma, ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux, U_yr[i, j, :]) - F_y[i, j, :]) - A_minus_delta_q_y[i, j, :] = myg.gamma_fcx[i, j] * \ - (my_data.R_fcx[i, j]).T @ \ + A_minus_delta_q_y[i, j, :] = myg.gamma_fcy[i, j] * \ + (my_data.R_fcy[i, j]).T @ \ (F_y[i, j, :] - interface.consFlux(2, gamma, ivars.idens, ivars.ixmom, ivars.iymom, ivars.iener, ivars.irhox, ivars.naux, diff --git a/mesh/mapped.py b/mesh/mapped.py index 3c7fe2f7b..1b1cd5304 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -144,11 +144,8 @@ def scratch_array(self, nvar=1): and number of ghostcells as the parent grid """ - def isTuple(x): - return isinstance(x, tuple) - def flatten(t): - if not isTuple(t): + if not isinstance(t, tuple): return (t, ) elif len(t) == 0: return () @@ -158,9 +155,11 @@ def flatten(t): if nvar == 1: _tmp = np.zeros((self.qx, self.qy), dtype=np.float64) else: - _tmp = np.zeros((self.qx, self.qy) + flatten(nvar), dtype=np.float64) + _tmp = np.zeros((self.qx, self.qy) + + flatten(nvar), dtype=np.float64) return ai.ArrayIndexer(d=_tmp, grid=self) + class MappedCellCenterData2d(CellCenterData2d): def __init__(self, grid, dtype=np.float64): @@ -180,6 +179,7 @@ def make_rotation_matrices(self, ivars): self.R_fcx = self.grid.R_fcx(ivars.nvar, ivars.ixmom, ivars.iymom) self.R_fcy = self.grid.R_fcy(ivars.nvar, ivars.ixmom, ivars.iymom) + def mapped_cell_center_data_clone(old): """ Create a new CellCenterData2d object that is a copy of an existing @@ -215,5 +215,5 @@ def mapped_cell_center_data_clone(old): new.R_fcx = old.R_fcx.copy() new.R_fcy = old.R_fcy.copy() - + return new From 82b59035c21a95b169aeb7972eef6c69009bb2a2 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Tue, 26 Feb 2019 14:25:52 -0500 Subject: [PATCH 07/21] use sympy to calculate area elements --- .../problems/acoustic_pulse.py | 8 ++++ compressible_mapped/simulation.py | 14 ++++--- mesh/mapped.py | 42 ++++++++++++++----- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 5690ee44f..6f85abb3a 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -81,6 +81,14 @@ def R(iface, myg, nvar, ixmom, iymom): return R_fc +def map(myg): + + xs_t = myg.x2d * 2 + ys_t = myg.y2d + + return xs_t, ys_t + + def finalize(): """ print out any information to the user at the end of the run """ pass diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 00810ea8a..3f5366768 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -18,7 +18,7 @@ import compressible.derives as derives -def mapped_grid_setup(rp, area, h, R, ng=1): +def mapped_grid_setup(rp, area, h, R, map, ng=1): nx = rp.get_param("mesh.nx") ny = rp.get_param("mesh.ny") @@ -49,7 +49,7 @@ def mapped_grid_setup(rp, area, h, R, ng=1): my_grid = mapped.MappedGrid2d(nx, ny, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, ng=ng, - area_func=area, h_func=h, R_func=R) + area_func=area, h_func=h, R_func=R, map_func=map) return my_grid @@ -71,7 +71,7 @@ def initialize(self, extra_vars=None, ng=4): self.solver_name, self.problem_name)) my_grid = mapped_grid_setup( - self.rp, problem.area, problem.h, problem.R, ng=ng) + self.rp, problem.area, problem.h, problem.R, problem.map, ng=ng) my_data = self.data_class(my_grid) # define solver specific boundary condition routines @@ -222,8 +222,12 @@ def dovis(self): for n, ax in enumerate(axes): v = fields[n] - X = myg.x2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcy.v() - Y = myg.y2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcx.v() + # X = myg.x2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcy.v() + # Y = myg.y2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcx.v() + + X, Y = myg.map + X = X[myg.ng:-myg.ng, myg.ng:-myg.ng] + Y = Y[myg.ng:-myg.ng, myg.ng:-myg.ng] img = ax.pcolormesh(X, Y, v.v(), cmap=self.cm) diff --git a/mesh/mapped.py b/mesh/mapped.py index 1b1cd5304..9cb41158b 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -33,12 +33,9 @@ from __future__ import print_function import numpy as np -# -# import h5py -# +import sympy +from sympy.abc import x, y from util import msg -# -# import mesh.boundary as bnd import mesh.array_indexer as ai from functools import partial from mesh.patch import Grid2d, CellCenterData2d @@ -66,7 +63,7 @@ class MappedGrid2d(Grid2d): def __init__(self, nx, ny, ng=1, xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, - area_func=None, h_func=None, R_func=None): + area_func=None, h_func=None, R_func=None, map_func=None): """ Create a Grid2d object. @@ -99,15 +96,29 @@ def __init__(self, nx, ny, ng=1, super().__init__(nx, ny, ng, xmin, xmax, ymin, ymax) + self.map = map_func(self) + self.kappa, self.gamma_fcx, self.gamma_fcy = self.calculate_metric_elements( area_func, h_func) self.R_fcx, self.R_fcy = self.calculate_rotation_matrices(R_func) - # self.R_fcx = self.scratch_array() + 1.0 - # self.R_fcy = self.scratch_array() + 1.0 - # self.R_T_fcx = self.scratch_array() + 1.0 - # self.R_T_fcy = self.scratch_array() + 1.0 + def sym_area_element(p, u, v): + """ + Use sympy to calculate area element using https://mzucker.github.io/2018/04/12/sympy-part-3-moar-derivatives.html + """ + + def norm(z): + return sympy.sqrt(z.dot(z)) + + p1 = sympy.simplify(p.diff(u)) + p2 = sympy.simplify(p.diff(v)) + + p1_cross_p2 = sympy.simplify(p1.cross(p2)) + + dA = sympy.simplify(norm(p1_cross_p2)) + + return dA def calculate_metric_elements(self, area, h): """ @@ -117,7 +128,16 @@ def calculate_metric_elements(self, area, h): kappa = self.scratch_array() - kappa[:, :] = area(self) / (self.dx * self.dy) + if isinstance(self.map, sympy.Matrix): + # calculate sympy formula on grid + sym_dA = self.sym_area_element(self.map, x, y) + dA = sympy.lambdify((x, y), sym_dA) + + for i in range(self.qx): + for j in range(self.qy): + kappa[i, j] = dA(self.x2d[i, j], self.y2d[i, j]) + else: + kappa[:, :] = area(self) / (self.dx * self.dy) hx = self.scratch_array() hy = self.scratch_array() From 414b26614d2273329396e49a7cd5efa8363a982c Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Tue, 26 Feb 2019 14:44:51 -0500 Subject: [PATCH 08/21] use sympy to calculate area elements --- .../problems/acoustic_pulse.py | 10 ++++- mesh/mapped.py | 43 +++++++++++++------ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 6f85abb3a..4b75d4285 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -1,9 +1,11 @@ from __future__ import print_function -import sys -import mesh.fv as fv +# import sys +# import mesh.fv as fv import numpy as np from util import msg +import sympy +from sympy.abs import x, y, z def init_data(myd, rp): @@ -88,6 +90,10 @@ def map(myg): return xs_t, ys_t +def sym_map(myg): + + return sympy.Matrix([2 * x, y, z]) + def finalize(): """ print out any information to the user at the end of the run """ diff --git a/mesh/mapped.py b/mesh/mapped.py index 9cb41158b..f5baacf29 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -103,7 +103,11 @@ def __init__(self, nx, ny, ng=1, self.R_fcx, self.R_fcy = self.calculate_rotation_matrices(R_func) - def sym_area_element(p, u, v): + @staticmethod + def norm(z): + return sympy.sqrt(z.dot(z)) + + def sym_area_element(self): """ Use sympy to calculate area element using https://mzucker.github.io/2018/04/12/sympy-part-3-moar-derivatives.html """ @@ -111,15 +115,25 @@ def sym_area_element(p, u, v): def norm(z): return sympy.sqrt(z.dot(z)) - p1 = sympy.simplify(p.diff(u)) - p2 = sympy.simplify(p.diff(v)) + p1 = sympy.simplify(self.map.diff(x)) + p2 = sympy.simplify(self.map.diff(y)) p1_cross_p2 = sympy.simplify(p1.cross(p2)) - dA = sympy.simplify(norm(p1_cross_p2)) + dA = sympy.simplify(self.norm(p1_cross_p2)) return dA + def sym_line_elements(self): + """ + Use sympy to calculate the line elements + """ + + l1 = sympy.simplify(sympy.norm(self.map.diff(y))) + l2 = sympy.simplify(sympy.norm(self.map.diff(x))) + + return l1, l2 + def calculate_metric_elements(self, area, h): """ Given the functions for the area and line elements, calculate them on @@ -127,25 +141,30 @@ def calculate_metric_elements(self, area, h): """ kappa = self.scratch_array() + hx = self.scratch_array() + hy = self.scratch_array() if isinstance(self.map, sympy.Matrix): # calculate sympy formula on grid - sym_dA = self.sym_area_element(self.map, x, y) + sym_dA = self.sym_area_element() dA = sympy.lambdify((x, y), sym_dA) + sym_hx, sym_hy = self.sym_line_elements() + _hx = sympy.lambdify((x, y), sym_hx) + _hy = sympy.lambdify((x, y), sym_hy) + for i in range(self.qx): for j in range(self.qy): kappa[i, j] = dA(self.x2d[i, j], self.y2d[i, j]) + hx[i,j] = _hx(self.x2d[i,j] - 0.5*self.dx, self.y2d[i,j]) + hy[i,j] = _hy(self.x2d[i,j], self.y2d[i,j] - 0.5*self.dy) + else: kappa[:, :] = area(self) / (self.dx * self.dy) + hx[:, :] = h(1, self) / self.dy + hy[:, :] = h(2, self) / self.dx - hx = self.scratch_array() - hy = self.scratch_array() - - hx[:, :] = h(1, self) - hy[:, :] = h(2, self) - - return kappa, hx / self.dy, hy / self.dx + return kappa, hx, hy def calculate_rotation_matrices(self, R): """ From 944389fa210efc0fc6b74d1e0c8e950be524f08b Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Tue, 26 Feb 2019 15:42:00 -0500 Subject: [PATCH 09/21] mapped grids work with sympy calculating stuff (at least for rectilinear) --- .../problems/acoustic_pulse.py | 3 +- compressible_mapped/simulation.py | 12 ++-- mesh/mapped.py | 67 ++++++++++++++++--- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 4b75d4285..3a5c41b56 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -5,7 +5,7 @@ import numpy as np from util import msg import sympy -from sympy.abs import x, y, z +from sympy.abc import x, y, z def init_data(myd, rp): @@ -90,6 +90,7 @@ def map(myg): return xs_t, ys_t + def sym_map(myg): return sympy.Matrix([2 * x, y, z]) diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 3f5366768..23414d0f5 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -71,7 +71,7 @@ def initialize(self, extra_vars=None, ng=4): self.solver_name, self.problem_name)) my_grid = mapped_grid_setup( - self.rp, problem.area, problem.h, problem.R, problem.map, ng=ng) + self.rp, problem.area, problem.h, problem.R, problem.sym_map, ng=ng) my_data = self.data_class(my_grid) # define solver specific boundary condition routines @@ -222,12 +222,12 @@ def dovis(self): for n, ax in enumerate(axes): v = fields[n] - # X = myg.x2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcy.v() - # Y = myg.y2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcx.v() + X = myg.x2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcy.v() + Y = myg.y2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcx.v() - X, Y = myg.map - X = X[myg.ng:-myg.ng, myg.ng:-myg.ng] - Y = Y[myg.ng:-myg.ng, myg.ng:-myg.ng] + # X, Y = myg.map + # X = X[myg.ng:-myg.ng, myg.ng:-myg.ng] + # Y = Y[myg.ng:-myg.ng, myg.ng:-myg.ng] img = ax.pcolormesh(X, Y, v.v(), cmap=self.cm) diff --git a/mesh/mapped.py b/mesh/mapped.py index f5baacf29..7fdd0984c 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -129,11 +129,22 @@ def sym_line_elements(self): Use sympy to calculate the line elements """ - l1 = sympy.simplify(sympy.norm(self.map.diff(y))) - l2 = sympy.simplify(sympy.norm(self.map.diff(x))) + l1 = sympy.simplify(sympy.Abs(self.map.diff(y))) + l2 = sympy.simplify(sympy.Abs(self.map.diff(x))) return l1, l2 + def sym_rotation_matrix(self): + """ + Use sympy to calculate the rotation matrix (which is just the Jacobian??) + """ + + J = sympy.Matrix(self.map[:-1]).jacobian((x, y)) + J[0,:] /= J[0,:].norm() + J[1,:] /= J[1,:].norm() + + return J + def calculate_metric_elements(self, area, h): """ Given the functions for the area and line elements, calculate them on @@ -147,17 +158,16 @@ def calculate_metric_elements(self, area, h): if isinstance(self.map, sympy.Matrix): # calculate sympy formula on grid sym_dA = self.sym_area_element() - dA = sympy.lambdify((x, y), sym_dA) sym_hx, sym_hy = self.sym_line_elements() - _hx = sympy.lambdify((x, y), sym_hx) - _hy = sympy.lambdify((x, y), sym_hy) for i in range(self.qx): for j in range(self.qy): - kappa[i, j] = dA(self.x2d[i, j], self.y2d[i, j]) - hx[i,j] = _hx(self.x2d[i,j] - 0.5*self.dx, self.y2d[i,j]) - hy[i,j] = _hy(self.x2d[i,j], self.y2d[i,j] - 0.5*self.dy) + kappa[i, j] = sym_dA.subs((x, self.x2d[i, j]), (y, self.y2d[i, j])) + hx[i, j] = sym_hx.subs((x, self.x2d[i, j] - 0.5 * + self.dx), (y, self.y2d[i, j]))[1] + hy[i, j] = sym_hy.subs( + (x, self.x2d[i, j]), (y, self.y2d[i, j] - 0.5 * self.dy))[0] else: kappa[:, :] = area(self) / (self.dx * self.dy) @@ -172,8 +182,45 @@ def calculate_rotation_matrices(self, R): the variables. """ - R_fcx = partial(R, 1, self) - R_fcy = partial(R, 2, self) + if isinstance(self.map, sympy.Matrix): + sym_R = self.sym_rotation_matrix() + R = sympy.lambdify((x, y), sym_R) + + def R_fcx(nvar, ixmom, iymom): + R_fc = self.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(self.qx): + for j in range(self.qy): + R_fc[i, j, :, :] = R_mat + + R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + + 1] = R(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) + + return R_fc + + # print(R_fcx(4, 2, 3)) + + def R_fcy(nvar, ixmom, iymom): + R_fc = self.scratch_array(nvar=(nvar, nvar)) + + R_mat = np.eye(nvar) + + for i in range(self.qx): + for j in range(self.qy): + R_fc[i, j, :, :] = R_mat + + R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + + 1] = R(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) + return R_fc + + # print(R_fcy(4, 2, 3)) + else: + R_fcx = partial(R, 1, self) + R_fcy = partial(R, 2, self) + + # print(R_fcx(4, 2, 3)) return R_fcx, R_fcy From 35834459f3c4df947b4163fc8f2cb8ee0b29c47d Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Wed, 27 Feb 2019 09:35:14 -0500 Subject: [PATCH 10/21] made a NullVariables class, added some documentation for the mapped grids --- compressible/simulation.py | 61 ++++---- .../problems/acoustic_pulse.py | 4 +- compressible_mapped/simulation.py | 10 +- docs/source/mapped_basics.rst | 81 ++++++++++ docs/source/mesh.rst | 8 + docs/source/mesh_basics.rst | 4 +- mesh/mapped.py | 139 +++++++++--------- simulation_null.py | 24 ++- 8 files changed, 221 insertions(+), 110 deletions(-) create mode 100644 docs/source/mapped_basics.rst diff --git a/compressible/simulation.py b/compressible/simulation.py index 42169d293..dc20cfa49 100644 --- a/compressible/simulation.py +++ b/compressible/simulation.py @@ -10,18 +10,18 @@ import compressible.derives as derives import compressible.unsplit_fluxes as flx import mesh.boundary as bnd -from simulation_null import NullSimulation, grid_setup, bc_setup +from simulation_null import NullSimulation, NullVariables, grid_setup, bc_setup import util.plot_tools as plot_tools import particles.particles as particles -class Variables(object): +class Variables(NullVariables): """ a container class for easy access to the different compressible variable by an integer key """ - def __init__(self, myd): - self.nvar = len(myd.names) + + def initialize(self, myd): # conserved variables -- we set these when we initialize for # they match the CellCenterData2d object @@ -58,19 +58,19 @@ def cons_to_prim(U, gamma, ivars, myg): q = myg.scratch_array(nvar=ivars.nq) q[:, :, ivars.irho] = U[:, :, ivars.idens] - q[:, :, ivars.iu] = U[:, :, ivars.ixmom]/U[:, :, ivars.idens] - q[:, :, ivars.iv] = U[:, :, ivars.iymom]/U[:, :, ivars.idens] + q[:, :, ivars.iu] = U[:, :, ivars.ixmom] / U[:, :, ivars.idens] + q[:, :, ivars.iv] = U[:, :, ivars.iymom] / U[:, :, ivars.idens] e = (U[:, :, ivars.iener] - - 0.5*q[:, :, ivars.irho]*(q[:, :, ivars.iu]**2 + - q[:, :, ivars.iv]**2))/q[:, :, ivars.irho] + 0.5 * q[:, :, ivars.irho] * (q[:, :, ivars.iu]**2 + + q[:, :, ivars.iv]**2)) / q[:, :, ivars.irho] q[:, :, ivars.ip] = eos.pres(gamma, q[:, :, ivars.irho], e) if ivars.naux > 0: - for nq, nu in zip(range(ivars.ix, ivars.ix+ivars.naux), - range(ivars.irhox, ivars.irhox+ivars.naux)): - q[:, :, nq] = U[:, :, nu]/q[:, :, ivars.irho] + for nq, nu in zip(range(ivars.ix, ivars.ix + ivars.naux), + range(ivars.irhox, ivars.irhox + ivars.naux)): + q[:, :, nq] = U[:, :, nu] / q[:, :, ivars.irho] return q @@ -81,18 +81,18 @@ def prim_to_cons(q, gamma, ivars, myg): 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] + 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) + 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] + 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 @@ -113,7 +113,8 @@ def initialize(self, extra_vars=None, ng=4): # define solver specific boundary condition routines bnd.define_bc("hse", BC.user, is_solid=False) - bnd.define_bc("ramp", BC.user, is_solid=False) # for double mach reflection problem + # for double mach reflection problem + bnd.define_bc("ramp", BC.user, is_solid=False) bc, bc_xodd, bc_yodd = bc_setup(self.rp) @@ -182,10 +183,10 @@ def method_compute_timestep(self): u, v, cs = self.cc_data.get_var(["velocity", "soundspeed"]) # the timestep is min(dx/(|u| + cs), dy/(|v| + cs)) - xtmp = self.cc_data.grid.dx/(abs(u) + cs) - ytmp = self.cc_data.grid.dy/(abs(v) + cs) + xtmp = self.cc_data.grid.dx / (abs(u) + cs) + ytmp = self.cc_data.grid.dy / (abs(v) + cs) - self.dt = cfl*float(min(xtmp.min(), ytmp.min())) + self.dt = cfl * float(min(xtmp.min(), ytmp.min())) def evolve(self): """ @@ -211,19 +212,19 @@ def evolve(self): old_ymom = ymom.copy() # conservative update - dtdx = self.dt/myg.dx - dtdy = self.dt/myg.dy + dtdx = self.dt / myg.dx + dtdy = self.dt / myg.dy for n in range(self.ivars.nvar): var = self.cc_data.get_var_by_index(n) var.v()[:, :] += \ - dtdx*(Flux_x.v(n=n) - Flux_x.ip(1, n=n)) + \ - dtdy*(Flux_y.v(n=n) - Flux_y.jp(1, n=n)) + dtdx * (Flux_x.v(n=n) - Flux_x.ip(1, n=n)) + \ + dtdy * (Flux_y.v(n=n) - Flux_y.jp(1, n=n)) # gravitational source terms - ymom[:, :] += 0.5*self.dt*(dens[:, :] + old_dens[:, :])*grav - ener[:, :] += 0.5*self.dt*(ymom[:, :] + old_ymom[:, :])*grav + ymom[:, :] += 0.5 * self.dt * (dens[:, :] + old_dens[:, :]) * grav + ener[:, :] += 0.5 * self.dt * (ymom[:, :] + old_ymom[:, :]) * grav if self.particles is not None: self.particles.update_particles(self.dt) @@ -257,7 +258,7 @@ def dovis(self): u = q[:, :, ivars.iu] v = q[:, :, ivars.iv] p = q[:, :, ivars.ip] - e = eos.rhoe(gamma, p)/rho + e = eos.rhoe(gamma, p) / rho magvel = np.sqrt(u**2 + v**2) @@ -297,7 +298,7 @@ def dovis(self): # plot particles ax.scatter(particle_positions[:, 0], - particle_positions[:, 1], s=5, c=colors, alpha=0.8, cmap="Greys") + 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]) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 3a5c41b56..aa35e3560 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -5,7 +5,7 @@ import numpy as np from util import msg import sympy -from sympy.abc import x, y, z +from sympy.abc import x, y def init_data(myd, rp): @@ -93,7 +93,7 @@ def map(myg): def sym_map(myg): - return sympy.Matrix([2 * x, y, z]) + return sympy.Matrix([2 * x, y-1]) def finalize(): diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 23414d0f5..a1be03e44 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -18,7 +18,7 @@ import compressible.derives as derives -def mapped_grid_setup(rp, area, h, R, map, ng=1): +def mapped_grid_setup(rp, map, ng=1): nx = rp.get_param("mesh.nx") ny = rp.get_param("mesh.ny") @@ -46,10 +46,9 @@ def mapped_grid_setup(rp, area, h, R, map, ng=1): ymax = 1.0 msg.warning("mesh.ynax not set, defaulting to 1.0") - my_grid = mapped.MappedGrid2d(nx, ny, + my_grid = mapped.MappedGrid2d(map, nx, ny, xmin=xmin, xmax=xmax, - ymin=ymin, ymax=ymax, ng=ng, - area_func=area, h_func=h, R_func=R, map_func=map) + ymin=ymin, ymax=ymax, ng=ng) return my_grid @@ -70,8 +69,7 @@ def initialize(self, extra_vars=None, ng=4): problem = importlib.import_module("{}.problems.{}".format( self.solver_name, self.problem_name)) - my_grid = mapped_grid_setup( - self.rp, problem.area, problem.h, problem.R, problem.sym_map, ng=ng) + my_grid = mapped_grid_setup(self.rp, problem.sym_map, ng=ng) my_data = self.data_class(my_grid) # define solver specific boundary condition routines diff --git a/docs/source/mapped_basics.rst b/docs/source/mapped_basics.rst new file mode 100644 index 000000000..e7ec9300f --- /dev/null +++ b/docs/source/mapped_basics.rst @@ -0,0 +1,81 @@ +:mod:`mesh.mapped ` implementation and use +------------------------------------------------------- + +This module defines the structures required for mapped grids. It defines the classes +:func:`MappedGrid2d ` and +:func:`MappedCellCenterData2d ` that inherit from +the un-mapped versions, :func:`Grid2d ` and +:func:`CellCenterData2d `. + +We import the basic mapped grids functionality as: + +.. code-block:: python + + import mesh.mapped as mapped + +The classes in the mapped module that we interact with are: + +* :func:`mapped.MappedGrid2d `: this is the main mapped + grid class. It holds the coordinate grid (a :func:`Grid2d ` + object) and details about the mapping from the physical grid to the + coordinate grid. The mapping is defined using a sympy function: when the object + is instantiated, this analytic expression with then be used to calculate + the various numerical quantities on the actual grid. + +* :func:`mapped.MappedCellCenterData2d `: this + holds the cell-centered data on the coordinate grid. It is identical to its + parent class, :func:`CellCenterData2d `, except + it also defines the rotation matrices that define how the velocity + components are mapped between the physical and coordinate grids (these + rotation matrices cannot be fully defined on the grid itself as they require + information about the variables which the grid alone does not have). + +The procedure for setting up a mapped grid and the data that lives on it is as +follows: + +.. code-block:: python + + import sympy + from sympy.abs import x, y + import mesh.mapped as mapped + import mesh.boundary as bnd + import compressible + + mapping = sympy.Matrix([2 * x + 3, y**2]) + + myg = mapped.MappedGrid2d(mapping, 16, 32, xmax=1.0, ymax=2.0) + +This creates a 2-d mapped grid object ``myg`` with 16 zones in the x-direction +and 32 zones in the y-direction on the coordinate grid. It also specifies the +extent of the coordinate grid in the x- and y-directions. The mapping is defined +using a ``sympy.Matrix`` object as a function of the cartesian coordinates +``x`` and ``y``. + +.. note:: + + The mapping must be specified as a function of the ``sympy.Symbol`` objects + ``x`` and ``y`` only. + +.. code-block:: python + + mydata = mapped.MappedCellCenterData2d(myg) + + bc = bnd.BC(xlb="periodic", xrb="periodic", ylb="reflect-even", yrb="outflow") + + mydata.register_var("a", bc) + mydata.create() + + ivars = compressible.Variables(mydata) + + mydata.make_rotation_matrices(ivars) + +This create the mapped cell-centered data object, ``mydata``, that lives on the +mapped grid we just defined. Just as we would for the non-mapped grid, we next +create a boundary condition object to specify the boundary conditions on each edge, +register variables and call the ``create()`` function to allocate storage for the +variables. For the mapped grid, there is one more step that we must do: define the +rotation matrices associated with the variables. To do this, we define a +``Variables`` object (here we use the one from the compressible module), then +pass this to the data object's :func:`make_rotation_matrices ` method. This will +take the rotation matrix function defined on the mapped grid object ``myg`` and +create the actual matrices associated with the data's variables. diff --git a/docs/source/mesh.rst b/docs/source/mesh.rst index 0b8fde256..0503b2dee 100644 --- a/docs/source/mesh.rst +++ b/docs/source/mesh.rst @@ -41,6 +41,14 @@ mesh\.integration module :undoc-members: :show-inheritance: +mesh\.mapped module +------------------------ + +.. automodule:: mesh.mapped + :members: + :undoc-members: + :show-inheritance: + mesh\.patch module ------------------ diff --git a/docs/source/mesh_basics.rst b/docs/source/mesh_basics.rst index 5ba86e6f8..cc6b1ce29 100644 --- a/docs/source/mesh_basics.rst +++ b/docs/source/mesh_basics.rst @@ -27,7 +27,7 @@ We import the basic mesh functionality as: import mesh.boundary as bnd import mesh.array_indexer as ai -There are several main objects in the patch class that we interact with: +There are several main classes in the patch module that we interact with: * :func:`patch.Grid2d `: this is the main grid object. It is basically a container that holds the number of zones @@ -96,6 +96,8 @@ Note that each variable needs to specify a BC—this allows us to do different actions for each variable (for example, some may do even reflection while others may do odd reflection). +.. include:: mapped_basics.rst + Jupyter notebook ---------------- diff --git a/mesh/mapped.py b/mesh/mapped.py index 7fdd0984c..029110547 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -34,10 +34,9 @@ import numpy as np import sympy -from sympy.abc import x, y +from sympy.abc import x, y, z from util import msg import mesh.array_indexer as ai -from functools import partial from mesh.patch import Grid2d, CellCenterData2d @@ -59,13 +58,10 @@ class MappedGrid2d(Grid2d): The '*' marks the data locations. """ - # pylint: disable=too-many-instance-attributes - - def __init__(self, nx, ny, ng=1, - xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, - area_func=None, h_func=None, R_func=None, map_func=None): + def __init__(self, map_func, nx, ny, ng=1, + xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0): """ - Create a Grid2d object. + Create a MappedGrid2d object. The only data that we require is the number of points that make up the mesh in each direction. Optionally we take the @@ -78,6 +74,7 @@ def __init__(self, nx, ny, ng=1, Parameters ---------- + map_func : sympy.Matrix nx : int Number of zones in the x-direction ny : int @@ -85,23 +82,24 @@ def __init__(self, nx, ny, ng=1, ng : int, optional Number of ghost cells xmin : float, optional - Physical coordinate at the lower x boundary + Mapped coordinate at the lower x boundary xmax : float, optional - Physical coordinate at the upper x boundary + Mapped coordinate at the upper x boundary ymin : float, optional - Physical coordinate at the lower y boundary + Mapped coordinate at the lower y boundary ymax : float, optional - Physical coordinate at the upper y boundary + Mapped coordinate at the upper y boundary """ super().__init__(nx, ny, ng, xmin, xmax, ymin, ymax) - self.map = map_func(self) + # we need to add a z-direction so that we can calculate the cross product + # of the basis vectors + self.map = map_func(self).col_join(sympy.Matrix([z])) - self.kappa, self.gamma_fcx, self.gamma_fcy = self.calculate_metric_elements( - area_func, h_func) + self.kappa, self.gamma_fcx, self.gamma_fcy = self.calculate_metric_elements() - self.R_fcx, self.R_fcy = self.calculate_rotation_matrices(R_func) + self.R_fcx, self.R_fcy = self.calculate_rotation_matrices() @staticmethod def norm(z): @@ -109,7 +107,8 @@ def norm(z): def sym_area_element(self): """ - Use sympy to calculate area element using https://mzucker.github.io/2018/04/12/sympy-part-3-moar-derivatives.html + Use sympy to calculate area element using + https://mzucker.github.io/2018/04/12/sympy-part-3-moar-derivatives.html """ def norm(z): @@ -136,16 +135,16 @@ def sym_line_elements(self): def sym_rotation_matrix(self): """ - Use sympy to calculate the rotation matrix (which is just the Jacobian??) + Use sympy to calculate the rotation matrix """ J = sympy.Matrix(self.map[:-1]).jacobian((x, y)) - J[0,:] /= J[0,:].norm() - J[1,:] /= J[1,:].norm() + J[0, :] /= J[0, :].norm() + J[1, :] /= J[1, :].norm() return J - def calculate_metric_elements(self, area, h): + def calculate_metric_elements(self): """ Given the functions for the area and line elements, calculate them on the grid. @@ -155,70 +154,73 @@ def calculate_metric_elements(self, area, h): hx = self.scratch_array() hy = self.scratch_array() - if isinstance(self.map, sympy.Matrix): - # calculate sympy formula on grid - sym_dA = self.sym_area_element() + # if isinstance(self.map, sympy.Matrix): + # calculate sympy formula on grid + sym_dA = self.sym_area_element() - sym_hx, sym_hy = self.sym_line_elements() + sym_hx, sym_hy = self.sym_line_elements() - for i in range(self.qx): - for j in range(self.qy): - kappa[i, j] = sym_dA.subs((x, self.x2d[i, j]), (y, self.y2d[i, j])) - hx[i, j] = sym_hx.subs((x, self.x2d[i, j] - 0.5 * - self.dx), (y, self.y2d[i, j]))[1] - hy[i, j] = sym_hy.subs( - (x, self.x2d[i, j]), (y, self.y2d[i, j] - 0.5 * self.dy))[0] + for i in range(self.qx): + for j in range(self.qy): + kappa[i, j] = sym_dA.subs( + (x, self.x2d[i, j]), (y, self.y2d[i, j])) + hx[i, j] = sym_hx.subs((x, self.x2d[i, j] - 0.5 * + self.dx), (y, self.y2d[i, j]))[1] + hy[i, j] = sym_hy.subs( + (x, self.x2d[i, j]), (y, self.y2d[i, j] - 0.5 * self.dy))[0] - else: - kappa[:, :] = area(self) / (self.dx * self.dy) - hx[:, :] = h(1, self) / self.dy - hy[:, :] = h(2, self) / self.dx + # else: + # kappa[:, :] = area(self) / (self.dx * self.dy) + # hx[:, :] = h(1, self) / self.dy + # hy[:, :] = h(2, self) / self.dx return kappa, hx, hy - def calculate_rotation_matrices(self, R): + def calculate_rotation_matrices(self): """ - We're going to use partial functions here as the grid knows nothing of - the variables. + Calculate the rotation matrices on the cell interfaces. + It will return this as functions of nvar, ixmom and iymom - the grid + itself knows nothing of the variables, so these must be specified + by the MappedCellCenterData2d object. """ - if isinstance(self.map, sympy.Matrix): - sym_R = self.sym_rotation_matrix() - R = sympy.lambdify((x, y), sym_R) + # if isinstance(self.map, sympy.Matrix): + sym_R = self.sym_rotation_matrix() + R = sympy.lambdify((x, y), sym_R) - def R_fcx(nvar, ixmom, iymom): - R_fc = self.scratch_array(nvar=(nvar, nvar)) + def R_fcx(nvar, ixmom, iymom): + R_fc = self.scratch_array(nvar=(nvar, nvar)) - R_mat = np.eye(nvar) + R_mat = np.eye(nvar) - for i in range(self.qx): - for j in range(self.qy): - R_fc[i, j, :, :] = R_mat + for i in range(self.qx): + for j in range(self.qy): + R_fc[i, j, :, :] = R_mat - R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + - 1] = R(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) + R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + + 1] = R(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) - return R_fc + return R_fc - # print(R_fcx(4, 2, 3)) + # print(R_fcx(4, 2, 3)) - def R_fcy(nvar, ixmom, iymom): - R_fc = self.scratch_array(nvar=(nvar, nvar)) + def R_fcy(nvar, ixmom, iymom): + R_fc = self.scratch_array(nvar=(nvar, nvar)) - R_mat = np.eye(nvar) + R_mat = np.eye(nvar) - for i in range(self.qx): - for j in range(self.qy): - R_fc[i, j, :, :] = R_mat + for i in range(self.qx): + for j in range(self.qy): + R_fc[i, j, :, :] = R_mat - R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + - 1] = R(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) - return R_fc + R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + + 1] = R(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) + return R_fc # print(R_fcy(4, 2, 3)) - else: - R_fcx = partial(R, 1, self) - R_fcy = partial(R, 2, self) + # else: + # R_fcx = partial(R, 1, self) + # R_fcy = partial(R, 2, self) # print(R_fcx(4, 2, 3)) @@ -227,7 +229,10 @@ def R_fcy(nvar, ixmom, iymom): def scratch_array(self, nvar=1): """ return a standard numpy array dimensioned to have the size - and number of ghostcells as the parent grid + and number of ghostcells as the parent grid. + + Here I've generalized the version in Grid2d so that we can define + tensors (not just scalars and vectors) e.g. the rotation matrices """ def flatten(t): @@ -252,8 +257,8 @@ def __init__(self, grid, dtype=np.float64): super().__init__(grid, dtype=dtype) - # self.R_fcx = [] - # self.R_fcy = [] + self.R_fcx = [] + self.R_fcy = [] def make_rotation_matrices(self, ivars): """ diff --git a/simulation_null.py b/simulation_null.py index 1f98ca39d..5bc80a941 100644 --- a/simulation_null.py +++ b/simulation_null.py @@ -82,6 +82,20 @@ def bc_setup(rp): return bc, bc_xodd, bc_yodd +class NullVariables(object): + """ + a container class for easy access to the different variables by an integer key + """ + + def __init__(self, myd): + self.nvar = len(myd.names) + + self.initialize(myd) + + def initialize(self, myd): + pass + + class NullSimulation(object): def __init__(self, solver_name, problem_name, rp, timers=None, data_class=patch.CellCenterData2d): @@ -153,7 +167,8 @@ def do_output(self): n_out = self.rp.get_param("io.n_out") do_io = self.rp.get_param("io.do_io") - is_time = self.cc_data.t >= (self.n_num_out + 1)*dt_out or self.n % n_out == 0 + is_time = self.cc_data.t >= ( + self.n_num_out + 1) * dt_out or self.n % n_out == 0 if is_time and do_io == 1: self.n_num_out += 1 return True @@ -185,9 +200,9 @@ def compute_timestep(self): else: self.method_compute_timestep() if self.n == 0: - self.dt = init_tstep_factor*self.dt + self.dt = init_tstep_factor * self.dt else: - self.dt = min(max_dt_change*self.dt_old, self.dt) + self.dt = min(max_dt_change * self.dt_old, self.dt) self.dt_old = self.dt if self.cc_data.t + self.dt > self.tmax: @@ -215,7 +230,8 @@ def finalize(self): finalize() method. """ # there should be a cleaner way of doing this - problem = importlib.import_module("{}.problems.{}".format(self.solver_name, self.problem_name)) + problem = importlib.import_module( + "{}.problems.{}".format(self.solver_name, self.problem_name)) problem.finalize() From b0f73320b140626ae5df5c41110599f9691ad789 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Wed, 27 Feb 2019 11:57:36 -0500 Subject: [PATCH 11/21] added tests for curvilinear grids --- docs/source/mapped_basics.rst | 5 +++-- mesh/mapped.py | 26 ++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/docs/source/mapped_basics.rst b/docs/source/mapped_basics.rst index e7ec9300f..1d68bf535 100644 --- a/docs/source/mapped_basics.rst +++ b/docs/source/mapped_basics.rst @@ -41,7 +41,8 @@ follows: import mesh.boundary as bnd import compressible - mapping = sympy.Matrix([2 * x + 3, y**2]) + def mapping(myg): + return sympy.Matrix([2 * x + 3, y**2]) myg = mapped.MappedGrid2d(mapping, 16, 32, xmax=1.0, ymax=2.0) @@ -49,7 +50,7 @@ This creates a 2-d mapped grid object ``myg`` with 16 zones in the x-direction and 32 zones in the y-direction on the coordinate grid. It also specifies the extent of the coordinate grid in the x- and y-directions. The mapping is defined using a ``sympy.Matrix`` object as a function of the cartesian coordinates -``x`` and ``y``. +``x`` and ``y``. The mapping itself is a function of the mapped grid object. .. note:: diff --git a/mesh/mapped.py b/mesh/mapped.py index 029110547..1363c8984 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -128,8 +128,10 @@ def sym_line_elements(self): Use sympy to calculate the line elements """ - l1 = sympy.simplify(sympy.Abs(self.map.diff(y))) - l2 = sympy.simplify(sympy.Abs(self.map.diff(x))) + l1 = sympy.simplify(sympy.sqrt( + self.map[1].diff(x)**2 + self.map[1].diff(y)**2)) + l2 = sympy.simplify(sympy.sqrt( + self.map[0].diff(x)**2 + self.map[0].diff(y)**2)) return l1, l2 @@ -139,8 +141,10 @@ def sym_rotation_matrix(self): """ J = sympy.Matrix(self.map[:-1]).jacobian((x, y)) - J[0, :] /= J[0, :].norm() - J[1, :] /= J[1, :].norm() + if J[0, :].norm() != 0: + J[0, :] /= J[0, :].norm() + if J[1, :].norm() != 0: + J[1, :] /= J[1, :].norm() return J @@ -158,16 +162,18 @@ def calculate_metric_elements(self): # calculate sympy formula on grid sym_dA = self.sym_area_element() + _dA = sympy.lambdify((x, y), sym_dA, modules="sympy") + sym_hx, sym_hy = self.sym_line_elements() + _hx = sympy.lambdify((x, y), sym_hx, modules="sympy") + _hy = sympy.lambdify((x, y), sym_hy, modules="sympy") + for i in range(self.qx): for j in range(self.qy): - kappa[i, j] = sym_dA.subs( - (x, self.x2d[i, j]), (y, self.y2d[i, j])) - hx[i, j] = sym_hx.subs((x, self.x2d[i, j] - 0.5 * - self.dx), (y, self.y2d[i, j]))[1] - hy[i, j] = sym_hy.subs( - (x, self.x2d[i, j]), (y, self.y2d[i, j] - 0.5 * self.dy))[0] + kappa[i, j] = _dA(self.x2d[i, j], self.y2d[i, j]) + hx[i, j] = _hx(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) + hy[i, j] = _hy(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) # else: # kappa[:, :] = area(self) / (self.dx * self.dy) From e356ddb6ebf4881ff10085bfb23d20f84e6aedb0 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Wed, 27 Feb 2019 19:16:31 -0500 Subject: [PATCH 12/21] rotation matrix is less broken --- compressible/problems/acoustic_pulse.py | 10 +-- .../problems/acoustic_pulse.py | 48 ++++--------- compressible_mapped/simulation.py | 11 ++- mesh/mapped.py | 69 ++++++++++++++----- 4 files changed, 71 insertions(+), 67 deletions(-) diff --git a/compressible/problems/acoustic_pulse.py b/compressible/problems/acoustic_pulse.py index a9c98c2dd..aa36a9780 100644 --- a/compressible/problems/acoustic_pulse.py +++ b/compressible/problems/acoustic_pulse.py @@ -12,11 +12,11 @@ def init_data(myd, rp): 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() + # 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") diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index aa35e3560..4ce796bf5 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -5,7 +5,7 @@ import numpy as np from util import msg import sympy -from sympy.abc import x, y +from sympy.abc import x, y, p, q def init_data(myd, rp): @@ -45,11 +45,14 @@ def init_data(myd, rp): myg = myd.grid - xctr = 0.5 * (xmin + xmax) * myg.gamma_fcy - yctr = 0.5 * (ymin + ymax) * myg.gamma_fcx + xctr = 0.5 * (xmin + xmax) + yctr = 0.5 * (ymin + ymax) - dist = np.sqrt((myd.grid.x2d * myg.gamma_fcy - xctr)**2 + - (myd.grid.y2d * myg.gamma_fcx - yctr)**2) + X, Y = myg.physical_coords() + + xctr_t, yctr_t = myg.physical_coords(xctr, yctr) + + dist = np.sqrt((X - xctr_t)**2 + (Y - yctr_t)**2) dens[:, :] = rho0 idx = dist <= 0.5 @@ -60,40 +63,13 @@ def init_data(myd, rp): ener[:, :] = p / (gamma - 1) -def area(myg): - return 2 * myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return 2 * myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def map(myg): - - xs_t = myg.x2d * 2 - ys_t = myg.y2d - - return xs_t, ys_t +def sym_map(myg): + return sympy.Matrix([x+3 + y, -2*y]) -def sym_map(myg): +def inverse_map(myg): - return sympy.Matrix([2 * x, y-1]) + return sympy.Matrix([]) def finalize(): diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index a1be03e44..77323236c 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -217,16 +217,13 @@ def dovis(self): _, axes, cbar_title = plot_tools.setup_axes(myg, len(fields)) + X, Y = myg.physical_coords() + X = X[myg.ng:-myg.ng, myg.ng:-myg.ng] + Y = Y[myg.ng:-myg.ng, myg.ng:-myg.ng] + for n, ax in enumerate(axes): v = fields[n] - X = myg.x2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcy.v() - Y = myg.y2d[myg.ng:-myg.ng, myg.ng:-myg.ng] * myg.gamma_fcx.v() - - # X, Y = myg.map - # X = X[myg.ng:-myg.ng, myg.ng:-myg.ng] - # Y = Y[myg.ng:-myg.ng, myg.ng:-myg.ng] - img = ax.pcolormesh(X, Y, v.v(), cmap=self.cm) ax.set_xlabel("x") diff --git a/mesh/mapped.py b/mesh/mapped.py index 1363c8984..58c902886 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -137,16 +137,27 @@ def sym_line_elements(self): def sym_rotation_matrix(self): """ - Use sympy to calculate the rotation matrix + Use sympy to calculate the rotation matrices """ J = sympy.Matrix(self.map[:-1]).jacobian((x, y)) - if J[0, :].norm() != 0: - J[0, :] /= J[0, :].norm() - if J[1, :].norm() != 0: - J[1, :] /= J[1, :].norm() - return J + # normalize + J[0,:] /= J[0,:].norm() + J[1,:] /= J[1,:].norm() + + Rx = sympy.zeros(2) + Ry = sympy.zeros(2) + + Rx[1,:] = J[1,:] + Rx[0,0] = J[1,1] + Rx[0,1] = -J[1,0] + + Ry[1,:] = J[0,::-1] + Ry[0,0] = J[0,0] + Ry[0,1] = -J[0,1] + + return Rx, Ry def calculate_metric_elements(self): """ @@ -180,6 +191,10 @@ def calculate_metric_elements(self): # hx[:, :] = h(1, self) / self.dy # hy[:, :] = h(2, self) / self.dx + print('dA = ', sym_dA) + print('hx = ', sym_hx) + print('hy = ', sym_hy) + return kappa, hx, hy def calculate_rotation_matrices(self): @@ -191,45 +206,47 @@ def calculate_rotation_matrices(self): """ # if isinstance(self.map, sympy.Matrix): - sym_R = self.sym_rotation_matrix() - R = sympy.lambdify((x, y), sym_R) + sym_Rx, sym_Ry = self.sym_rotation_matrix() + print('Rx = ', sym_Rx) + print('Ry = ', sym_Ry) + + # R = sympy.lambdify((x, y), sym_R, modules="sympy") + + # print(sympy.limit(sym_R, x, 0)) def R_fcx(nvar, ixmom, iymom): R_fc = self.scratch_array(nvar=(nvar, nvar)) R_mat = np.eye(nvar) + xs = self.x2d - 0.5 * self.dx + ys = self.y2d + for i in range(self.qx): for j in range(self.qy): R_fc[i, j, :, :] = R_mat R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + - 1] = R(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) + 1] = np.array(sym_Rx.subs({x: xs[i, j], y: ys[i, j]})) return R_fc - # print(R_fcx(4, 2, 3)) - def R_fcy(nvar, ixmom, iymom): R_fc = self.scratch_array(nvar=(nvar, nvar)) R_mat = np.eye(nvar) + xs = self.x2d + ys = self.y2d - 0.5 * self.dy + for i in range(self.qx): for j in range(self.qy): R_fc[i, j, :, :] = R_mat R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + - 1] = R(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) + 1] = np.array(sym_Ry.subs({x: xs[i, j], y: ys[i, j]})) return R_fc - # print(R_fcy(4, 2, 3)) - # else: - # R_fcx = partial(R, 1, self) - # R_fcy = partial(R, 2, self) - - # print(R_fcx(4, 2, 3)) - return R_fcx, R_fcy def scratch_array(self, nvar=1): @@ -256,6 +273,18 @@ def flatten(t): flatten(nvar), dtype=np.float64) return ai.ArrayIndexer(d=_tmp, grid=self) + def physical_coords(self, xs=None, ys=None): + + if xs is None: + xs = self.x2d + if ys is None: + ys = self.y2d + + xs_t = sympy.lambdify((x, y), self.map[0]) + ys_t = sympy.lambdify((x, y), self.map[1]) + + return xs_t(xs, ys), ys_t(xs, ys) + class MappedCellCenterData2d(CellCenterData2d): @@ -276,6 +305,8 @@ def make_rotation_matrices(self, ivars): self.R_fcx = self.grid.R_fcx(ivars.nvar, ivars.ixmom, ivars.iymom) self.R_fcy = self.grid.R_fcy(ivars.nvar, ivars.ixmom, ivars.iymom) + # print('Rx contains nan?', np.isnan(self.R_fcx).any()) + def mapped_cell_center_data_clone(old): """ From 6baf2df155d6b7bff54cdd6bb4b6c3475226c157 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Thu, 28 Feb 2019 13:40:55 -0500 Subject: [PATCH 13/21] finally got it working on non-square grids --- .../problems/acoustic_pulse.py | 5 +- compressible_mapped/simulation.py | 8 +-- mesh/mapped.py | 49 ++++++++++++------- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 4ce796bf5..69f8dc03a 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -65,11 +65,10 @@ def init_data(myd, rp): def sym_map(myg): - return sympy.Matrix([x+3 + y, -2*y]) + return sympy.Matrix([2*y-x, 2*y+x]) -def inverse_map(myg): + # return sympy.Matrix([sympy.sqrt(x**2+y**2), sympy.atan(y/x)]) - return sympy.Matrix([]) def finalize(): diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 77323236c..1d14f62d6 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -140,11 +140,11 @@ def substep(self, myd): flux_xp, flux_xm, flux_yp, flux_ym = flx.fluxes(myd, self.rp, self.ivars, self.solid, self.tc) - + b=3 for n in range(self.ivars.nvar): - k.v(n=n)[:, :] = \ - (flux_xp.v(n=n) + flux_xm.ip(1, n=n)) / (myg.dx * myg.kappa.v()) + \ - (flux_yp.v(n=n) + flux_ym.jp(1, n=n)) / (myg.dy * myg.kappa.v()) + k.v(n=n,buf=b)[:, :] = \ + (flux_xp.v(n=n,buf=b) + flux_xm.ip(1, n=n,buf=b)) / (myg.dx * myg.kappa.v(buf=b)) + \ + (flux_yp.v(n=n,buf=b) + flux_ym.jp(1, n=n,buf=b)) / (myg.dy * myg.kappa.v(buf=b)) return -k diff --git a/mesh/mapped.py b/mesh/mapped.py index 58c902886..3d3841f46 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -111,9 +111,6 @@ def sym_area_element(self): https://mzucker.github.io/2018/04/12/sympy-part-3-moar-derivatives.html """ - def norm(z): - return sympy.sqrt(z.dot(z)) - p1 = sympy.simplify(self.map.diff(x)) p2 = sympy.simplify(self.map.diff(y)) @@ -129,9 +126,9 @@ def sym_line_elements(self): """ l1 = sympy.simplify(sympy.sqrt( - self.map[1].diff(x)**2 + self.map[1].diff(y)**2)) + self.map[0].diff(y)**2 + self.map[1].diff(y)**2)) l2 = sympy.simplify(sympy.sqrt( - self.map[0].diff(x)**2 + self.map[0].diff(y)**2)) + self.map[0].diff(x)**2 + self.map[1].diff(x)**2)) return l1, l2 @@ -140,24 +137,40 @@ def sym_rotation_matrix(self): Use sympy to calculate the rotation matrices """ - J = sympy.Matrix(self.map[:-1]).jacobian((x, y)) - - # normalize - J[0,:] /= J[0,:].norm() - J[1,:] /= J[1,:].norm() - Rx = sympy.zeros(2) Ry = sympy.zeros(2) + # + # Rx[0,0] = sympy.simplify(self.map[1].diff(y)) + # Rx[0,1] = sympy.simplify(self.map[1].diff(x)) + # Rx[1,0] = -sympy.simplify(self.map[1].diff(x)) + # Rx[1,1] = sympy.simplify(self.map[1].diff(y)) + # + # Ry[0,0] = sympy.simplify(self.map[0].diff(x)) + # Ry[0,1] = -sympy.simplify(self.map[0].diff(y)) + # Ry[1,0] = sympy.simplify(self.map[0].diff(y)) + # Ry[1,1] = sympy.simplify(self.map[0].diff(x)) + + Rx[0,0] = sympy.simplify(self.map[1].diff(y)) + Rx[0,1] = sympy.simplify(self.map[0].diff(y)) + Rx[1,0] = -sympy.simplify(self.map[0].diff(y)) + Rx[1,1] = sympy.simplify(self.map[1].diff(y)) + + Ry[0,0] = sympy.simplify(self.map[0].diff(x)) + Ry[0,1] = -sympy.simplify(self.map[1].diff(x)) + Ry[1,0] = sympy.simplify(self.map[1].diff(x)) + Ry[1,1] = sympy.simplify(self.map[0].diff(x)) - Rx[1,:] = J[1,:] - Rx[0,0] = J[1,1] - Rx[0,1] = -J[1,0] + # normalize + Rx[0,:] /= self.norm(Rx[0,:]) + Rx[1,:] /= self.norm(Rx[1,:]) + Ry[0,:] /= self.norm(Ry[0,:]) + Ry[1,:] /= self.norm(Ry[1,:]) - Ry[1,:] = J[0,::-1] - Ry[0,0] = J[0,0] - Ry[0,1] = -J[0,1] + # check rotation matrices + assert Rx @ Rx.T == sympy.eye(2) + assert Ry @ Ry.T == sympy.eye(2) - return Rx, Ry + return sympy.simplify(Rx), sympy.simplify(Ry) def calculate_metric_elements(self): """ From 28e00aeb3628735dcb8a11e8d35b947a45c5339d Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Thu, 28 Feb 2019 13:56:17 -0500 Subject: [PATCH 14/21] fixed rotation matrix so works on non-rectilinear grids as well --- compressible_mapped/problems/acoustic_pulse.py | 2 +- mesh/mapped.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 69f8dc03a..05a7dac02 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -65,7 +65,7 @@ def init_data(myd, rp): def sym_map(myg): - return sympy.Matrix([2*y-x, 2*y+x]) + return sympy.Matrix([2*y, y+2*x]) # return sympy.Matrix([sympy.sqrt(x**2+y**2), sympy.atan(y/x)]) diff --git a/mesh/mapped.py b/mesh/mapped.py index 3d3841f46..8f02ec5d3 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -156,8 +156,8 @@ def sym_rotation_matrix(self): Rx[1,1] = sympy.simplify(self.map[1].diff(y)) Ry[0,0] = sympy.simplify(self.map[0].diff(x)) - Ry[0,1] = -sympy.simplify(self.map[1].diff(x)) - Ry[1,0] = sympy.simplify(self.map[1].diff(x)) + Ry[0,1] = sympy.simplify(self.map[1].diff(x)) + Ry[1,0] = -sympy.simplify(self.map[1].diff(x)) Ry[1,1] = sympy.simplify(self.map[0].diff(x)) # normalize From 8054e6a59be0d030a1294aa8a4f7e1025caa6f47 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Thu, 28 Feb 2019 17:10:52 -0500 Subject: [PATCH 15/21] fixed tests --- .../problems/acoustic_pulse.py | 5 +- .../problems/inputs.acoustic_pulse.64 | 8 +-- compressible_mapped/simulation.py | 9 +-- mesh/mapped.py | 55 +++++++++---------- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 05a7dac02..37e534d62 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -65,10 +65,9 @@ def init_data(myd, rp): def sym_map(myg): - return sympy.Matrix([2*y, y+2*x]) - - # return sympy.Matrix([sympy.sqrt(x**2+y**2), sympy.atan(y/x)]) + # return sympy.Matrix([y, -2*x-y]) + return sympy.Matrix([x * sympy.cos(y), x * sympy.sin(y)]) def finalize(): diff --git a/compressible_mapped/problems/inputs.acoustic_pulse.64 b/compressible_mapped/problems/inputs.acoustic_pulse.64 index f2ca50e65..23bbcca37 100644 --- a/compressible_mapped/problems/inputs.acoustic_pulse.64 +++ b/compressible_mapped/problems/inputs.acoustic_pulse.64 @@ -22,11 +22,11 @@ ny = 64 xmax = 1.0 ymax = 1.0 -xlboundary = periodic -xrboundary = periodic +xlboundary = outflow +xrboundary = outflow -ylboundary = periodic -yrboundary = periodic +ylboundary = outflow +yrboundary = outflow [acoustic_pulse] diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 1d14f62d6..c0246fa17 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -140,11 +140,12 @@ def substep(self, myd): flux_xp, flux_xm, flux_yp, flux_ym = flx.fluxes(myd, self.rp, self.ivars, self.solid, self.tc) - b=3 + b = 3 for n in range(self.ivars.nvar): - k.v(n=n,buf=b)[:, :] = \ - (flux_xp.v(n=n,buf=b) + flux_xm.ip(1, n=n,buf=b)) / (myg.dx * myg.kappa.v(buf=b)) + \ - (flux_yp.v(n=n,buf=b) + flux_ym.jp(1, n=n,buf=b)) / (myg.dy * myg.kappa.v(buf=b)) + k.v(n=n, buf=b)[:, :] = \ + (flux_xp.v(n=n, buf=b) + flux_xm.ip(1, n=n, buf=b)) / (myg.dx * myg.kappa.v(buf=b)) + \ + (flux_yp.v(n=n, buf=b) + flux_ym.jp(1, n=n, buf=b)) / \ + (myg.dy * myg.kappa.v(buf=b)) return -k diff --git a/mesh/mapped.py b/mesh/mapped.py index 8f02ec5d3..c505311b8 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -35,6 +35,9 @@ import numpy as np import sympy from sympy.abc import x, y, z +from random import random +from numpy.testing import assert_array_almost_equal + from util import msg import mesh.array_indexer as ai from mesh.patch import Grid2d, CellCenterData2d @@ -139,36 +142,32 @@ def sym_rotation_matrix(self): Rx = sympy.zeros(2) Ry = sympy.zeros(2) - # - # Rx[0,0] = sympy.simplify(self.map[1].diff(y)) - # Rx[0,1] = sympy.simplify(self.map[1].diff(x)) - # Rx[1,0] = -sympy.simplify(self.map[1].diff(x)) - # Rx[1,1] = sympy.simplify(self.map[1].diff(y)) - # - # Ry[0,0] = sympy.simplify(self.map[0].diff(x)) - # Ry[0,1] = -sympy.simplify(self.map[0].diff(y)) - # Ry[1,0] = sympy.simplify(self.map[0].diff(y)) - # Ry[1,1] = sympy.simplify(self.map[0].diff(x)) - - Rx[0,0] = sympy.simplify(self.map[1].diff(y)) - Rx[0,1] = sympy.simplify(self.map[0].diff(y)) - Rx[1,0] = -sympy.simplify(self.map[0].diff(y)) - Rx[1,1] = sympy.simplify(self.map[1].diff(y)) - - Ry[0,0] = sympy.simplify(self.map[0].diff(x)) - Ry[0,1] = sympy.simplify(self.map[1].diff(x)) - Ry[1,0] = -sympy.simplify(self.map[1].diff(x)) - Ry[1,1] = sympy.simplify(self.map[0].diff(x)) + + Rx[0, 0] = sympy.simplify(self.map[1].diff(y)) + Rx[0, 1] = sympy.simplify(self.map[0].diff(y)) + Rx[1, 0] = -sympy.simplify(self.map[0].diff(y)) + Rx[1, 1] = sympy.simplify(self.map[1].diff(y)) + + Ry[0, 0] = sympy.simplify(self.map[0].diff(x)) + Ry[0, 1] = sympy.simplify(self.map[1].diff(x)) + Ry[1, 0] = -sympy.simplify(self.map[1].diff(x)) + Ry[1, 1] = sympy.simplify(self.map[0].diff(x)) # normalize - Rx[0,:] /= self.norm(Rx[0,:]) - Rx[1,:] /= self.norm(Rx[1,:]) - Ry[0,:] /= self.norm(Ry[0,:]) - Ry[1,:] /= self.norm(Ry[1,:]) - - # check rotation matrices - assert Rx @ Rx.T == sympy.eye(2) - assert Ry @ Ry.T == sympy.eye(2) + Rx[0, :] /= self.norm(Rx[0, :]) + Rx[1, :] /= self.norm(Rx[1, :]) + Ry[0, :] /= self.norm(Ry[0, :]) + Ry[1, :] /= self.norm(Ry[1, :]) + + Rx = sympy.simplify(Rx) + Ry = sympy.simplify(Ry) + + # check rotation matrices - do this by substituting in random (non-zero) + # numbers as sympy is not great at cancelling things + assert_array_almost_equal((Rx @ Rx.T).subs( + {x: random() + 0.01, y: random() + 0.01}), np.eye(2)) + assert_array_almost_equal((Ry @ Ry.T).subs( + {x: random() + 0.01, y: random() + 0.01}), np.eye(2)) return sympy.simplify(Rx), sympy.simplify(Ry) From 632c3b73ddc5849c5b09115b9ff09d6543546c4e Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Fri, 1 Mar 2019 11:23:17 -0500 Subject: [PATCH 16/21] switch to computing line and area elements numerically to deal with nonlinear grids --- .../problems/acoustic_pulse.py | 4 +- mesh/mapped.py | 87 +++++++++++++------ 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 37e534d62..a68819bd9 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -65,9 +65,9 @@ def init_data(myd, rp): def sym_map(myg): - # return sympy.Matrix([y, -2*x-y]) + return sympy.Matrix([y**2, -2*x-y]) - return sympy.Matrix([x * sympy.cos(y), x * sympy.sin(y)]) + # return sympy.Matrix([x * sympy.cos(y), x * sympy.sin(y)]) def finalize(): diff --git a/mesh/mapped.py b/mesh/mapped.py index c505311b8..bd46cecf3 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -123,17 +123,17 @@ def sym_area_element(self): return dA - def sym_line_elements(self): - """ - Use sympy to calculate the line elements - """ - - l1 = sympy.simplify(sympy.sqrt( - self.map[0].diff(y)**2 + self.map[1].diff(y)**2)) - l2 = sympy.simplify(sympy.sqrt( - self.map[0].diff(x)**2 + self.map[1].diff(x)**2)) - - return l1, l2 + # def sym_line_elements(self): + # """ + # Use sympy to calculate the line elements + # """ + # + # l1 = sympy.simplify(sympy.sqrt( + # self.map[0].diff(y)**2 + self.map[1].diff(y)**2)) + # l2 = sympy.simplify(sympy.sqrt( + # self.map[0].diff(x)**2 + self.map[1].diff(x)**2)) + # + # return l1, l2 def sym_rotation_matrix(self): """ @@ -183,31 +183,66 @@ def calculate_metric_elements(self): # if isinstance(self.map, sympy.Matrix): # calculate sympy formula on grid - sym_dA = self.sym_area_element() - - _dA = sympy.lambdify((x, y), sym_dA, modules="sympy") - - sym_hx, sym_hy = self.sym_line_elements() - - _hx = sympy.lambdify((x, y), sym_hx, modules="sympy") - _hy = sympy.lambdify((x, y), sym_hy, modules="sympy") + # sym_dA = self.sym_area_element() + # + # _dA = sympy.lambdify((x, y), sym_dA, modules="sympy") + + # sym_hx, sym_hy = self.sym_line_elements() + # + # _hx = sympy.lambdify((x, y), sym_hx, modules="sympy") + # _hy = sympy.lambdify((x, y), sym_hy, modules="sympy") + + def mapped_distance(v1, v2): + m1 = self.physical_coords(v1[0], v1[1]) + m2 = self.physical_coords(v2[0], v2[1]) + return np.sqrt((m1[0] - m2[0])**2 + (m1[1] - m2[1])**2) + + def mapped_area(i, j): + # c1-4 are the corners + c1 = np.array([self.x2d[i, j] - 0.5 * self.dx, + self.y2d[i, j] - 0.5 * self.dy]) + c2 = np.array([self.x2d[i, j] - 0.5 * self.dx, + self.y2d[i, j] + 0.5 * self.dy]) + c3 = np.array([self.x2d[i, j] + 0.5 * self.dx, + self.y2d[i, j] + 0.5 * self.dy]) + c4 = np.array([self.x2d[i, j] + 0.5 * self.dx, + self.y2d[i, j] - 0.5 * self.dy]) + + m1 = self.physical_coords(c1[0], c1[1]) + m2 = self.physical_coords(c2[0], c2[1]) + m3 = self.physical_coords(c3[0], c3[1]) + m4 = self.physical_coords(c4[0], c4[1]) + + # find vectors of diagonals (and pad out z-direction with a zero) + p = np.append(c3 - c1, 0) + q = np.append(c4 - c2, 0) + + # area is half the cross product + return 0.5 * np.abs(np.cross(p, q)[-1]) for i in range(self.qx): for j in range(self.qy): - kappa[i, j] = _dA(self.x2d[i, j], self.y2d[i, j]) - hx[i, j] = _hx(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) - hy[i, j] = _hy(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) + # kappa[i, j] = _dA(self.x2d[i, j], self.y2d[i, j]) + hx[i, j] = mapped_distance([self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j] - 0.5 * self.dy], [ + self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j] + 0.5 * self.dy]) + hy[i, j] = mapped_distance([self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j] - 0.5 * self.dy], [ + self.x2d[i, j] + 0.5 * self.dx, self.y2d[i, j] - 0.5 * self.dy]) + kappa[i, j] = mapped_area(i, j) + # hx[i, j] = _hx(self.x2d[i, j] + 0.5 * self.dx, self.y2d[i, j]) - _hx(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) + # hy[i, j] = _hy(self.x2d[i, j], self.y2d[i, j] + 0.5 * self.dy) - _hy(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) # else: # kappa[:, :] = area(self) / (self.dx * self.dy) # hx[:, :] = h(1, self) / self.dy # hy[:, :] = h(2, self) / self.dx - print('dA = ', sym_dA) - print('hx = ', sym_hx) - print('hy = ', sym_hy) + # print('dA = ', sym_dA) + # print('hx = ', sym_hx) + # print('hy = ', sym_hy) + + print(hx[2, 2], self.dy * self.x2d[2, 2]) - return kappa, hx, hy + return kappa / (self.dx * self.dy), hx / self.dy, hy / self.dx def calculate_rotation_matrices(self): """ From 6e05c17f5bb5d30262f888e4a6c76776f5a8ad51 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Fri, 1 Mar 2019 14:58:16 -0500 Subject: [PATCH 17/21] reflect-odd boundary conditions for mapped grids must be rotated --- .../problems/acoustic_pulse.py | 4 +- compressible_mapped/simulation.py | 58 +++++++- mesh/mapped.py | 127 +++++++++++++++--- 3 files changed, 167 insertions(+), 22 deletions(-) diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index a68819bd9..aa09ec335 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -5,7 +5,7 @@ import numpy as np from util import msg import sympy -from sympy.abc import x, y, p, q +from sympy.abc import x, y def init_data(myd, rp): @@ -65,7 +65,7 @@ def init_data(myd, rp): def sym_map(myg): - return sympy.Matrix([y**2, -2*x-y]) + return sympy.Matrix([y**2, -2*x**2-y]) # return sympy.Matrix([x * sympy.cos(y), x * sympy.sin(y)]) diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index c0246fa17..27cbee4dd 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -51,6 +51,56 @@ def mapped_grid_setup(rp, map, ng=1): ymin=ymin, ymax=ymax, ng=ng) return my_grid +def mapped_bc_setup(rp): + + bnd.define_bc("mapped_periodic", BC.user, is_solid=False) + bnd.define_bc("mapped_outflow", BC.user, is_solid=False) + bnd.define_bc("mapped_neumann", BC.user, is_solid=False) + bnd.define_bc("mapped_reflect", BC.user, is_solid=True) + bnd.define_bc("mapped_reflect-even", BC.user, is_solid=True) + bnd.define_bc("mapped_reflect-odd", BC.user, is_solid=True) + bnd.define_bc("mapped_dirichlet", BC.user, is_solid=True) + + # first figure out the BCs + try: + xlb_type = "mapped_" + rp.get_param("mesh.xlboundary") + except KeyError: + xlb_type = "mapped_periodic" + msg.warning("mesh.xlboundary is not set, defaulting to mapped_periodic") + + try: + xrb_type = "mapped_" + rp.get_param("mesh.xrboundary") + except KeyError: + xrb_type = "mapped_periodic" + msg.warning("mesh.xrboundary is not set, defaulting to mapped_periodic") + + try: + ylb_type = "mapped_" + rp.get_param("mesh.ylboundary") + except KeyError: + ylb_type = "mapped_periodic" + msg.warning("mesh.ylboundary is not set, defaulting to mapped_periodic") + + try: + yrb_type = "mapped_" + rp.get_param("mesh.yrboundary") + except KeyError: + yrb_type = "mapped_periodic" + msg.warning("mesh.yrboundary is not set, defaulting to mapped_periodic") + + bc = bnd.BC(xlb=xlb_type, xrb=xrb_type, + ylb=ylb_type, yrb=yrb_type) + + # if we are reflecting, we need odd reflection in the normal + # directions for the velocity + bc_xodd = bnd.BC(xlb=xlb_type, xrb=xrb_type, + ylb=ylb_type, yrb=yrb_type, + odd_reflect_dir="x") + + bc_yodd = bnd.BC(xlb=xlb_type, xrb=xrb_type, + ylb=ylb_type, yrb=yrb_type, + odd_reflect_dir="y") + + return bc, bc_xodd, bc_yodd + class Simulation(compressible_rk.Simulation): """The main simulation class for the method of lines compressible @@ -72,10 +122,10 @@ def initialize(self, extra_vars=None, ng=4): my_grid = mapped_grid_setup(self.rp, problem.sym_map, ng=ng) my_data = self.data_class(my_grid) - # define solver specific boundary condition routines - bnd.define_bc("hse", BC.user, is_solid=False) - # for double mach reflection problem - bnd.define_bc("ramp", BC.user, is_solid=False) + # # define solver specific boundary condition routines + # bnd.define_bc("hse", BC.user, is_solid=False) + # # for double mach reflection problem + # bnd.define_bc("ramp", BC.user, is_solid=False) bc, bc_xodd, bc_yodd = bc_setup(self.rp) diff --git a/mesh/mapped.py b/mesh/mapped.py index bd46cecf3..d5bfdcb9c 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -39,6 +39,7 @@ from numpy.testing import assert_array_almost_equal from util import msg +import mesh.boundary as bnd import mesh.array_indexer as ai from mesh.patch import Grid2d, CellCenterData2d @@ -199,14 +200,10 @@ def mapped_distance(v1, v2): def mapped_area(i, j): # c1-4 are the corners - c1 = np.array([self.x2d[i, j] - 0.5 * self.dx, - self.y2d[i, j] - 0.5 * self.dy]) - c2 = np.array([self.x2d[i, j] - 0.5 * self.dx, - self.y2d[i, j] + 0.5 * self.dy]) - c3 = np.array([self.x2d[i, j] + 0.5 * self.dx, - self.y2d[i, j] + 0.5 * self.dy]) - c4 = np.array([self.x2d[i, j] + 0.5 * self.dx, - self.y2d[i, j] - 0.5 * self.dy]) + c1 = [self.xl[i], self.yl[j]] + c2 = [self.xl[i], self.yr[j]] + c3 = [self.xr[i], self.yr[j]] + c4 = [self.xr[i], self.yl[j]] m1 = self.physical_coords(c1[0], c1[1]) m2 = self.physical_coords(c2[0], c2[1]) @@ -214,8 +211,8 @@ def mapped_area(i, j): m4 = self.physical_coords(c4[0], c4[1]) # find vectors of diagonals (and pad out z-direction with a zero) - p = np.append(c3 - c1, 0) - q = np.append(c4 - c2, 0) + p = np.append(m3 - m1, 0) + q = np.append(m4 - m2, 0) # area is half the cross product return 0.5 * np.abs(np.cross(p, q)[-1]) @@ -223,10 +220,10 @@ def mapped_area(i, j): for i in range(self.qx): for j in range(self.qy): # kappa[i, j] = _dA(self.x2d[i, j], self.y2d[i, j]) - hx[i, j] = mapped_distance([self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j] - 0.5 * self.dy], [ - self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j] + 0.5 * self.dy]) - hy[i, j] = mapped_distance([self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j] - 0.5 * self.dy], [ - self.x2d[i, j] + 0.5 * self.dx, self.y2d[i, j] - 0.5 * self.dy]) + hx[i, j] = mapped_distance([self.xl[i], self.yl[j]], + [self.xl[i], self.yr[j]]) + hy[i, j] = mapped_distance([self.xl[i], self.yl[j]], + [self.xr[i], self.yl[j]]) kappa[i, j] = mapped_area(i, j) # hx[i, j] = _hx(self.x2d[i, j] + 0.5 * self.dx, self.y2d[i, j]) - _hx(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) # hy[i, j] = _hy(self.x2d[i, j], self.y2d[i, j] + 0.5 * self.dy) - _hy(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) @@ -240,7 +237,7 @@ def mapped_area(i, j): # print('hx = ', sym_hx) # print('hy = ', sym_hy) - print(hx[2, 2], self.dy * self.x2d[2, 2]) + # print(hx[2, 2], self.dy * self.x2d[2, 2]) return kappa / (self.dx * self.dy), hx / self.dy, hy / self.dx @@ -330,7 +327,7 @@ def physical_coords(self, xs=None, ys=None): xs_t = sympy.lambdify((x, y), self.map[0]) ys_t = sympy.lambdify((x, y), self.map[1]) - return xs_t(xs, ys), ys_t(xs, ys) + return np.array([xs_t(xs, ys), ys_t(xs, ys)]) class MappedCellCenterData2d(CellCenterData2d): @@ -354,6 +351,104 @@ def make_rotation_matrices(self, ivars): # print('Rx contains nan?', np.isnan(self.R_fcx).any()) + def fill_BC(self, name): + n = self.names.index(name) + self.fill_mapped_ghost(name, n=n, bc=self.BCs[name]) + + # that will handle the standard type of BCs, but if we asked + # for a custom BC, we handle it here + if self.BCs[name].xlb in bnd.ext_bcs.keys(): + bnd.ext_bcs[self.BCs[name].xlb](self.BCs[name].xlb, "xlb", name, self) + if self.BCs[name].xrb in bnd.ext_bcs.keys(): + bnd.ext_bcs[self.BCs[name].xrb](self.BCs[name].xrb, "xrb", name, self) + if self.BCs[name].ylb in bnd.ext_bcs.keys(): + bnd.ext_bcs[self.BCs[name].ylb](self.BCs[name].ylb, "ylb", name, self) + if self.BCs[name].yrb in bnd.ext_bcs.keys(): + bnd.ext_bcs[self.BCs[name].yrb](self.BCs[name].yrb, "yrb", name, self) + + def fill_mapped_ghost(self, name, n=0, bc=None): + """ + This replaces the fill_ghost routine in array_indexer to add some + scaling factors for mapped grids. + + We'll call fill_ghost then go back and fix the reflect-odd boundaries. + + It would be great if we could pass the variables object in here as we + actually only need to do this rotation if n == ixmom or iymom. + """ + myd = self.data + + myd.fill_ghost(n=n, bc=bc) + + if name == 'x-momentum' or name == 'y-momentum': + + # -x boundary + if bc.xlb in ["reflect-odd", "dirichlet"]: + if bc.xl_value is None: + for i in range(myd.g.ilo): + for j in range(myd.g.qy): + q_rot = self.R_fcy[myd.g.ilo, j] @ myd[2*myd.g.ng-i-1, j, :] + q_rot[n] = -q_rot[n] + myd[i, j, n] = (self.R_fcy[myd.g.ilo, j].T @ q_rot)[n] + else: + for j in range(myd.g.qy): + q_rot = self.R_fcy[myd.g.ilo, j] @ myd[myd.g.ilo, j, :] + q_rot[n] = 2*bc.xl_value - q_rot[n] + myd[myd.g.ilo-1, j, n] = (self.R_fcy[myd.g.ilo, j].T @ q_rot)[n] + + # +x boundary + if bc.xrb in ["reflect-odd", "dirichlet"]: + if bc.xr_value is None: + for i in range(myd.g.ng): + for j in range(myd.g.qy): + i_bnd = myd.g.ihi+1+i + i_src = myd.g.ihi-i + + q_rot = self.R_fcy[myd.g.ihi+1, j] @ myd[i_src, j, :] + q_rot[n] = -q_rot[n] + + myd[i_bnd, j, n] = (self.R_fcy[myd.g.ihi+1, j].T @ q_rot)[n] + else: + for j in range(myd.g.qy): + q_rot = self.R_fcy[myd.g.ihi+1, j] @ myd[myd.g.ihi, j, :] + q_rot[n] = 2*bc.xr_value - q_rot[n] + + myd[myd.g.ihi+1, j, n] = (self.R_fcy[myd.g.ihi+1, j].T @ q_rot)[n] + + # -y boundary + if bc.ylb in ["reflect-odd", "dirichlet"]: + if bc.yl_value is None: + for i in range(myd.g.qx): + for j in range(myd.g.jlo): + q_rot = self.R_fcx[i, myd.g.jlo] @ myd[i, 2*myd.g.ng-j-1, :] + q_rot[n] = -q_rot[n] + myd[i, j, n] = (self.R_fcx[i, myd.g.jlo].T @ q_rot)[n] + else: + for i in range(myd.g.qx): + q_rot = self.R_fcx[i, myd.g.jlo] @ myd[i, myd.g.jlo, :] + q_rot[n] = 2*bc.yl_value - q_rot[n] + myd[i, myd.g.jlo-1, n] = (self.R_fcx[i, myd.g.jlo].T @ q_rot)[n] + + # +y boundary + if bc.yrb in ["reflect-odd", "dirichlet"]: + if bc.yr_value is None: + for i in range(myd.g.qx): + for j in range(myd.g.ng): + j_bnd = myd.g.jhi+1+j + j_src = myd.g.jhi-j + + q_rot = self.R_fcx[i, myd.g.jhi+1] @ myd[i, j_src, n] + q_rot[n] = -q_rot[n] + + myd[i, j_bnd, n] = (self.R_fcx[i, myd.g.jhi+1].T @ q_rot)[n] + else: + for i in range(myd.g.qx): + + q_rot = self.R_fcx[i, myd.g.jhi+1] @ myd[i, myd.g.jhi, n] + q_rot[n] = 2*bc.yr_value - q_rot[n] + + myd[:, myd.g.jhi+1, n] = (self.R_fcx[i, myd.g.jhi+1].T @ q_rot)[n] + def mapped_cell_center_data_clone(old): """ From 7fb135c5d9fc288a0e36d3b95ed4080792efbd04 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Wed, 6 Mar 2019 16:56:36 -0500 Subject: [PATCH 18/21] moved some function calls outside of loops to speed up problem initialisation --- .../tests/test_compressible_mapped.py | 58 +++++++++ mesh/mapped.py | 123 +++++------------- 2 files changed, 93 insertions(+), 88 deletions(-) create mode 100644 compressible_mapped/tests/test_compressible_mapped.py diff --git a/compressible_mapped/tests/test_compressible_mapped.py b/compressible_mapped/tests/test_compressible_mapped.py new file mode 100644 index 000000000..f7ab975a9 --- /dev/null +++ b/compressible_mapped/tests/test_compressible_mapped.py @@ -0,0 +1,58 @@ +import numpy as np +from numpy.testing import assert_array_equal + +from util import runparams +import compressible_mapped.simulation as sn +import pytest + + +class TestSimulation(object): + @classmethod + def setup_class(cls): + """ this is run once for each class before any tests """ + pass + + @classmethod + def teardown_class(cls): + """ this is run once for each class after all tests """ + pass + + def setup_method(self): + """ this is run before each test """ + self.rp = runparams.RuntimeParameters() + + self.rp.params["mesh.nx"] = 8 + self.rp.params["mesh.ny"] = 8 + self.rp.params["particles.do_particles"] = 0 + + self.rp.params["eos.gamma"] = 1.4 + + self.sim = sn.Simulation("compressible_mapped", "test", self.rp) + self.sim.initialize() + + def teardown_method(self): + """ this is run after each test """ + self.rp = None + self.sim = None + + def test_initializationst(self): + dens = self.sim.cc_data.get_var("density") + assert dens.min() == 1.0 and dens.max() == 1.0 + + ener = self.sim.cc_data.get_var("energy") + assert ener.min() == 2.5 and ener.max() == 2.5 + + # test the mapped grids stuff has been initialized properly + + def test_prim(self): + + # U -> q + gamma = self.sim.cc_data.get_aux("gamma") + q = sn.cons_to_prim(self.sim.cc_data.data, gamma, self.sim.ivars, self.sim.cc_data.grid) + + assert q[:, :, self.sim.ivars.ip].min() == pytest.approx(1.0) and \ + q[:, :, self.sim.ivars.ip].max() == pytest.approx(1.0) + + # q -> U + U = sn.prim_to_cons(q, gamma, self.sim.ivars, self.sim.cc_data.grid) + assert_array_equal(U, self.sim.cc_data.data) diff --git a/mesh/mapped.py b/mesh/mapped.py index d5bfdcb9c..2a414613f 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -37,6 +37,7 @@ from sympy.abc import x, y, z from random import random from numpy.testing import assert_array_almost_equal +from numba import njit from util import msg import mesh.boundary as bnd @@ -101,41 +102,16 @@ def __init__(self, map_func, nx, ny, ng=1, # of the basis vectors self.map = map_func(self).col_join(sympy.Matrix([z])) + print("Calculating scaling factors...") self.kappa, self.gamma_fcx, self.gamma_fcy = self.calculate_metric_elements() + print("Calculating rotation matrices...") self.R_fcx, self.R_fcy = self.calculate_rotation_matrices() @staticmethod def norm(z): return sympy.sqrt(z.dot(z)) - def sym_area_element(self): - """ - Use sympy to calculate area element using - https://mzucker.github.io/2018/04/12/sympy-part-3-moar-derivatives.html - """ - - p1 = sympy.simplify(self.map.diff(x)) - p2 = sympy.simplify(self.map.diff(y)) - - p1_cross_p2 = sympy.simplify(p1.cross(p2)) - - dA = sympy.simplify(self.norm(p1_cross_p2)) - - return dA - - # def sym_line_elements(self): - # """ - # Use sympy to calculate the line elements - # """ - # - # l1 = sympy.simplify(sympy.sqrt( - # self.map[0].diff(y)**2 + self.map[1].diff(y)**2)) - # l2 = sympy.simplify(sympy.sqrt( - # self.map[0].diff(x)**2 + self.map[1].diff(x)**2)) - # - # return l1, l2 - def sym_rotation_matrix(self): """ Use sympy to calculate the rotation matrices @@ -182,62 +158,28 @@ def calculate_metric_elements(self): hx = self.scratch_array() hy = self.scratch_array() - # if isinstance(self.map, sympy.Matrix): - # calculate sympy formula on grid - # sym_dA = self.sym_area_element() - # - # _dA = sympy.lambdify((x, y), sym_dA, modules="sympy") - - # sym_hx, sym_hy = self.sym_line_elements() - # - # _hx = sympy.lambdify((x, y), sym_hx, modules="sympy") - # _hy = sympy.lambdify((x, y), sym_hy, modules="sympy") - - def mapped_distance(v1, v2): - m1 = self.physical_coords(v1[0], v1[1]) - m2 = self.physical_coords(v2[0], v2[1]) - return np.sqrt((m1[0] - m2[0])**2 + (m1[1] - m2[1])**2) - - def mapped_area(i, j): - # c1-4 are the corners - c1 = [self.xl[i], self.yl[j]] - c2 = [self.xl[i], self.yr[j]] - c3 = [self.xr[i], self.yr[j]] - c4 = [self.xr[i], self.yl[j]] + # calculate physical coordinates of corners + c1 = self.physical_coords(self.xl, self.yl) + c2 = self.physical_coords(self.xl, self.yr) + c3 = self.physical_coords(self.xr, self.yr) + c4 = self.physical_coords(self.xr, self.yl) - m1 = self.physical_coords(c1[0], c1[1]) - m2 = self.physical_coords(c2[0], c2[1]) - m3 = self.physical_coords(c3[0], c3[1]) - m4 = self.physical_coords(c4[0], c4[1]) + def mapped_distance(m1, m2): + return np.sqrt((m1[0] - m2[0])**2 + (m1[1] - m2[1])**2) + def mapped_area(i,j): # find vectors of diagonals (and pad out z-direction with a zero) - p = np.append(m3 - m1, 0) - q = np.append(m4 - m2, 0) + p = np.append(c3[:,i,j] - c1[:,i,j], 0) + q = np.append(c4[:,i,j] - c2[:,i,j], 0) # area is half the cross product return 0.5 * np.abs(np.cross(p, q)[-1]) for i in range(self.qx): for j in range(self.qy): - # kappa[i, j] = _dA(self.x2d[i, j], self.y2d[i, j]) - hx[i, j] = mapped_distance([self.xl[i], self.yl[j]], - [self.xl[i], self.yr[j]]) - hy[i, j] = mapped_distance([self.xl[i], self.yl[j]], - [self.xr[i], self.yl[j]]) + hx[i, j] = mapped_distance(c1[:,i,j], c2[:,i,j]) + hy[i, j] = mapped_distance(c1[:,i,j], c4[:,i,j]) kappa[i, j] = mapped_area(i, j) - # hx[i, j] = _hx(self.x2d[i, j] + 0.5 * self.dx, self.y2d[i, j]) - _hx(self.x2d[i, j] - 0.5 * self.dx, self.y2d[i, j]) - # hy[i, j] = _hy(self.x2d[i, j], self.y2d[i, j] + 0.5 * self.dy) - _hy(self.x2d[i, j], self.y2d[i, j] - 0.5 * self.dy) - - # else: - # kappa[:, :] = area(self) / (self.dx * self.dy) - # hx[:, :] = h(1, self) / self.dy - # hy[:, :] = h(2, self) / self.dx - - # print('dA = ', sym_dA) - # print('hx = ', sym_hx) - # print('hy = ', sym_hy) - - # print(hx[2, 2], self.dy * self.x2d[2, 2]) return kappa / (self.dx * self.dy), hx / self.dy, hy / self.dx @@ -254,24 +196,20 @@ def calculate_rotation_matrices(self): print('Rx = ', sym_Rx) print('Ry = ', sym_Ry) - # R = sympy.lambdify((x, y), sym_R, modules="sympy") - - # print(sympy.limit(sym_R, x, 0)) + Rx = sympy.lambdify((x, y), sym_Rx, modules="sympy") + Ry = sympy.lambdify((x, y), sym_Ry, modules="sympy") def R_fcx(nvar, ixmom, iymom): R_fc = self.scratch_array(nvar=(nvar, nvar)) R_mat = np.eye(nvar) - xs = self.x2d - 0.5 * self.dx - ys = self.y2d - for i in range(self.qx): for j in range(self.qy): R_fc[i, j, :, :] = R_mat R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + - 1] = np.array(sym_Rx.subs({x: xs[i, j], y: ys[i, j]})) + 1] = np.array(Rx(self.xl[i], self.y[j])) return R_fc @@ -280,15 +218,12 @@ def R_fcy(nvar, ixmom, iymom): R_mat = np.eye(nvar) - xs = self.x2d - ys = self.y2d - 0.5 * self.dy - for i in range(self.qx): for j in range(self.qy): R_fc[i, j, :, :] = R_mat R_fc[i, j, ixmom:iymom + 1, ixmom:iymom + - 1] = np.array(sym_Ry.subs({x: xs[i, j], y: ys[i, j]})) + 1] = np.array(Ry(self.x[i], self.yl[j])) return R_fc return R_fcx, R_fcy @@ -317,12 +252,24 @@ def flatten(t): flatten(nvar), dtype=np.float64) return ai.ArrayIndexer(d=_tmp, grid=self) - def physical_coords(self, xs=None, ys=None): + def physical_coords(self, xx=None, yy=None): - if xs is None: + if xx is None: xs = self.x2d - if ys is None: + elif not np.isscalar(xx) and len(xx.shape) == 1: + xs = np.repeat(xx, len(yy)) + xs.shape = (len(xx), len(yy)) + else: + xs = xx + + if yy is None: ys = self.y2d + elif not np.isscalar(yy) and len(yy.shape) == 1: + ys = np.repeat(yy, len(xx)) + ys.shape = (len(yy), len(xx)) + ys = np.transpose(ys) + else: + ys = yy xs_t = sympy.lambdify((x, y), self.map[0]) ys_t = sympy.lambdify((x, y), self.map[1]) @@ -381,7 +328,7 @@ def fill_mapped_ghost(self, name, n=0, bc=None): myd.fill_ghost(n=n, bc=bc) if name == 'x-momentum' or name == 'y-momentum': - + # -x boundary if bc.xlb in ["reflect-odd", "dirichlet"]: if bc.xl_value is None: From 178ce58dae06044a3b7567bce3ca473c040f6729 Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Thu, 7 Mar 2019 12:03:23 -0500 Subject: [PATCH 19/21] updated tests --- compressible/interface.py | 5 +- compressible/problems/test.py | 2 +- compressible_mapped/_defaults | 4 - compressible_mapped/fluxes.py | 7 +- .../problems/acoustic_pulse.py | 15 +- .../problems/inputs.acoustic_pulse.64 | 1 + compressible_mapped/problems/test.py | 14 +- compressible_mapped/simulation.py | 1 - .../tests/test_compressible_mapped.py | 29 +-- mesh/mapped.py | 2 - mesh/tests/test_mapped.py | 174 ++++++++++++++++++ 11 files changed, 219 insertions(+), 35 deletions(-) create mode 100644 mesh/tests/test_mapped.py diff --git a/compressible/interface.py b/compressible/interface.py index 2b9ccfc9c..bd0bdd194 100644 --- a/compressible/interface.py +++ b/compressible/interface.py @@ -801,7 +801,7 @@ def riemann_prim(idir, ng, return q_int -@njit(cache=True) +# @njit(cache=True) def riemann_hllc(idir, ng, idens, ixmom, iymom, iener, irhoX, nspec, lower_solid, upper_solid, @@ -857,6 +857,9 @@ def riemann_hllc(idir, ng, # primitive variable states rho_l = U_l[i, j, idens] + if (rho_l <= 0): + print(f"-ve density {rho_l} at i,j = ({i},{j})") + # un = normal velocity; ut = transverse velocity if (idir == 1): un_l = U_l[i, j, ixmom] / rho_l diff --git a/compressible/problems/test.py b/compressible/problems/test.py index 2e463f6ce..f0a7b757f 100644 --- a/compressible/problems/test.py +++ b/compressible/problems/test.py @@ -9,7 +9,7 @@ def init_data(my_data, rp): # 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("ERROR: patch invalid in test.py") print(my_data.__class__) sys.exit() diff --git a/compressible_mapped/_defaults b/compressible_mapped/_defaults index be64a2995..526658669 100644 --- a/compressible_mapped/_defaults +++ b/compressible_mapped/_defaults @@ -22,7 +22,3 @@ temporal_method = RK4 ; integration method (see mesh/integration.py) grav = 0.0 ; gravitational acceleration (in y-direction) riemann = HLLC ; HLLC or CGF - -well_balanced = 0 ; use a well-balanced scheme to keep the model in hydrostatic equilibrium - - diff --git a/compressible_mapped/fluxes.py b/compressible_mapped/fluxes.py index ea9257222..d3646c73f 100644 --- a/compressible_mapped/fluxes.py +++ b/compressible_mapped/fluxes.py @@ -22,8 +22,8 @@ import numpy as np import compressible.interface as interface -# import compressible as comp -# import mesh.reconstruction as reconstruction +import compressible as comp +import mesh.reconstruction as reconstruction import mesh.array_indexer as ai from util import msg @@ -64,6 +64,7 @@ def fluxes(my_data, rp, ivars, solid, tc): myg = my_data.grid U = my_data.data + gamma = rp.get_param("eos.gamma") # ========================================================================= # transform by rotating the velocity components @@ -90,8 +91,6 @@ def fluxes(my_data, rp, ivars, solid, tc): U_yr.v(buf=b)[i, j] = (my_data.R_fcy.v(buf=b)[i, j] @ U.v(buf=b)[i, j]) - gamma = rp.get_param("eos.gamma") - # ========================================================================= # construct the fluxes normal to the interfaces # ========================================================================= diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index aa09ec335..46f699fa4 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -1,12 +1,13 @@ from __future__ import print_function # import sys -# import mesh.fv as fv import numpy as np -from util import msg import sympy from sympy.abc import x, y +from util import msg +# import mesh.fv as fv + def init_data(myd, rp): """initialize the acoustic_pulse problem. This comes from @@ -45,12 +46,12 @@ def init_data(myd, rp): myg = myd.grid - xctr = 0.5 * (xmin + xmax) - yctr = 0.5 * (ymin + ymax) - X, Y = myg.physical_coords() - xctr_t, yctr_t = myg.physical_coords(xctr, yctr) + # rather than map the center of the coordinate grid, find the center by + # locating the center of a diagonal across the physical domain + xctr_t, yctr_t = 0.5 * \ + (myg.physical_coords(xmin, ymin) + myg.physical_coords(xmax, ymax)) dist = np.sqrt((X - xctr_t)**2 + (Y - yctr_t)**2) @@ -65,7 +66,7 @@ def init_data(myd, rp): def sym_map(myg): - return sympy.Matrix([y**2, -2*x**2-y]) + return sympy.Matrix([y**2, -2 * x**2 - y]) # return sympy.Matrix([x * sympy.cos(y), x * sympy.sin(y)]) diff --git a/compressible_mapped/problems/inputs.acoustic_pulse.64 b/compressible_mapped/problems/inputs.acoustic_pulse.64 index 23bbcca37..295af6d17 100644 --- a/compressible_mapped/problems/inputs.acoustic_pulse.64 +++ b/compressible_mapped/problems/inputs.acoustic_pulse.64 @@ -6,6 +6,7 @@ fix_dt = 3.0e-3 [compressible] cvisc = 0.1 +limiter = 0 [io] diff --git a/compressible_mapped/problems/test.py b/compressible_mapped/problems/test.py index 016989421..6be81cbbc 100644 --- a/compressible_mapped/problems/test.py +++ b/compressible_mapped/problems/test.py @@ -1,16 +1,19 @@ from __future__ import print_function import sys -import mesh.patch as patch import numpy as np +import sympy +from sympy.abc import x, y + +import mesh.mapped as mapped 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") + if not isinstance(my_data, mapped.MappedCellCenterData2d): + print("ERROR: patch invalid in test.py") print(my_data.__class__) sys.exit() @@ -52,6 +55,11 @@ def R(iface, myg, nvar, ixmom, iymom): return R_fc +def sym_map(myg): + + return sympy.Matrix([-2*y, x+4]) + + def finalize(): """ print out any information to the user at the end of the run """ pass diff --git a/compressible_mapped/simulation.py b/compressible_mapped/simulation.py index 27cbee4dd..08e58f049 100644 --- a/compressible_mapped/simulation.py +++ b/compressible_mapped/simulation.py @@ -148,7 +148,6 @@ def initialize(self, extra_vars=None, ng=4): # self-contained object stored in output files to make plots. # store grav because we'll need that in some BCs my_data.set_aux("gamma", self.rp.get_param("eos.gamma")) - my_data.set_aux("grav", self.rp.get_param("compressible.grav")) my_data.create() diff --git a/compressible_mapped/tests/test_compressible_mapped.py b/compressible_mapped/tests/test_compressible_mapped.py index f7ab975a9..e0ef2fea8 100644 --- a/compressible_mapped/tests/test_compressible_mapped.py +++ b/compressible_mapped/tests/test_compressible_mapped.py @@ -1,9 +1,10 @@ import numpy as np from numpy.testing import assert_array_equal +import pytest +import sympy from util import runparams import compressible_mapped.simulation as sn -import pytest class TestSimulation(object): @@ -35,24 +36,28 @@ def teardown_method(self): self.rp = None self.sim = None - def test_initializationst(self): + def test_initialization_state(self): dens = self.sim.cc_data.get_var("density") assert dens.min() == 1.0 and dens.max() == 1.0 ener = self.sim.cc_data.get_var("energy") assert ener.min() == 2.5 and ener.max() == 2.5 - # test the mapped grids stuff has been initialized properly + def test_mapped_grid(self): + + myg = self.sim.cc_data.grid + + kappa = myg.scratch_array() + 2 + assert_array_equal(kappa, myg.kappa) - def test_prim(self): + gamma_fcx = np.ones_like(kappa) * 2 + assert_array_equal(gamma_fcx, myg.gamma_fcx) - # U -> q - gamma = self.sim.cc_data.get_aux("gamma") - q = sn.cons_to_prim(self.sim.cc_data.data, gamma, self.sim.ivars, self.sim.cc_data.grid) + gamma_fcy = np.ones_like(kappa) + assert_array_equal(gamma_fcy, myg.gamma_fcy) - assert q[:, :, self.sim.ivars.ip].min() == pytest.approx(1.0) and \ - q[:, :, self.sim.ivars.ip].max() == pytest.approx(1.0) + R_x = sympy.Matrix([[0, -1], [1, 0]]) + R_y = sympy.Matrix([[0, 1], [-1, 0]]) - # q -> U - U = sn.prim_to_cons(q, gamma, self.sim.ivars, self.sim.cc_data.grid) - assert_array_equal(U, self.sim.cc_data.data) + assert_array_equal(myg.R_fcx(2, 0, 1)[3, 5], R_x) + assert_array_equal(myg.R_fcy(2, 0, 1)[6, 0], R_y) diff --git a/mesh/mapped.py b/mesh/mapped.py index 2a414613f..83dbfa275 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -296,8 +296,6 @@ def make_rotation_matrices(self, ivars): self.R_fcx = self.grid.R_fcx(ivars.nvar, ivars.ixmom, ivars.iymom) self.R_fcy = self.grid.R_fcy(ivars.nvar, ivars.ixmom, ivars.iymom) - # print('Rx contains nan?', np.isnan(self.R_fcx).any()) - def fill_BC(self, name): n = self.names.index(name) self.fill_mapped_ghost(name, n=n, bc=self.BCs[name]) diff --git a/mesh/tests/test_mapped.py b/mesh/tests/test_mapped.py new file mode 100644 index 000000000..a6606a27e --- /dev/null +++ b/mesh/tests/test_mapped.py @@ -0,0 +1,174 @@ +# unit tests for mapped +import numpy as np +from numpy.testing import assert_array_equal, assert_array_almost_equal +import sympy +from sympy.abc import x, y + +import mesh.mapped as mapped + + +class TestMappedGrid2d(object): + + @classmethod + def setup_class(cls): + """ this is run once for each class before any tests """ + pass + + @classmethod + def teardown_class(cls): + """ this is run once for each class after all tests """ + pass + + def setup_method(self): + """ this is run before each test """ + pass + + def teardown_method(self): + """ this is run after each test """ + pass + + def test_rectilinear(self): + """ + Test mapped grid class for a rectilinear grid + """ + + def map(myg): + return sympy.Matrix([2 * x, 0.1 * y]) + + grid = mapped.MappedGrid2d(map, 4, 8, ng=2, ymax=2.0) + + assert grid.dx == 0.25 + assert grid.dy == 0.25 + + assert_array_almost_equal( + grid.kappa, np.ones((8, 12)) * 0.2, decimal=12) + assert_array_almost_equal( + grid.gamma_fcx, np.ones((8, 12)) * 0.1, decimal=12) + assert_array_almost_equal( + grid.gamma_fcy, np.ones((8, 12)) * 2, decimal=12) + + assert_array_almost_equal(grid.R_fcx( + 2, 0, 1)[0, 0, :, :], np.eye(2), decimal=12) + assert_array_almost_equal(grid.R_fcy( + 2, 0, 1)[-1, -1, :, :], np.eye(2), decimal=12) + + def test_noncartesian(self): + """ + Test mapped grid class for a non cartesian grid. + """ + + def map(myg): + return sympy.Matrix([0.5 * x + y, x - 0.4 * y]) + + grid = mapped.MappedGrid2d(map, 4, 4, ng=2) + + # numpy and scipy use slightly different sqrt routines so lose a little + # bit of precision - use almost equal here rather than equal + assert_array_almost_equal(grid.kappa, np.ones((8, 8)) * 1.2) + assert_array_almost_equal(grid.gamma_fcx, np.ones( + (8, 8)) * np.sqrt(0.4**2 + 1), decimal=12) + assert_array_almost_equal(grid.gamma_fcy, np.ones( + (8, 8)) * np.sqrt(0.5**2 + 1), decimal=12) + + Rx = np.array([[-0.4 / np.sqrt(0.4**2 + 1), 1 / np.sqrt(0.4**2 + 1)], + [-1 / np.sqrt(0.4**2 + 1), -0.4 / np.sqrt(0.4**2 + 1)]]) + + Ry = np.array([[0.5 / np.sqrt(0.5**2 + 1), 1 / np.sqrt(0.5**2 + 1)], + [-1 / np.sqrt(0.5**2 + 1), 0.5 / np.sqrt(0.5**2 + 1)]]) + + assert_array_almost_equal(grid.R_fcx( + 2, 0, 1)[0, 0, :, :], Rx, decimal=12) + assert_array_almost_equal(grid.R_fcy( + 2, 0, 1)[2, 4, :, :], Ry, decimal=12) + + def test_polar(self): + """ + Test mapped grid class for polar coordinates. + """ + + def map(myg): + return sympy.Matrix([x * sympy.cos(y), x * sympy.sin(y)]) + + grid = mapped.MappedGrid2d(map, 4, 4, ng=2, xmin=0.1) + + xs = grid.x2d * np.cos(grid.y2d) + ys = grid.x2d * np.sin(grid.y2d) + + x_map = sympy.lambdify((x, y), map(grid)[0])(grid.x2d, grid.y2d) + y_map = sympy.lambdify((x, y), map(grid)[1])(grid.x2d, grid.y2d) + + assert_array_almost_equal(xs, x_map, decimal=12) + assert_array_almost_equal(ys, y_map, decimal=12) + + kappa = np.array([[0.23503376, 0.23503376, 0.23503376, 0.23503376, 0.23503376, 0.23503376, 0.23503376, 0.23503376], + [0.0123702, 0.0123702, 0.0123702, 0.0123702, 0.0123702, 0.0123702, + 0.0123702, 0.0123702], + [0.21029337, 0.21029337, 0.21029337, 0.21029337, 0.21029337, 0.21029337, + 0.21029337, 0.21029337], + [0.43295693, 0.43295693, 0.43295693, 0.43295693, 0.43295693, 0.43295693, + 0.43295693, 0.43295693], + [0.65562049, 0.65562049, 0.65562049, 0.65562049, 0.65562049, 0.65562049, + 0.65562049, 0.65562049], + [0.87828406, 0.87828406, 0.87828406, 0.87828406, 0.87828406, 0.87828406, + 0.87828406, 0.87828406], + [1.10094762, 1.10094762, 1.10094762, 1.10094762, 1.10094762, 1.10094762, + 1.10094762, 1.10094762], + [1.32361118, 1.32361118, 1.32361118, 1.32361118, 1.32361118, 1.32361118, + 1.32361118, 1.32361118]]) + assert_array_almost_equal(grid.kappa, kappa) + + gamma_fcx = np.array([[0.34908925, 0.34908925, 0.34908925, 0.34908925, 0.34908925, 0.34908925, 0.34908925, 0.34908925], + [0.12467473, 0.12467473, 0.12467473, 0.12467473, + 0.12467473, 0.12467473, 0.12467473, 0.12467473], + [0.09973979, 0.09973979, 0.09973979, 0.09973979, 0.09973979, 0.09973979, + 0.09973979, 0.09973979], + [0.32415431, 0.32415431, 0.32415431, 0.32415431, 0.32415431, 0.32415431, + 0.32415431, 0.32415431], + [0.54856883, 0.54856883, 0.54856883, 0.54856883, 0.54856883, 0.54856883, + 0.54856883, 0.54856883], + [0.77298335, 0.77298335, 0.77298335, 0.77298335, 0.77298335, 0.77298335, + 0.77298335, 0.77298335], + [0.99739787, 0.99739787, 0.99739787, 0.99739787, 0.99739787, 0.99739787, + 0.99739787, 0.99739787], + [1.22181239, 1.22181239, 1.22181239, 1.22181239, 1.22181239, 1.22181239, + 1.22181239, 1.22181239]] + ) + assert_array_almost_equal(grid.gamma_fcx, gamma_fcx) + + gamma_fcy = np.ones_like(xs) + assert_array_almost_equal(grid.gamma_fcy, gamma_fcy, decimal=12) + + Rx = lambda xx, yy: np.array([[np.cos(yy), -np.sin(yy)], + [np.sin(yy), np.cos(yy)]]) + + Ry = lambda xx, yy: np.array([[np.cos(yy), np.sin(yy)], + [-np.sin(yy), np.cos(yy)]]) + + R_fcx = Rx(grid.x2d[4, 5] - 0.5 * grid.dx, grid.y2d[4, 5]) + R_fcy = Ry(grid.x2d[3, 2], grid.y2d[3, 2] - 0.5 * grid.dy) + + assert_array_almost_equal(grid.R_fcx( + 2, 0, 1)[4, 5, :, :], R_fcx, decimal=12) + assert_array_almost_equal(grid.R_fcy( + 2, 0, 1)[3, 2, :, :], R_fcy, decimal=12) + + +class TestMappedCellCenterData2d(object): + + @classmethod + def setup_class(cls): + """ this is run once for each class before any tests """ + pass + + @classmethod + def teardown_class(cls): + """ this is run once for each class after all tests """ + pass + + def setup_method(self): + """ this is run before each test """ + self.g = mapped.MappedGrid2d(4, 6, ng=2, ymax=1.5) + + def teardown_method(self): + """ this is run after each test """ + self.g = None From f73fa3599444ce2d0c192ccd1036f0e026e8191f Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Thu, 7 Mar 2019 14:30:34 -0500 Subject: [PATCH 20/21] updated docs --- .../tests/test_compressible_mapped.py | 3 ++ docs/source/compressible_mapped.problems.rst | 26 +++++++++++++ docs/source/compressible_mapped.rst | 33 +++++++++++++++++ docs/source/compressible_mapped_defaults.inc | 37 +++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 docs/source/compressible_mapped.problems.rst create mode 100644 docs/source/compressible_mapped.rst create mode 100644 docs/source/compressible_mapped_defaults.inc diff --git a/compressible_mapped/tests/test_compressible_mapped.py b/compressible_mapped/tests/test_compressible_mapped.py index e0ef2fea8..c589b2b98 100644 --- a/compressible_mapped/tests/test_compressible_mapped.py +++ b/compressible_mapped/tests/test_compressible_mapped.py @@ -37,6 +37,9 @@ def teardown_method(self): self.sim = None def test_initialization_state(self): + """ + Test state initialized properly + """ dens = self.sim.cc_data.get_var("density") assert dens.min() == 1.0 and dens.max() == 1.0 diff --git a/docs/source/compressible_mapped.problems.rst b/docs/source/compressible_mapped.problems.rst new file mode 100644 index 000000000..971b87935 --- /dev/null +++ b/docs/source/compressible_mapped.problems.rst @@ -0,0 +1,26 @@ +compressible\_mapped\.problems package +=================================== + +.. automodule:: compressible_mapped.problems + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +compressible\_mapped\.problems\.acoustic\_pulse module +--------------------------------------------------- + +.. automodule:: compressible_mapped.problems.acoustic_pulse + :members: + :undoc-members: + :show-inheritance: + +compressible\_mapped\.problems\.test module +----------------------------------- + +.. automodule:: compressible_mapped.problems.test + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/compressible_mapped.rst b/docs/source/compressible_mapped.rst new file mode 100644 index 000000000..e7deb8225 --- /dev/null +++ b/docs/source/compressible_mapped.rst @@ -0,0 +1,33 @@ +compressible\_mapped package +========================= + +.. automodule:: compressible_mapped + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + + compressible_mapped.problems + +Submodules +---------- + +compressible\_mapped\.fluxes module +-------------------------------- + +.. automodule:: compressible_mapped.fluxes + :members: + :undoc-members: + :show-inheritance: + +compressible\_mapped\.simulation module +------------------------------------ + +.. automodule:: compressible_mapped.simulation + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/compressible_mapped_defaults.inc b/docs/source/compressible_mapped_defaults.inc new file mode 100644 index 000000000..5417b0298 --- /dev/null +++ b/docs/source/compressible_mapped_defaults.inc @@ -0,0 +1,37 @@ +* section: [compressible] + + +----------------------------------+----------------+----------------------------------------------------+ + | option | value | description | + +==================================+================+====================================================+ + | use_flattening | ``1`` | apply flattening at shocks (1) | + +----------------------------------+----------------+----------------------------------------------------+ + | z0 | ``0.75`` | flattening z0 parameter | + +----------------------------------+----------------+----------------------------------------------------+ + | z1 | ``0.85`` | flattening z1 parameter | + +----------------------------------+----------------+----------------------------------------------------+ + | delta | ``0.33`` | flattening delta parameter | + +----------------------------------+----------------+----------------------------------------------------+ + | cvisc | ``0.1`` | artifical viscosity coefficient | + +----------------------------------+----------------+----------------------------------------------------+ + | limiter | ``2`` | limiter (0 = none, 1 = 2nd order, 2 = 4th order) | + +----------------------------------+----------------+----------------------------------------------------+ + | temporal_method | ``RK4`` | integration method (see mesh/integration.py) | + +----------------------------------+----------------+----------------------------------------------------+ + | riemann | ``HLLC`` | riemann solver (HLLC or CGF) | + +----------------------------------+----------------+----------------------------------------------------+ + +* section: [driver] + + +----------------------------------+----------------+----------------------------------------------------+ + | option | value | description | + +==================================+================+====================================================+ + | cfl | ``0.8`` | | + +----------------------------------+----------------+----------------------------------------------------+ + +* section: [eos] + + +----------------------------------+----------------+----------------------------------------------------+ + | option | value | description | + +==================================+================+====================================================+ + | gamma | ``1.4`` | pres = rho ener (gamma - 1) | + +----------------------------------+----------------+----------------------------------------------------+ From bf42bf4420e666a583a7b600742bf23ed915d78a Mon Sep 17 00:00:00 2001 From: Alice Harpole Date: Thu, 7 Mar 2019 15:21:39 -0500 Subject: [PATCH 21/21] updated mapped grids problems --- compressible_mapped/problems/_bubble.defaults | 11 -- compressible_mapped/problems/_hse.defaults | 4 - compressible_mapped/problems/_logo.defaults | 1 - compressible_mapped/problems/_quad.defaults | 33 ----- compressible_mapped/problems/_ramp.defaults | 19 --- compressible_mapped/problems/_rt.defaults | 10 -- compressible_mapped/problems/_rt2.defaults | 10 -- compressible_mapped/problems/_sedov.defaults | 4 - .../problems/acoustic_pulse.py | 14 +-- compressible_mapped/problems/advect.py | 48 +++---- compressible_mapped/problems/bubble.py | 109 ---------------- compressible_mapped/problems/hse.py | 85 ------------- .../problems/inputs.acoustic_pulse | 8 +- .../problems/inputs.acoustic_pulse.256 | 9 +- .../problems/inputs.acoustic_pulse.512 | 8 +- .../problems/inputs.advect.128 | 8 +- .../problems/inputs.advect.256 | 8 +- compressible_mapped/problems/inputs.advect.64 | 8 +- compressible_mapped/problems/inputs.bubble | 39 ------ compressible_mapped/problems/inputs.hse | 34 ----- compressible_mapped/problems/inputs.logo | 34 ----- compressible_mapped/problems/inputs.quad | 52 -------- compressible_mapped/problems/inputs.ramp | 40 ------ compressible_mapped/problems/inputs.rt | 33 ----- compressible_mapped/problems/inputs.rt2 | 33 ----- .../problems/inputs.rt_gravity_waves | 37 ------ compressible_mapped/problems/inputs.sedov | 38 ------ compressible_mapped/problems/kh.py | 66 +++++----- compressible_mapped/problems/logo.py | 104 --------------- compressible_mapped/problems/logo.txt | 21 ---- compressible_mapped/problems/quad.py | 119 ------------------ compressible_mapped/problems/ramp.py | 113 ----------------- compressible_mapped/problems/rt.py | 99 --------------- compressible_mapped/problems/rt2.py | 112 ----------------- compressible_mapped/problems/sedov.py | 115 ----------------- compressible_mapped/problems/sod.py | 45 +++---- compressible_mapped/problems/test.py | 26 +--- docs/source/compressible_mapped.problems.rst | 38 +++++- docs/source/mapped_basics.rst | 2 +- mesh/mapped.py | 4 +- 40 files changed, 134 insertions(+), 1467 deletions(-) delete mode 100644 compressible_mapped/problems/_bubble.defaults delete mode 100644 compressible_mapped/problems/_hse.defaults delete mode 100644 compressible_mapped/problems/_logo.defaults delete mode 100644 compressible_mapped/problems/_quad.defaults delete mode 100644 compressible_mapped/problems/_ramp.defaults delete mode 100644 compressible_mapped/problems/_rt.defaults delete mode 100644 compressible_mapped/problems/_rt2.defaults delete mode 100644 compressible_mapped/problems/_sedov.defaults delete mode 100644 compressible_mapped/problems/bubble.py delete mode 100644 compressible_mapped/problems/hse.py delete mode 100644 compressible_mapped/problems/inputs.bubble delete mode 100644 compressible_mapped/problems/inputs.hse delete mode 100644 compressible_mapped/problems/inputs.logo delete mode 100644 compressible_mapped/problems/inputs.quad delete mode 100644 compressible_mapped/problems/inputs.ramp delete mode 100644 compressible_mapped/problems/inputs.rt delete mode 100644 compressible_mapped/problems/inputs.rt2 delete mode 100644 compressible_mapped/problems/inputs.rt_gravity_waves delete mode 100644 compressible_mapped/problems/inputs.sedov delete mode 100644 compressible_mapped/problems/logo.py delete mode 100644 compressible_mapped/problems/logo.txt delete mode 100644 compressible_mapped/problems/quad.py delete mode 100644 compressible_mapped/problems/ramp.py delete mode 100644 compressible_mapped/problems/rt.py delete mode 100644 compressible_mapped/problems/rt2.py delete mode 100644 compressible_mapped/problems/sedov.py diff --git a/compressible_mapped/problems/_bubble.defaults b/compressible_mapped/problems/_bubble.defaults deleted file mode 100644 index d5d7a40ff..000000000 --- a/compressible_mapped/problems/_bubble.defaults +++ /dev/null @@ -1,11 +0,0 @@ -[bubble] -dens_base = 10.0 ; density at the base of the atmosphere -scale_height = 2.0 ; scale height of the isothermal atmosphere - -x_pert = 2.0 -y_pert = 2.0 -r_pert = 0.25 -pert_amplitude_factor = 5.0 - -dens_cutoff = 0.01 - diff --git a/compressible_mapped/problems/_hse.defaults b/compressible_mapped/problems/_hse.defaults deleted file mode 100644 index 56ef80d2b..000000000 --- a/compressible_mapped/problems/_hse.defaults +++ /dev/null @@ -1,4 +0,0 @@ -[hse] -dens0 = 1.0 -h = 1.0 - diff --git a/compressible_mapped/problems/_logo.defaults b/compressible_mapped/problems/_logo.defaults deleted file mode 100644 index 39647231c..000000000 --- a/compressible_mapped/problems/_logo.defaults +++ /dev/null @@ -1 +0,0 @@ -[logo] diff --git a/compressible_mapped/problems/_quad.defaults b/compressible_mapped/problems/_quad.defaults deleted file mode 100644 index 30918f7d1..000000000 --- a/compressible_mapped/problems/_quad.defaults +++ /dev/null @@ -1,33 +0,0 @@ -# these defaults seem to be equivalent to Configuration 3 from -# Shulz-Rinne et al. SIAM J. Sci. Comput., 14, 6, 1394-1414, 1993 -# -# Also, with the numbers written out, this is Configuration 3 from -# Lax and Liu, SIAM J. Sci. Comput., 19, 2, 319-340, 1998 -# -# See also LeVeque JCP 131, 327-353, 1997 - -[quadrant] -rho1 = 1.5 ; quadrant 1 initial density -u1 = 0.0 ; quadrant 1 initial x-velocity -v1 = 0.0 ; quadrant 1 initial y-velocity -p1 = 1.5 ; quadrant 1 initial pressure - -rho2 = 0.532258064516129 ; quadrant 2 initial density -u2 = 1.206045378311055 ; quadrant 2 initial x-velocity -v2 = 0.0 ; quadrant 2 initial y-velocity -p2 = 0.3 ; quadrant 2 initial pressure - -rho3 = 0.137992831541219 ; quadrant 3 initial density -u3 = 1.206045378311055 ; quadrant 3 initial x-velocity -v3 = 1.206045378311055 ; quadrant 3 initial y-velocity -p3 = 0.029032258064516 ; quadrant 3 initial pressure - -rho4 = 0.532258064516129 ; quadrant 4 initial density -u4 = 0.0 ; quadrant 4 initial x-velocity -v4 = 1.206045378311055 ; quadrant 4 initial y-velocity -p4 = 0.3 ; quadrant 4 initial pressure - -cx = 0.5 ; corner x position -cy = 0.5 ; corner y position - - diff --git a/compressible_mapped/problems/_ramp.defaults b/compressible_mapped/problems/_ramp.defaults deleted file mode 100644 index bc7975170..000000000 --- a/compressible_mapped/problems/_ramp.defaults +++ /dev/null @@ -1,19 +0,0 @@ -# these defaults comes from the third test problem in -# Woodward and Colella. Journal of Computational Physics, 54, 115-174, 1984 -# -# Also, the numbers is consitent with the ones in Castro -# - - -[ramp] -rhol = 8.0 ; post-shock initial density -ul = 7.1447096 ; post-shock initial x-velocity -vl = -4.125 ; post-shock initial y-velocity -pl = 116.5 ; post-shock initial pressure - -rhor = 1.4 ; pre-shock initial density -ur = 0.0 ; pre-shock initial x-velocity -vr = 0.0 ; pre-shock initial y-velocity -pr = 1.0 ; pre-shock initial pressure - - diff --git a/compressible_mapped/problems/_rt.defaults b/compressible_mapped/problems/_rt.defaults deleted file mode 100644 index 5fb52e497..000000000 --- a/compressible_mapped/problems/_rt.defaults +++ /dev/null @@ -1,10 +0,0 @@ -[rt] -dens1 = 1.0 -dens2 = 2.0 - -amp = 1.0 -sigma = 0.1 - -p0 = 10.0 - - diff --git a/compressible_mapped/problems/_rt2.defaults b/compressible_mapped/problems/_rt2.defaults deleted file mode 100644 index a7daabef3..000000000 --- a/compressible_mapped/problems/_rt2.defaults +++ /dev/null @@ -1,10 +0,0 @@ -[rt2] -dens1 = 1.0 -dens2 = 2.0 - -amp = 1.0 -sigma = 0.1 - -p0 = 10.0 - - diff --git a/compressible_mapped/problems/_sedov.defaults b/compressible_mapped/problems/_sedov.defaults deleted file mode 100644 index 21fbd398a..000000000 --- a/compressible_mapped/problems/_sedov.defaults +++ /dev/null @@ -1,4 +0,0 @@ -[sedov] -r_init = 0.1 ; radius for the initial perturbation -nsub = 4 - diff --git a/compressible_mapped/problems/acoustic_pulse.py b/compressible_mapped/problems/acoustic_pulse.py index 46f699fa4..e1ac4d95d 100644 --- a/compressible_mapped/problems/acoustic_pulse.py +++ b/compressible_mapped/problems/acoustic_pulse.py @@ -1,12 +1,12 @@ from __future__ import print_function -# import sys +import sys import numpy as np import sympy from sympy.abc import x, y from util import msg -# import mesh.fv as fv +import mesh.mapped as mapped def init_data(myd, rp): @@ -15,11 +15,11 @@ def init_data(myd, rp): 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() + # make sure that we are passed a valid patch object + if not isinstance(myd, mapped.MappedCellCenterData2d): + 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") diff --git a/compressible_mapped/problems/advect.py b/compressible_mapped/problems/advect.py index 4523524af..e77126544 100644 --- a/compressible_mapped/problems/advect.py +++ b/compressible_mapped/problems/advect.py @@ -1,8 +1,11 @@ from __future__ import print_function import sys -import mesh.patch as patch import numpy as np +import sympy +from sympy.abc import x, y + +import mesh.mapped as mapped from util import msg @@ -12,7 +15,7 @@ def init_data(my_data, rp): msg.bold("initializing the advect problem...") # make sure that we are passed a valid patch object - if not isinstance(my_data, patch.CellCenterData2d): + if not isinstance(my_data, mapped.MappedCellCenterData2d): print("ERROR: patch invalid in advect.py") print(my_data.__class__) sys.exit() @@ -38,45 +41,32 @@ def init_data(my_data, rp): ymin = rp.get_param("mesh.ymin") ymax = rp.get_param("mesh.ymax") - xctr = 0.5*(xmin + xmax) - yctr = 0.5*(ymin + ymax) + myg = my_data.grid + + X, Y = myg.physical_coords() + + xctr, yctr = 0.5 * \ + (myg.physical_coords(xmin, ymin) + myg.physical_coords(xmax, ymax)) # this is identical to the advection/smooth problem - dens[:, :] = 1.0 + np.exp(-60.0*((my_data.grid.x2d-xctr)**2 + - (my_data.grid.y2d-yctr)**2)) + dens[:, :] = 1.0 + np.exp(-60.0 * ((X - xctr)**2 + + (Y - yctr)**2)) # velocity is diagonal u = 1.0 v = 1.0 - xmom[:, :] = dens[:, :]*u - ymom[:, :] = dens[:, :]*v + xmom[:, :] = dens[:, :] * u + ymom[:, :] = dens[:, :] * v # pressure is constant p = 1.0 - ener[:, :] = p/(gamma - 1.0) + 0.5*(xmom[:, :]**2 + ymom[:, :]**2)/dens[:, :] - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) + ener[:, :] = p / (gamma - 1.0) + 0.5 * (xmom[:, :] + ** 2 + ymom[:, :]**2) / dens[:, :] - R_mat = np.eye(nvar) - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat +def sym_map(myg): - return R_fc + return sympy.Matrix([0.5*x + y, -x + 3]) def finalize(): diff --git a/compressible_mapped/problems/bubble.py b/compressible_mapped/problems/bubble.py deleted file mode 100644 index e22979ff2..000000000 --- a/compressible_mapped/problems/bubble.py +++ /dev/null @@ -1,109 +0,0 @@ -from __future__ import print_function - -import numpy as np -import sys - -import mesh.patch as patch -from util import msg - - -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] - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - pass diff --git a/compressible_mapped/problems/hse.py b/compressible_mapped/problems/hse.py deleted file mode 100644 index 981e164ec..000000000 --- a/compressible_mapped/problems/hse.py +++ /dev/null @@ -1,85 +0,0 @@ -from __future__ import print_function - -import numpy as np - -import sys -import mesh.patch as patch -from util import msg - - -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[:, :] - - def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - pass diff --git a/compressible_mapped/problems/inputs.acoustic_pulse b/compressible_mapped/problems/inputs.acoustic_pulse index b1dfaef26..21a1f9485 100644 --- a/compressible_mapped/problems/inputs.acoustic_pulse +++ b/compressible_mapped/problems/inputs.acoustic_pulse @@ -22,11 +22,11 @@ ny = 128 xmax = 1.0 ymax = 1.0 -xlboundary = periodic -xrboundary = periodic +xlboundary = outflow +xrboundary = outflow -ylboundary = periodic -yrboundary = periodic +ylboundary = outflow +yrboundary = outflow [acoustic_pulse] diff --git a/compressible_mapped/problems/inputs.acoustic_pulse.256 b/compressible_mapped/problems/inputs.acoustic_pulse.256 index 13743d11e..e0dc73e8a 100644 --- a/compressible_mapped/problems/inputs.acoustic_pulse.256 +++ b/compressible_mapped/problems/inputs.acoustic_pulse.256 @@ -24,12 +24,11 @@ ny = 256 xmax = 1.0 ymax = 1.0 -xlboundary = periodic -xrboundary = periodic - -ylboundary = periodic -yrboundary = periodic +xlboundary = outflow +xrboundary = outflow +ylboundary = outflow +yrboundary = outflow [acoustic_pulse] rho0 = 1.4 diff --git a/compressible_mapped/problems/inputs.acoustic_pulse.512 b/compressible_mapped/problems/inputs.acoustic_pulse.512 index 610d8b039..3aae69719 100644 --- a/compressible_mapped/problems/inputs.acoustic_pulse.512 +++ b/compressible_mapped/problems/inputs.acoustic_pulse.512 @@ -24,11 +24,11 @@ ny = 512 xmax = 1.0 ymax = 1.0 -xlboundary = periodic -xrboundary = periodic +xlboundary = outflow +xrboundary = outflow -ylboundary = periodic -yrboundary = periodic +ylboundary = outflow +yrboundary = outflow [acoustic_pulse] diff --git a/compressible_mapped/problems/inputs.advect.128 b/compressible_mapped/problems/inputs.advect.128 index c657a646a..f0def69b5 100644 --- a/compressible_mapped/problems/inputs.advect.128 +++ b/compressible_mapped/problems/inputs.advect.128 @@ -25,11 +25,11 @@ ny = 128 xmax = 1.0 ymax = 1.0 -xlboundary = periodic -xrboundary = periodic +xlboundary = outflow +xrboundary = outflow -ylboundary = periodic -yrboundary = periodic +ylboundary = outflow +yrboundary = outflow [vis] diff --git a/compressible_mapped/problems/inputs.advect.256 b/compressible_mapped/problems/inputs.advect.256 index 77cec1857..30b083840 100644 --- a/compressible_mapped/problems/inputs.advect.256 +++ b/compressible_mapped/problems/inputs.advect.256 @@ -25,11 +25,11 @@ ny = 256 xmax = 1.0 ymax = 1.0 -xlboundary = periodic -xrboundary = periodic +xlboundary = outflow +xrboundary = outflow -ylboundary = periodic -yrboundary = periodic +ylboundary = outflow +yrboundary = outflow [vis] diff --git a/compressible_mapped/problems/inputs.advect.64 b/compressible_mapped/problems/inputs.advect.64 index 8e99c8ff1..30cfdc59d 100644 --- a/compressible_mapped/problems/inputs.advect.64 +++ b/compressible_mapped/problems/inputs.advect.64 @@ -25,11 +25,11 @@ ny = 64 xmax = 1.0 ymax = 1.0 -xlboundary = periodic -xrboundary = periodic +xlboundary = outflow +xrboundary = outflow -ylboundary = periodic -yrboundary = periodic +ylboundary = outflow +yrboundary = outflow [vis] diff --git a/compressible_mapped/problems/inputs.bubble b/compressible_mapped/problems/inputs.bubble deleted file mode 100644 index f25179261..000000000 --- a/compressible_mapped/problems/inputs.bubble +++ /dev/null @@ -1,39 +0,0 @@ -# simple inputs files for the four-corner problem. - -[driver] -max_steps = 1000 -tmax = 100.0 - - -[io] -basename = bubble_ -n_out = 100 - - -[mesh] -nx = 128 -ny = 256 -xmax = 4.0 -ymax = 8.0 - -xlboundary = outflow -xrboundary = outflow - -ylboundary = hse -yrboundary = hse - - -[bubble] -scale_height = 1.0 -dens_base = 1000.0 - -x_pert = 2.0 -y_pert = 2.0 -r_pert = 0.25 -pert_amplitude_factor = 2.0 - - -[compressible] -grav = -2.0 - -limiter = 2 diff --git a/compressible_mapped/problems/inputs.hse b/compressible_mapped/problems/inputs.hse deleted file mode 100644 index 08eef9473..000000000 --- a/compressible_mapped/problems/inputs.hse +++ /dev/null @@ -1,34 +0,0 @@ -# simple inputs files for the four-corner problem. - -[driver] -max_steps = 10000 -tmax = 3.0 - - -[io] -basename = rt_ -n_out = 100 - - -[mesh] -nx = 64 -ny = 192 -xmax = 1.0 -ymax = 3.0 - -xlboundary = periodic -xrboundary = periodic - -ylboundary = hse -yrboundary = hse - - -[hse] -dens0 = 1.0 -H = 1.0 - - -[compressible] -grav = -1.0 - -limiter = 2 diff --git a/compressible_mapped/problems/inputs.logo b/compressible_mapped/problems/inputs.logo deleted file mode 100644 index 3d6aa18e5..000000000 --- a/compressible_mapped/problems/inputs.logo +++ /dev/null @@ -1,34 +0,0 @@ -[driver] -max_steps = 5000 -tmax = 30.0 - - -[compressible] -limiter = 2 -cvisc = 0.1 - - -[io] -basename = logo_ -dt_out = 0.02 - - -[eos] -gamma = 1.4 - - -[mesh] -nx = 64 -ny = 64 -xmax = 1.0 -ymax = 1.0 - -xlboundary = outflow -xrboundary = outflow - -ylboundary = outflow -yrboundary = outflow - - -[vis] -dovis = 1 diff --git a/compressible_mapped/problems/inputs.quad b/compressible_mapped/problems/inputs.quad deleted file mode 100644 index 51723d29a..000000000 --- a/compressible_mapped/problems/inputs.quad +++ /dev/null @@ -1,52 +0,0 @@ -# simple inputs files for the four-corner problem. - -[driver] -max_steps = 1000 -tmax = 0.8 - - -[compressible] -limiter = 2 -cvisc = 0.1 - -[io] -basename = quad_unsplit_ -dt_out = 0.1 - - -[mesh] -nx = 256 -ny = 256 -xmax = 1.0 -ymax = 1.0 - -xlboundary = outflow -xrboundary = outflow - -ylboundary = outflow -yrboundary = outflow - - -[quadrant] -rho1 = 1.4 -u1 = 0.0 -v1 = 0.0 -p1 = 1.5 - -rho2 = 0.532258064516129 -u2 = 1.206045378311055 -v2 = 0.0 -p2 = 0.3 - -rho3 = 0.137992831541219 -u3 = 1.206045378311055 -v3 = 1.206045378311055 -p3 = 0.029032258064516 - -rho4 = 0.532258064516129 -u4 = 0.0 -v4 = 1.206045378311055 -p4 = 0.3 - -cx = 0.8 -cy = 0.8 diff --git a/compressible_mapped/problems/inputs.ramp b/compressible_mapped/problems/inputs.ramp deleted file mode 100644 index e047d8f83..000000000 --- a/compressible_mapped/problems/inputs.ramp +++ /dev/null @@ -1,40 +0,0 @@ -# simple inputs files for the double Mach reflection problem. - -[driver] -max_steps = 12500 -tmax = 0.25 - - -[compressible] -limiter = 2 -cvisc = 0.1 - -[io] -basename = double_mach_reflection_ -dt_out = 0.1 - - -[mesh] -nx = 1024 -ny = 256 -xmax = 4.0 -ymax = 1.0 - -xlboundary = ramp -xrboundary = outflow - -ylboundary = ramp -yrboundary = ramp - - -[ramp] -rhol = 8.0 -ul = 7.1447096 -vl = -4.125 -pl = 116.5 - -rhor = 1.4 -ur = 0.0 -vr = 0.0 -pr = 1.0 - diff --git a/compressible_mapped/problems/inputs.rt b/compressible_mapped/problems/inputs.rt deleted file mode 100644 index b8e7cf3de..000000000 --- a/compressible_mapped/problems/inputs.rt +++ /dev/null @@ -1,33 +0,0 @@ -# simple inputs files for the four-corner problem. - -[driver] -max_steps = 10000 -tmax = 3.0 - - -[io] -basename = rt_ -n_out = 100 - - -[mesh] -nx = 64 -ny = 192 -xmax = 1.0 -ymax = 3.0 - -xlboundary = periodic -xrboundary = periodic - -ylboundary = hse -yrboundary = hse - - -[rt] -amp = 0.25 - - -[compressible] -grav = -1.0 - -limiter = 2 diff --git a/compressible_mapped/problems/inputs.rt2 b/compressible_mapped/problems/inputs.rt2 deleted file mode 100644 index 6f76e907c..000000000 --- a/compressible_mapped/problems/inputs.rt2 +++ /dev/null @@ -1,33 +0,0 @@ -# simple inputs files for the four-corner problem. - -[driver] -max_steps = 10000 -tmax = 5.0 - - -[io] -basename = rt_ -n_out = 10000 -dt_out = 0.025 - -[mesh] -nx = 384 -ny = 192 -xmax = 6.0 -ymax = 3.0 - -xlboundary = periodic -xrboundary = periodic - -ylboundary = hse -yrboundary = hse - - -[rt2] -amp = 0.1 -sigma = 0.025 - -[compressible] -grav = -1.0 - -limiter = 2 diff --git a/compressible_mapped/problems/inputs.rt_gravity_waves b/compressible_mapped/problems/inputs.rt_gravity_waves deleted file mode 100644 index f34d41857..000000000 --- a/compressible_mapped/problems/inputs.rt_gravity_waves +++ /dev/null @@ -1,37 +0,0 @@ -# simple inputs files for the four-corner problem. - -[driver] -max_steps = 10000 -tmax = 3.0 - - -[io] -basename = rt_ -n_out = 3 -dt_out = 1000000 - - -[mesh] -nx = 64 -ny = 192 -xmax = 1.0 -ymax = 3.0 - -xlboundary = periodic -xrboundary = periodic - -ylboundary = hse -yrboundary = hse - - -[rt] -amp = 0.25 - -dens1 = 2.0 -dens2 = 1.0 - - -[compressible] -grav = -1.0 - -limiter = 2 diff --git a/compressible_mapped/problems/inputs.sedov b/compressible_mapped/problems/inputs.sedov deleted file mode 100644 index 1dabca855..000000000 --- a/compressible_mapped/problems/inputs.sedov +++ /dev/null @@ -1,38 +0,0 @@ -[driver] -max_steps = 5000 -tmax = 0.1 - - -[compressible] -limiter = 2 -cvisc = 0.1 - - -[io] -basename = sedov_unsplit_ -dt_out = 0.0125 - - -[eos] -gamma = 1.4 - - -[mesh] -nx = 128 -ny = 128 -xmax = 1.0 -ymax = 1.0 - -xlboundary = outflow -xrboundary = outflow - -ylboundary = outflow -yrboundary = outflow - - -[sedov] -r_init = 0.01 - - -[vis] -dovis = 1 diff --git a/compressible_mapped/problems/kh.py b/compressible_mapped/problems/kh.py index 060fb56fd..6b8662a3b 100644 --- a/compressible_mapped/problems/kh.py +++ b/compressible_mapped/problems/kh.py @@ -1,8 +1,10 @@ from __future__ import print_function import numpy as np +import sympy +from sympy.abc import x, y -import mesh.patch as patch +import mesh.mapped as mapped from util import msg @@ -12,7 +14,7 @@ def init_data(my_data, rp): msg.bold("initializing the Kelvin-Helmholtz problem...") # make sure that we are passed a valid patch object - if not isinstance(my_data, patch.CellCenterData2d): + if not isinstance(my_data, mapped.MappedCellCenterData2d): print(my_data.__class__) msg.fail("ERROR: patch invalid in kh.py") @@ -34,68 +36,60 @@ def init_data(my_data, rp): rho_2 = rp.get_param("kh.rho_2") v_2 = rp.get_param("kh.v_2") + xmin_coord = rp.get_param("mesh.xmin") + ymin_coord = rp.get_param("mesh.ymin") + xmax_coord = rp.get_param("mesh.xmax") + ymax_coord = rp.get_param("mesh.ymax") + gamma = rp.get_param("eos.gamma") myg = my_data.grid - dy = 0.025 + xmin, ymin = myg.physical_coords(xmin_coord, ymin_coord) + xmax, ymax = myg.physical_coords(xmax_coord, ymax_coord) + + dy = 0.025*(ymax - ymin) 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 + X, Y = myg.physical_coords() + + idx1 = Y < 0.25*ymax + idx2 = np.logical_and(Y >= 0.25*ymax, Y < 0.5*ymax) + idx3 = np.logical_and(Y >= 0.5*ymax, Y < 0.75*ymax) + idx4 = Y >= 0.75*ymax # 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) + dens[idx1] = rho_1 - rhom * np.exp((Y[idx1] - 0.25*ymax) / dy) + xmom[idx1] = v_1 - vm * np.exp((Y[idx1] - 0.25*ymax) / 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) + dens[idx2] = rho_2 + rhom * np.exp((0.25*ymax - Y[idx2]) / dy) + xmom[idx2] = v_2 + vm * np.exp((0.25*ymax - Y[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) + dens[idx3] = rho_2 + rhom * np.exp((Y[idx3] - 0.75*ymax) / dy) + xmom[idx3] = v_2 + vm * np.exp((Y[idx3] - 0.75*ymax) / 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) + dens[idx4] = rho_1 - rhom * np.exp((0.75*ymax - Y[idx4]) / dy) + xmom[idx4] = v_1 - vm * np.exp((0.75*ymax - Y[idx4]) / dy) # upper half xmom[:, :] *= dens - ymom[:, :] = dens * w0 * np.sin(4 * np.pi * myg.x2d) + ymom[:, :] = dens * w0 * np.sin(4 * np.pi * X/(xmax-xmin)) p = 2.5 ener[:, :] = p / (gamma - 1.0) + 0.5 * (xmom[:, :] ** 2 + ymom[:, :]**2) / dens[:, :] -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat +def sym_map(myg): - return R_fc + return sympy.Matrix([-x + 4, 2*y]) def finalize(): diff --git a/compressible_mapped/problems/logo.py b/compressible_mapped/problems/logo.py deleted file mode 100644 index 9d0b0ba8f..000000000 --- a/compressible_mapped/problems/logo.py +++ /dev/null @@ -1,104 +0,0 @@ -from __future__ import print_function - -import sys -import mesh.patch as patch -import numpy as np -from util import msg -import matplotlib.pyplot as plt - - -def init_data(my_data, rp): - """ initialize the logo 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 logo.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) - dens[:, :] = 1.0 - xmom[:, :] = 0.0 - ymom[:, :] = 0.0 - - # set the density in the logo zones to be really large - logo_dens = 50.0 - - dens.v()[:, :] = logo[:, :] * logo_dens - - # pressure equilibrium - gamma = rp.get_param("eos.gamma") - - p_ambient = 1.e-5 - ener[:, :] = p_ambient / (gamma - 1.0) - - # explosion - ener[myg.ilo, myg.jlo] = 1.0 - ener[myg.ilo, myg.jhi] = 1.0 - ener[myg.ihi, myg.jlo] = 1.0 - ener[myg.ihi, myg.jhi] = 1.0 - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - - msg = """ - The script analysis/sedov_compare.py can be used to analyze these - results. That will perform an average at constant radius and - compare the radial profiles to the exact solution. Sample exact - data is provided as analysis/cylindrical-sedov.out - """ - - print(msg) diff --git a/compressible_mapped/problems/logo.txt b/compressible_mapped/problems/logo.txt deleted file mode 100644 index e57926259..000000000 --- a/compressible_mapped/problems/logo.txt +++ /dev/null @@ -1,21 +0,0 @@ -xxxxxxx -xxxxxxxx -xx xx -xx xx -xx xx -xx xxx -xxxxxxx xx xx xx xxxx xxxx -xxxxx xx xx xx xxxxx xxxxxx -xx xx xx xxxx xxx xxx -xx xx xx xxx xx xx -xx xx xx xx xx xx -xx xxx xx xx xxx xxx -xx xxxxxx xx xxxxxx -xx xxxx xx xxxx - xx - xx - xx - xx - xx - xxxx - xxx diff --git a/compressible_mapped/problems/quad.py b/compressible_mapped/problems/quad.py deleted file mode 100644 index 889393cf2..000000000 --- a/compressible_mapped/problems/quad.py +++ /dev/null @@ -1,119 +0,0 @@ -from __future__ import print_function - -import sys - -import numpy as np - -import mesh.patch as patch -from util import msg - - -def init_data(my_data, rp): - """ initialize the quadrant problem """ - - msg.bold("initializing the quadrant problem...") - - # make sure that we are passed a valid patch object - if not isinstance(my_data, patch.CellCenterData2d): - print("ERROR: patch invalid in quad.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) - r1 = rp.get_param("quadrant.rho1") - u1 = rp.get_param("quadrant.u1") - v1 = rp.get_param("quadrant.v1") - p1 = rp.get_param("quadrant.p1") - - r2 = rp.get_param("quadrant.rho2") - u2 = rp.get_param("quadrant.u2") - v2 = rp.get_param("quadrant.v2") - p2 = rp.get_param("quadrant.p2") - - r3 = rp.get_param("quadrant.rho3") - u3 = rp.get_param("quadrant.u3") - v3 = rp.get_param("quadrant.v3") - p3 = rp.get_param("quadrant.p3") - - r4 = rp.get_param("quadrant.rho4") - u4 = rp.get_param("quadrant.u4") - v4 = rp.get_param("quadrant.v4") - p4 = rp.get_param("quadrant.p4") - - cx = rp.get_param("quadrant.cx") - cy = rp.get_param("quadrant.cy") - - gamma = rp.get_param("eos.gamma") - - # there is probably an easier way to do this, but for now, we - # will just do an explicit loop. Also, we really want to set - # the pressue and get the internal energy from that, and then - # compute the total energy (which is what we store). For now - # we will just fake this - - myg = my_data.grid - - iq1 = np.logical_and(myg.x2d >= cx, myg.y2d >= cy) - iq2 = np.logical_and(myg.x2d < cx, myg.y2d >= cy) - iq3 = np.logical_and(myg.x2d < cx, myg.y2d < cy) - iq4 = np.logical_and(myg.x2d >= cx, myg.y2d < cy) - - # quadrant 1 - dens[iq1] = r1 - xmom[iq1] = r1 * u1 - ymom[iq1] = r1 * v1 - ener[iq1] = p1 / (gamma - 1.0) + 0.5 * r1 * (u1 * u1 + v1 * v1) - - # quadrant 2 - dens[iq2] = r2 - xmom[iq2] = r2 * u2 - ymom[iq2] = r2 * v2 - ener[iq2] = p2 / (gamma - 1.0) + 0.5 * r2 * (u2 * u2 + v2 * v2) - - # quadrant 3 - dens[iq3] = r3 - xmom[iq3] = r3 * u3 - ymom[iq3] = r3 * v3 - ener[iq3] = p3 / (gamma - 1.0) + 0.5 * r3 * (u3 * u3 + v3 * v3) - - # quadrant 4 - dens[iq4] = r4 - xmom[iq4] = r4 * u4 - ymom[iq4] = r4 * v4 - ener[iq4] = p4 / (gamma - 1.0) + 0.5 * r4 * (u4 * u4 + v4 * v4) - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - pass diff --git a/compressible_mapped/problems/ramp.py b/compressible_mapped/problems/ramp.py deleted file mode 100644 index b421d5a77..000000000 --- a/compressible_mapped/problems/ramp.py +++ /dev/null @@ -1,113 +0,0 @@ -from __future__ import print_function - -import sys - -import numpy as np -import math - -import mesh.patch as patch -from util import msg - - -def init_data(my_data, rp): - """ initialize the double Mach reflection problem """ - - msg.bold("initializing the double Mach reflection problem...") - - # make sure that we are passed a valid patch object - if not isinstance(my_data, patch.CellCenterData2d): - print("ERROR: patch invalid in ramp.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) - - r_l = rp.get_param("ramp.rhol") - u_l = rp.get_param("ramp.ul") - v_l = rp.get_param("ramp.vl") - p_l = rp.get_param("ramp.pl") - - r_r = rp.get_param("ramp.rhor") - u_r = rp.get_param("ramp.ur") - v_r = rp.get_param("ramp.vr") - p_r = rp.get_param("ramp.pr") - - gamma = rp.get_param("eos.gamma") - - energy_l = p_l / (gamma - 1.0) + 0.5 * r_l * (u_l * u_l + v_l * v_l) - energy_r = p_r / (gamma - 1.0) + 0.5 * r_r * (u_r * u_r + v_r * v_r) - - # there is probably an easier way to do this, but for now, we - # will just do an explicit loop. Also, we really want to set - # the pressue and get the internal energy from that, and then - # compute the total energy (which is what we store). For now - # we will just fake this - - myg = my_data.grid - dens[:, :] = 1.4 - - for j in range(myg.jlo, myg.jhi + 1): - cy_up = myg.y[j] + 0.5 * myg.dy * math.sqrt(3) - cy_down = myg.y[j] - 0.5 * myg.dy * math.sqrt(3) - cy = np.array([cy_down, cy_up]) - - for i in range(myg.ilo, myg.ihi + 1): - dens[i, j] = 0.0 - xmom[i, j] = 0.0 - ymom[i, j] = 0.0 - ener[i, j] = 0.0 - - sf_up = math.tan(math.pi / 3.0) * \ - (myg.x[i] + 0.5 * myg.dx * math.sqrt(3) - 1.0 / 6.0) - sf_down = math.tan(math.pi / 3.0) * \ - (myg.x[i] - 0.5 * myg.dx * math.sqrt(3) - 1.0 / 6.0) - sf = np.array([sf_down, sf_up]) # initial shock front - - for y in cy: - for shockfront in sf: - if y >= shockfront: - dens[i, j] = dens[i, j] + 0.25 * r_l - xmom[i, j] = xmom[i, j] + 0.25 * r_l * u_l - ymom[i, j] = ymom[i, j] + 0.25 * r_l * v_l - ener[i, j] = ener[i, j] + 0.25 * energy_l - else: - dens[i, j] = dens[i, j] + 0.25 * r_r - xmom[i, j] = xmom[i, j] + 0.25 * r_r * u_r - ymom[i, j] = ymom[i, j] + 0.25 * r_r * v_r - ener[i, j] = ener[i, j] + 0.25 * energy_r - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - pass diff --git a/compressible_mapped/problems/rt.py b/compressible_mapped/problems/rt.py deleted file mode 100644 index 122885e01..000000000 --- a/compressible_mapped/problems/rt.py +++ /dev/null @@ -1,99 +0,0 @@ -from __future__ import print_function - -import numpy as np - -import sys -import mesh.patch as patch -from util import msg - - -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() - - j = myg.jlo - while j <= myg.jhi: - 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) - - j += 1 - - ymom[:, :] = amp * np.cos(2.0 * np.pi * myg.x2d / (myg.xmax - myg.xmin) - ) * np.exp(-(myg.y2d - ycenter)**2 / sigma**2) - - ymom *= dens - - # set the energy (P = cs2*dens) - ener[:, :] = p[:, :] / (gamma - 1.0) + \ - 0.5 * (xmom[:, :]**2 + ymom[:, :]**2) / dens[:, :] - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - pass diff --git a/compressible_mapped/problems/rt2.py b/compressible_mapped/problems/rt2.py deleted file mode 100644 index 725b701b8..000000000 --- a/compressible_mapped/problems/rt2.py +++ /dev/null @@ -1,112 +0,0 @@ -"""A RT problem with two distinct modes: short wave length on the -left and long wavelenght on the right. This allows one to see -how the growth rate depends on wavenumber. -""" - -from __future__ import print_function - -import numpy as np - -import sys -import mesh.patch as patch -from util import msg - - -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 rt2.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("rt2.dens1") - dens2 = rp.get_param("rt2.dens2") - p0 = rp.get_param("rt2.p0") - amp = rp.get_param("rt2.amp") - sigma = rp.get_param("rt2.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 - - f_l = 18 - f_r = 3 - - # 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() - - j = myg.jlo - while j <= myg.jhi: - 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) - - j += 1 - - idx_l = myg.x2d < (myg.xmax - myg.xmin) / 3.0 - idx_r = myg.x2d >= (myg.xmax - myg.xmin) / 3.0 - - ymom[idx_l] = amp * np.sin(4.0 * np.pi * f_l * myg.x2d[idx_l] / - (myg.xmax - myg.xmin)) * np.exp(-(myg.y2d[idx_l] - ycenter)**2 / sigma**2) - ymom[idx_r] = amp * np.sin(4.0 * np.pi * f_r * myg.x2d[idx_r] / - (myg.xmax - myg.xmin)) * np.exp(-(myg.y2d[idx_r] - ycenter)**2 / sigma**2) - - ymom *= dens - - # set the energy (P = cs2*dens) - ener[:, :] = p[:, :] / (gamma - 1.0) + \ - 0.5 * (xmom[:, :]**2 + ymom[:, :]**2) / dens[:, :] - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - pass diff --git a/compressible_mapped/problems/sedov.py b/compressible_mapped/problems/sedov.py deleted file mode 100644 index 59fea1498..000000000 --- a/compressible_mapped/problems/sedov.py +++ /dev/null @@ -1,115 +0,0 @@ -from __future__ import print_function - -import sys -import mesh.patch as patch -import numpy as np -from util import msg -import math - - -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 = 1.0 - - 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) - - -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - -def finalize(): - """ print out any information to the user at the end of the run """ - - msg = """ - The script analysis/sedov_compare.py can be used to analyze these - results. That will perform an average at constant radius and - compare the radial profiles to the exact solution. Sample exact - data is provided as analysis/cylindrical-sedov.out - """ - - print(msg) diff --git a/compressible_mapped/problems/sod.py b/compressible_mapped/problems/sod.py index 60c859378..7c7b2241e 100644 --- a/compressible_mapped/problems/sod.py +++ b/compressible_mapped/problems/sod.py @@ -1,9 +1,10 @@ from __future__ import print_function import sys -import numpy as np +import sympy +from sympy.abc import x, y -import mesh.patch as patch +import mesh.mapped as mapped from util import msg @@ -13,7 +14,7 @@ def init_data(my_data, rp): msg.bold("initializing the sod problem...") # make sure that we are passed a valid patch object - if not isinstance(my_data, patch.CellCenterData2d): + if not isinstance(my_data, mapped.MappedCellCenterData2d): print("ERROR: patch invalid in sod.py") print(my_data.__class__) sys.exit() @@ -47,15 +48,17 @@ def init_data(my_data, rp): direction = rp.get_param("sod.direction") - xctr = 0.5 * (xmin + xmax) - yctr = 0.5 * (ymin + ymax) - myg = my_data.grid + X, Y = myg.physical_coords() + + xctr, yctr = 0.5 * \ + (myg.physical_coords(xmin, ymin) + myg.physical_coords(xmax, ymax)) + if direction == "x": # left - idxl = myg.x2d <= xctr + idxl = X <= xctr dens[idxl] = dens_left xmom[idxl] = dens_left * u_left @@ -63,7 +66,7 @@ def init_data(my_data, rp): ener[idxl] = p_left / (gamma - 1.0) + 0.5 * xmom[idxl] * u_left # right - idxr = myg.x2d > xctr + idxr = X > xctr dens[idxr] = dens_right xmom[idxr] = dens_right * u_right @@ -73,7 +76,7 @@ def init_data(my_data, rp): else: # bottom - idxb = myg.y2d <= yctr + idxb = Y <= yctr dens[idxb] = dens_left xmom[idxb] = 0.0 @@ -81,7 +84,7 @@ def init_data(my_data, rp): ener[idxb] = p_left / (gamma - 1.0) + 0.5 * ymom[idxb] * u_left # top - idxt = myg.y2d > yctr + idxt = Y > yctr dens[idxt] = dens_right xmom[idxt] = 0.0 @@ -89,27 +92,9 @@ def init_data(my_data, rp): ener[idxt] = p_right / (gamma - 1.0) + 0.5 * ymom[idxt] * u_right -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat +def sym_map(myg): - return R_fc + return sympy.Matrix([x - y, x + y + 3]) def finalize(): diff --git a/compressible_mapped/problems/test.py b/compressible_mapped/problems/test.py index 6be81cbbc..035d74bf7 100644 --- a/compressible_mapped/problems/test.py +++ b/compressible_mapped/problems/test.py @@ -1,7 +1,6 @@ from __future__ import print_function import sys -import numpy as np import sympy from sympy.abc import x, y @@ -32,32 +31,9 @@ def init_data(my_data, rp): ener[:, :] = 2.5 -def area(myg): - return myg.dx * myg.dy + myg.scratch_array() - - -def h(idir, myg): - if idir == 1: - return myg.dy + myg.scratch_array() - else: - return myg.dx + myg.scratch_array() - - -def R(iface, myg, nvar, ixmom, iymom): - R_fc = myg.scratch_array(nvar=(nvar, nvar)) - - R_mat = np.eye(nvar) - - for i in range(myg.qx): - for j in range(myg.qy): - R_fc[i, j, :, :] = R_mat - - return R_fc - - def sym_map(myg): - return sympy.Matrix([-2*y, x+4]) + return sympy.Matrix([-2 * y, x + 4]) def finalize(): diff --git a/docs/source/compressible_mapped.problems.rst b/docs/source/compressible_mapped.problems.rst index 971b87935..79f378c45 100644 --- a/docs/source/compressible_mapped.problems.rst +++ b/docs/source/compressible_mapped.problems.rst @@ -1,5 +1,5 @@ compressible\_mapped\.problems package -=================================== +====================================== .. automodule:: compressible_mapped.problems :members: @@ -10,15 +10,47 @@ Submodules ---------- compressible\_mapped\.problems\.acoustic\_pulse module ---------------------------------------------------- +------------------------------------------------------ .. automodule:: compressible_mapped.problems.acoustic_pulse :members: :undoc-members: :show-inheritance: +compressible\_mapped\.problems\.advect module +--------------------------------------------- + +.. automodule:: compressible_mapped.problems.advect + :members: + :undoc-members: + :show-inheritance: + +compressible\_mapped\.problems\.kh module +----------------------------------------- + +.. automodule:: compressible_mapped.problems.kh + :members: + :undoc-members: + :show-inheritance: + +compressible\_mapped\.problems\.sedov module +-------------------------------------------- + +.. automodule:: compressible_mapped.problems.sedov + :members: + :undoc-members: + :show-inheritance: + +compressible\_mapped\.problems\.sod module +------------------------------------------ + +.. automodule:: compressible_mapped.problems.sod + :members: + :undoc-members: + :show-inheritance: + compressible\_mapped\.problems\.test module ------------------------------------ +------------------------------------------- .. automodule:: compressible_mapped.problems.test :members: diff --git a/docs/source/mapped_basics.rst b/docs/source/mapped_basics.rst index 1d68bf535..3eaa0baca 100644 --- a/docs/source/mapped_basics.rst +++ b/docs/source/mapped_basics.rst @@ -70,7 +70,7 @@ using a ``sympy.Matrix`` object as a function of the cartesian coordinates mydata.make_rotation_matrices(ivars) -This create the mapped cell-centered data object, ``mydata``, that lives on the +This creates the mapped cell-centered data object, ``mydata``, that lives on the mapped grid we just defined. Just as we would for the non-mapped grid, we next create a boundary condition object to specify the boundary conditions on each edge, register variables and call the ``create()`` function to allocate storage for the diff --git a/mesh/mapped.py b/mesh/mapped.py index 83dbfa275..a999938c9 100644 --- a/mesh/mapped.py +++ b/mesh/mapped.py @@ -382,14 +382,14 @@ def fill_mapped_ghost(self, name, n=0, bc=None): j_bnd = myd.g.jhi+1+j j_src = myd.g.jhi-j - q_rot = self.R_fcx[i, myd.g.jhi+1] @ myd[i, j_src, n] + q_rot = self.R_fcx[i, myd.g.jhi+1] @ myd[i, j_src, :] q_rot[n] = -q_rot[n] myd[i, j_bnd, n] = (self.R_fcx[i, myd.g.jhi+1].T @ q_rot)[n] else: for i in range(myd.g.qx): - q_rot = self.R_fcx[i, myd.g.jhi+1] @ myd[i, myd.g.jhi, n] + q_rot = self.R_fcx[i, myd.g.jhi+1] @ myd[i, myd.g.jhi, :] q_rot[n] = 2*bc.yr_value - q_rot[n] myd[:, myd.g.jhi+1, n] = (self.R_fcx[i, myd.g.jhi+1].T @ q_rot)[n]