def test_slipwall_identity(actx_factory, dim): """Identity test - check for the expected boundary solution. Checks that the slipwall implements the expected boundary solution: rho_plus = rho_minus v_plus = v_minus - 2 * (n_hat . v_minus) * n_hat mom_plus = rho_plus * v_plus E_plus = E_minus """ actx = actx_factory() nel_1d = 4 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, nelements_per_axis=(nel_1d, ) * dim) order = 3 discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) eos = IdealSingleGas() orig = np.zeros(shape=(dim, )) nhat = thaw(actx, discr.normal(BTAG_ALL)) gas_model = GasModel(eos=eos) logger.info(f"Number of {dim}d elems: {mesh.nelements}") # for velocity going along each direction for vdir in range(dim): vel = np.zeros(shape=(dim, )) # for velocity directions +1, and -1 for parity in [1.0, -1.0]: vel[vdir] = parity # Check incoming normal initializer = Lump(dim=dim, center=orig, velocity=vel, rhoamp=0.0) wall = AdiabaticSlipBoundary() uniform_state = initializer(nodes) fluid_state = make_fluid_state(uniform_state, gas_model) def bnd_norm(vec): return actx.to_numpy(discr.norm(vec, p=np.inf, dd=BTAG_ALL)) interior_soln = \ project_fluid_state(discr, "vol", BTAG_ALL, gas_model=gas_model, state=fluid_state) bnd_soln = \ wall.adiabatic_slip_state(discr, btag=BTAG_ALL, gas_model=gas_model, state_minus=interior_soln) from grudge.trace_pair import TracePair bnd_pair = TracePair(BTAG_ALL, interior=interior_soln.cv, exterior=bnd_soln.cv) # check that mass and energy are preserved mass_resid = bnd_pair.int.mass - bnd_pair.ext.mass mass_err = bnd_norm(mass_resid) assert mass_err == 0.0 energy_resid = bnd_pair.int.energy - bnd_pair.ext.energy energy_err = bnd_norm(energy_resid) assert energy_err == 0.0 # check that exterior momentum term is mom_interior - 2 * mom_normal mom_norm_comp = np.dot(bnd_pair.int.momentum, nhat) mom_norm = nhat * mom_norm_comp expected_mom_ext = bnd_pair.int.momentum - 2.0 * mom_norm mom_resid = bnd_pair.ext.momentum - expected_mom_ext mom_err = bnd_norm(mom_resid) assert mom_err == 0.0
def test_slipwall_flux(actx_factory, dim, order): """Check for zero boundary flux. Check for vanishing flux across the slipwall. """ actx = actx_factory() wall = AdiabaticSlipBoundary() eos = IdealSingleGas() gas_model = GasModel(eos=eos) from pytools.convergence import EOCRecorder eoc = EOCRecorder() for nel_1d in [4, 8, 12]: from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, nelements_per_axis=(nel_1d, ) * dim) discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) nhat = thaw(actx, discr.normal(BTAG_ALL)) h = 1.0 / nel_1d def bnd_norm(vec): return actx.to_numpy(discr.norm(vec, p=np.inf, dd=BTAG_ALL)) logger.info(f"Number of {dim}d elems: {mesh.nelements}") # for velocities in each direction err_max = 0.0 for vdir in range(dim): vel = np.zeros(shape=(dim, )) # for velocity directions +1, and -1 for parity in [1.0, -1.0]: vel[vdir] = parity from mirgecom.initializers import Uniform initializer = Uniform(dim=dim, velocity=vel) uniform_state = initializer(nodes) fluid_state = make_fluid_state(uniform_state, gas_model) interior_soln = project_fluid_state(discr, "vol", BTAG_ALL, state=fluid_state, gas_model=gas_model) bnd_soln = wall.adiabatic_slip_state(discr, btag=BTAG_ALL, gas_model=gas_model, state_minus=interior_soln) from grudge.trace_pair import TracePair bnd_pair = TracePair(BTAG_ALL, interior=interior_soln.cv, exterior=bnd_soln.cv) state_pair = TracePair(BTAG_ALL, interior=interior_soln, exterior=bnd_soln) # Check the total velocity component normal # to each surface. It should be zero. The # numerical fluxes cannot be zero. avg_state = 0.5 * (bnd_pair.int + bnd_pair.ext) err_max = max(err_max, bnd_norm(np.dot(avg_state.momentum, nhat))) from mirgecom.inviscid import inviscid_facial_flux bnd_flux = inviscid_facial_flux(discr, state_pair, local=True) err_max = max(err_max, bnd_norm(bnd_flux.mass), bnd_norm(bnd_flux.energy)) eoc.add_data_point(h, err_max) message = (f"EOC:\n{eoc}") logger.info(message) assert (eoc.order_estimate() >= order - 0.5 or eoc.max_error() < 1e-12)