Exemplo n.º 1
0
    def write_soln(write_status=True):
        cv = split_conserved(dim, fields)
        dv = eos.dependent_vars(cv)
        expected_result = initializer(t, nodes)
        result_resid = fields - expected_result
        maxerr = [
            np.max(np.abs(result_resid[i].get())) for i in range(dim + 2)
        ]
        mindv = [np.min(dvfld.get()) for dvfld in dv]
        maxdv = [np.max(dvfld.get()) for dvfld in dv]

        if write_status is True:
            statusmsg = (f"Status: Step({istep}) Time({t})\n"
                         f"------   P({mindv[0]},{maxdv[0]})\n"
                         f"------   T({mindv[1]},{maxdv[1]})\n"
                         f"------   dt,cfl = ({dt},{cfl})\n"
                         f"------   Err({maxerr})")
            logger.info(statusmsg)

        io_fields = ["cv", split_conserved(dim, fields)]
        io_fields += eos.split_fields(dim, dv)
        io_fields.append(("exact_soln", expected_result))
        io_fields.append(("residual", result_resid))
        nameform = casename + "-{iorank:04d}-{iostep:06d}.vtu"
        visfilename = nameform.format(iorank=rank, iostep=istep)
        vis.write_vtk_file(visfilename, io_fields)

        return maxerr
Exemplo n.º 2
0
    def my_checkpoint(step, t, dt, state):

        write_restart = (check_step(step, nrestart)
                         if step != restart_step else False)
        if write_restart is True:
            with open(snapshot_pattern.format(step=step, rank=rank), "wb") as f:
                pickle.dump({
                    "local_mesh": local_mesh,
                    "state": obj_array_vectorize(actx.to_numpy, flatten(state)),
                    "t": t,
                    "step": step,
                    "global_nelements": global_nelements,
                    "num_parts": nparts,
                    }, f)

        cv = split_conserved(dim, state)
        tagged_cells = smoothness_indicator(discr, cv.mass, s0=s0_sc, kappa=kappa_sc)

        viz_fields = [("sponge_sigma", gen_sponge()),("tagged cells", tagged_cells)]
        return sim_checkpoint(discr=discr, visualizer=visualizer, eos=eos,
                              q=state, vizname=casename,
                              step=step, t=t, dt=dt, nstatus=nstatus,
                              nviz=nviz, exittol=exittol,
                              constant_cfl=constant_cfl, comm=comm, vis_timer=vis_timer,
                              overwrite=True,s0=s0_sc,kappa=kappa_sc,
                              viz_fields=viz_fields)
Exemplo n.º 3
0
def sim_checkpoint(discr, visualizer, eos, q, vizname, exact_soln=None,
                   step=0, t=0, dt=0, cfl=1.0, nstatus=-1, nviz=-1, exittol=1e-16,
                   constant_cfl=False, comm=None, overwrite=False):
    """Check simulation health, status, viz dumps, and restart."""
    # TODO: Add restart
    do_viz = check_step(step=step, interval=nviz)
    do_status = check_step(step=step, interval=nstatus)
    if do_viz is False and do_status is False:
        return 0

    from mirgecom.euler import split_conserved
    cv = split_conserved(discr.dim, q)
    dependent_vars = eos.dependent_vars(cv)

    rank = 0
    if comm is not None:
        rank = comm.Get_rank()

    maxerr = 0.0
    if exact_soln is not None:
        actx = cv.mass.array_context
        nodes = thaw(actx, discr.nodes())
        expected_state = exact_soln(t=t, x_vec=nodes, eos=eos)
        exp_resid = q - expected_state
        err_norms = [discr.norm(v, np.inf) for v in exp_resid]
        maxerr = max(err_norms)

    if do_viz:
        io_fields = [
            ("cv", cv),
            ("dv", dependent_vars)
        ]
        if exact_soln is not None:
            exact_list = [
                ("exact_soln", expected_state),
            ]
            io_fields.extend(exact_list)

        from mirgecom.io import make_rank_fname, make_par_fname
        rank_fn = make_rank_fname(basename=vizname, rank=rank, step=step, t=t)
        visualizer.write_parallel_vtk_file(
            comm, rank_fn, io_fields, overwrite=overwrite,
            par_manifest_filename=make_par_fname(basename=vizname, step=step, t=t))

    if do_status is True:
        #        if constant_cfl is False:
        #            current_cfl = get_inviscid_cfl(discr=discr, q=q,
        #                                           eos=eos, dt=dt)
        statusmesg = make_status_message(discr=discr, t=t, step=step, dt=dt,
                                         cfl=cfl, dependent_vars=dependent_vars)
        if exact_soln is not None:
            statusmesg += (
                "\n------- errors="
                + ", ".join("%.3g" % en for en in err_norms))

        if rank == 0:
            logger.info(statusmesg)

    if maxerr > exittol:
        raise ExactSolutionMismatch(step, t=t, state=q)
Exemplo n.º 4
0
    def my_rhs(t, state):
        # check for some troublesome output types
        inf_exists = not np.isfinite(discr.norm(state, np.inf))
        if inf_exists:
            if rank == 0:
                logging.info(
                    "Non-finite values detected in simulation, exiting...")
            # dump right now
            sim_checkpoint(discr=discr,
                           visualizer=visualizer,
                           eos=eos,
                           q=state,
                           vizname=casename,
                           step=999999999,
                           t=t,
                           dt=current_dt,
                           nviz=1,
                           exittol=exittol,
                           constant_cfl=constant_cfl,
                           comm=comm,
                           vis_timer=vis_timer,
                           overwrite=True,
                           s0=s0_sc,
                           kappa=kappa_sc)
            exit()

        cv = split_conserved(dim=dim, q=state)
        return (inviscid_operator(
            discr, q=state, t=t, boundaries=boundaries, eos=eos) +
                eos.get_species_source_terms(cv))
Exemplo n.º 5
0
def test_inviscid_flux(actx_factory, dim):
    """Identity test - directly check inviscid flux
    routine :func:`mirgecom.euler.inviscid_flux` against the exact
    expected result. This test is designed to fail
    if the flux routine is broken.
    The expected inviscid flux is:
      F(q) = <rhoV, (E+p)V, rho(V.x.V) + pI>
    """
    actx = actx_factory()

    nel_1d = 16

    from meshmode.mesh.generation import generate_regular_rect_mesh

    #    for dim in [1, 2, 3]:
    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                      b=(0.5, ) * dim,
                                      n=(nel_1d, ) * dim)

    order = 3
    discr = EagerDGDiscretization(actx, mesh, order=order)
    eos = IdealSingleGas()

    logger.info(f"Number of {dim}d elems: {mesh.nelements}")

    mass = cl.clrandom.rand(actx.queue, (mesh.nelements, ), dtype=np.float64)
    energy = cl.clrandom.rand(actx.queue, (mesh.nelements, ), dtype=np.float64)
    mom = make_obj_array([
        cl.clrandom.rand(actx.queue, (mesh.nelements, ), dtype=np.float64)
        for i in range(dim)
    ])

    q = join_conserved(dim, mass=mass, energy=energy, momentum=mom)
    cv = split_conserved(dim, q)

    # {{{ create the expected result

    p = eos.pressure(cv)
    escale = (energy + p) / mass

    expected_flux = np.zeros((dim + 2, dim), dtype=object)
    expected_flux[0] = mom
    expected_flux[1] = mom * make_obj_array([escale])

    for i in range(dim):
        for j in range(dim):
            expected_flux[2 + i,
                          j] = (mom[i] * mom[j] / mass + (p if i == j else 0))

    # }}}

    from mirgecom.euler import inviscid_flux

    flux = inviscid_flux(discr, eos, q)
    flux_resid = flux - expected_flux

    for i in range(dim + 2, dim):
        for j in range(dim):
            assert (la.norm(flux_resid[i, j].get())) == 0.0
Exemplo n.º 6
0
def test_uniform(ctx_factory, dim):
    """
    Simple test to check that Uniform initializer
    creates the expected solution field.
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    nel_1d = 2

    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                      b=(0.5, ) * dim,
                                      n=(nel_1d, ) * dim)

    order = 1
    print(f"Number of elements: {mesh.nelements}")

    discr = EagerDGDiscretization(actx, mesh, order=order)
    nodes = thaw(actx, discr.nodes())
    print(f"DIM = {dim}, {len(nodes)}")
    print(f"Nodes={nodes}")

    from mirgecom.initializers import Uniform
    initr = Uniform(numdim=dim)
    initsoln = initr(t=0.0, x_vec=nodes)
    tol = 1e-15
    ssoln = split_conserved(dim, initsoln)

    assert discr.norm(ssoln.mass - 1.0, np.inf) < tol
    assert discr.norm(ssoln.energy - 2.5, np.inf) < tol

    print(f"Uniform Soln:{initsoln}")
    eos = IdealSingleGas()
    cv = split_conserved(dim, initsoln)
    p = eos.pressure(cv)
    print(f"Press:{p}")

    assert discr.norm(p - 1.0, np.inf) < tol
Exemplo n.º 7
0
def test_idealsingle_lump(ctx_factory):
    """Test EOS with mass lump.

    Tests that the IdealSingleGas EOS returns
    the correct (uniform) pressure for the Lump
    solution field.
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    dim = 2
    nel_1d = 4

    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=[(0.0, ), (-5.0, )],
                                      b=[(10.0, ), (5.0, )],
                                      n=(nel_1d, ) * dim)

    order = 3
    logger.info(f"Number of elements {mesh.nelements}")

    discr = EagerDGDiscretization(actx, mesh, order=order)
    nodes = thaw(actx, discr.nodes())

    # Init soln with Vortex
    center = np.zeros(shape=(dim, ))
    velocity = np.zeros(shape=(dim, ))
    center[0] = 5
    velocity[0] = 1
    lump = Lump(center=center, velocity=velocity)
    eos = IdealSingleGas()
    lump_soln = lump(0, nodes)

    cv = split_conserved(dim, lump_soln)
    p = eos.pressure(cv)
    exp_p = 1.0
    errmax = discr.norm(p - exp_p, np.inf)

    exp_ke = 0.5 * cv.mass
    ke = eos.kinetic_energy(cv)
    kerr = discr.norm(ke - exp_ke, np.inf)

    te = eos.total_energy(cv, p)
    terr = discr.norm(te - cv.energy, np.inf)

    logger.info(f"lump_soln = {lump_soln}")
    logger.info(f"pressure = {p}")

    assert errmax < 1e-15
    assert kerr < 1e-15
    assert terr < 1e-15
Exemplo n.º 8
0
    def boundary_pair(self, discr, q, btag, eos, t=0.0):
        """Get the interior and exterior solution on the boundary.

        The exterior solution is set such that there will be vanishing
        flux through the boundary, preserving mass, momentum (magnitude) and
        energy.
        rho_plus = rho_minus
        v_plus = v_minus - 2 * (v_minus . n_hat) * n_hat
        mom_plus = rho_plus * v_plus
        E_plus = E_minus
        """
        # Grab some boundary-relevant data
        dim = discr.dim
        cv = split_conserved(dim, q)
        actx = cv.mass.array_context

        # Grab a unit normal to the boundary
        nhat = thaw(actx, discr.normal(btag))

        # Get the interior/exterior solns
        int_soln = discr.project("vol", btag, q)
        int_cv = split_conserved(dim, int_soln)

        # Subtract out the 2*wall-normal component
        # of velocity from the velocity at the wall to
        # induce an equal but opposite wall-normal (reflected) wave
        # preserving the tangential component
        mom_normcomp = np.dot(int_cv.momentum, nhat)  # wall-normal component
        wnorm_mom = nhat * mom_normcomp  # wall-normal mom vec
        ext_mom = int_cv.momentum - 2.0 * wnorm_mom  # prescribed ext momentum

        # Form the external boundary solution with the new momentum
        bndry_soln = join_conserved(dim=dim,
                                    mass=int_cv.mass,
                                    energy=int_cv.energy,
                                    momentum=ext_mom)

        return TracePair(btag, interior=int_soln, exterior=bndry_soln)
Exemplo n.º 9
0
def test_idealsingle_vortex(ctx_factory):
    r"""Test EOS with isentropic vortex.

    Tests that the IdealSingleGas EOS returns
    the correct pressure (p) for the Vortex2D solution
    field (i.e. $p = \rho^{\gamma}$).
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    dim = 2
    nel_1d = 4

    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=[(0.0, ), (-5.0, )],
                                      b=[(10.0, ), (5.0, )],
                                      n=(nel_1d, ) * dim)

    order = 3
    logger.info(f"Number of elements {mesh.nelements}")

    discr = EagerDGDiscretization(actx, mesh, order=order)
    nodes = thaw(actx, discr.nodes())
    eos = IdealSingleGas()
    # Init soln with Vortex
    vortex = Vortex2D()
    vortex_soln = vortex(0, nodes)
    cv = split_conserved(dim, vortex_soln)
    gamma = eos.gamma()
    p = eos.pressure(cv)
    exp_p = cv.mass**gamma
    errmax = discr.norm(p - exp_p, np.inf)

    exp_ke = 0.5 * np.dot(cv.momentum, cv.momentum) / cv.mass
    ke = eos.kinetic_energy(cv)
    kerr = discr.norm(ke - exp_ke, np.inf)

    te = eos.total_energy(cv, p)
    terr = discr.norm(te - cv.energy, np.inf)

    logger.info(f"vortex_soln = {vortex_soln}")
    logger.info(f"pressure = {p}")

    assert errmax < 1e-15
    assert kerr < 1e-15
    assert terr < 1e-15
Exemplo n.º 10
0
    def __call__(self, x_vec, q, eos=IdealSingleGas()):
        """
        Create the acoustic pulse at locations *x_vec*.

        Parameters
        ----------
        t: float
            Current time at which the solution is desired (unused)
        x_vec: numpy.ndarray
            Nodal coordinates
        eos: :class:`mirgecom.eos.GasEOS`
            Equation of state class to be used in construction of soln (unused)
        """
        assert len(x_vec) == self._dim
        cv = split_conserved(self._dim, q)
        return cv.replace(
            energy=cv.energy + _make_pulse(
                amp=self._amp, w=self._width, r0=self._center, r=x_vec)
            ).join()
Exemplo n.º 11
0
def test_lump_init(ctx_factory):
    """
    Simple test to check that Lump initializer
    creates the expected solution field.
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)
    dim = 2
    nel_1d = 4

    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=[(0.0, ), (-5.0, )],
                                      b=[(10.0, ), (5.0, )],
                                      n=(nel_1d, ) * dim)

    order = 3
    logger.info(f"Number of elements: {mesh.nelements}")

    discr = EagerDGDiscretization(actx, mesh, order=order)
    nodes = thaw(actx, discr.nodes())

    # Init soln with Vortex
    center = np.zeros(shape=(dim, ))
    velocity = np.zeros(shape=(dim, ))
    center[0] = 5
    velocity[0] = 1
    lump = Lump(center=center, velocity=velocity)
    lump_soln = lump(0, nodes)

    cv = split_conserved(dim, lump_soln)
    p = 0.4 * (cv.energy - 0.5 * np.dot(cv.momentum, cv.momentum) / cv.mass)
    exp_p = 1.0
    errmax = discr.norm(p - exp_p, np.inf)

    logger.info(f"lump_soln = {lump_soln}")
    logger.info(f"pressure = {p}")

    assert errmax < 1e-15
Exemplo n.º 12
0
    def my_checkpoint(step, t, dt, state):

        write_restart = (check_step(step, nrestart)
                         if step != restart_step else False)
        if write_restart is True:
            with open(snapshot_pattern.format(step=step, rank=rank),
                      "wb") as f:
                pickle.dump(
                    {
                        "local_mesh": local_mesh,
                        "state": obj_array_vectorize(actx.to_numpy,
                                                     flatten(state)),
                        "t": t,
                        "step": step,
                        "global_nelements": global_nelements,
                        "num_parts": nparts,
                    }, f)

        cv = split_conserved(dim, state)
        reaction_rates = eos.get_production_rates(cv)
        viz_fields = [("reaction_rates", reaction_rates)]

        return sim_checkpoint(discr=discr,
                              visualizer=visualizer,
                              eos=eos,
                              q=state,
                              vizname=casename,
                              step=step,
                              t=t,
                              dt=dt,
                              nstatus=nstatus,
                              nviz=nviz,
                              exittol=exittol,
                              constant_cfl=constant_cfl,
                              comm=comm,
                              vis_timer=vis_timer,
                              overwrite=True,
                              viz_fields=viz_fields)
Exemplo n.º 13
0
def test_shock_init(ctx_factory):
    """
    Simple test to check that Shock1D initializer
    creates the expected solution field.
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    nel_1d = 10
    dim = 2

    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=[(0.0, ), (1.0, )],
                                      b=[(-0.5, ), (0.5, )],
                                      n=(nel_1d, ) * dim)

    order = 3
    print(f"Number of elements: {mesh.nelements}")

    discr = EagerDGDiscretization(actx, mesh, order=order)
    nodes = thaw(actx, discr.nodes())

    initr = SodShock1D()
    initsoln = initr(t=0.0, x_vec=nodes)
    print("Sod Soln:", initsoln)
    xpl = 1.0
    xpr = 0.1
    tol = 1e-15
    nodes_x = nodes[0]
    eos = IdealSingleGas()
    cv = split_conserved(dim, initsoln)
    p = eos.pressure(cv)

    assert discr.norm(actx.np.where(nodes_x < 0.5, p - xpl, p - xpr),
                      np.inf) < tol
Exemplo n.º 14
0
def test_vortex_init(ctx_factory):
    """
    Simple test to check that Vortex2D initializer
    creates the expected solution field.
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)
    dim = 2
    nel_1d = 4

    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=[(0.0, ), (-5.0, )],
                                      b=[(10.0, ), (5.0, )],
                                      n=(nel_1d, ) * dim)

    order = 3
    logger.info(f"Number of elements: {mesh.nelements}")

    discr = EagerDGDiscretization(actx, mesh, order=order)
    nodes = thaw(actx, discr.nodes())

    # Init soln with Vortex
    vortex = Vortex2D()
    vortex_soln = vortex(0, nodes)
    gamma = 1.4
    cv = split_conserved(dim, vortex_soln)
    p = 0.4 * (cv.energy - 0.5 * np.dot(cv.momentum, cv.momentum) / cv.mass)
    exp_p = cv.mass**gamma
    errmax = discr.norm(p - exp_p, np.inf)

    logger.info(f"vortex_soln = {vortex_soln}")
    logger.info(f"pressure = {p}")

    assert errmax < 1e-15
Exemplo n.º 15
0
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, n=(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))
    #    normal_mag = actx.np.sqrt(np.dot(normal, normal))
    #    nhat_mult = 1.0 / normal_mag
    #    nhat = normal * make_obj_array([nhat_mult])

    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(center=orig, velocity=vel, rhoamp=0.0)
            wall = AdiabaticSlipBoundary()

            uniform_state = initializer(0, nodes)
            from functools import partial
            bnd_norm = partial(discr.norm, p=np.inf, dd=BTAG_ALL)

            bnd_pair = wall.boundary_pair(discr, uniform_state, t=0.0,
                                          btag=BTAG_ALL, eos=eos)
            bnd_cv_int = split_conserved(dim, bnd_pair.int)
            bnd_cv_ext = split_conserved(dim, bnd_pair.ext)

            # check that mass and energy are preserved
            mass_resid = bnd_cv_int.mass - bnd_cv_ext.mass
            mass_err = bnd_norm(mass_resid)
            assert mass_err == 0.0
            energy_resid = bnd_cv_int.energy - bnd_cv_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_cv_int.momentum, nhat)
            mom_norm = nhat * mom_norm_comp
            expected_mom_ext = bnd_cv_int.momentum - 2.0 * mom_norm
            mom_resid = bnd_cv_ext.momentum - expected_mom_ext
            mom_err = bnd_norm(mom_resid)

            assert mom_err == 0.0
Exemplo n.º 16
0
def test_uniform_rhs(actx_factory, dim, order):
    """Tests the inviscid rhs using a trivial
    constant/uniform state which should
    yield rhs = 0 to FP.  The test is performed
    for 1, 2, and 3 dimensions.
    """
    actx = actx_factory()

    tolerance = 1e-9
    maxxerr = 0.0

    from pytools.convergence import EOCRecorder
    eoc_rec0 = EOCRecorder()
    eoc_rec1 = EOCRecorder()
    # for nel_1d in [4, 8, 12]:
    for nel_1d in [4, 8]:
        from meshmode.mesh.generation import generate_regular_rect_mesh
        mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                          b=(0.5, ) * dim,
                                          n=(nel_1d, ) * dim)

        logger.info(f"Number of {dim}d elements: {mesh.nelements}")

        discr = EagerDGDiscretization(actx, mesh, order=order)

        mass_input = discr.zeros(actx) + 1
        energy_input = discr.zeros(actx) + 2.5

        mom_input = make_obj_array(
            [discr.zeros(actx) for i in range(discr.dim)])
        fields = join_conserved(dim,
                                mass=mass_input,
                                energy=energy_input,
                                momentum=mom_input)

        expected_rhs = make_obj_array(
            [discr.zeros(actx) for i in range(len(fields))])

        boundaries = {BTAG_ALL: DummyBoundary()}
        inviscid_rhs = inviscid_operator(discr,
                                         eos=IdealSingleGas(),
                                         boundaries=boundaries,
                                         q=fields,
                                         t=0.0)
        rhs_resid = inviscid_rhs - expected_rhs

        resid_split = split_conserved(dim, rhs_resid)
        rho_resid = resid_split.mass
        rhoe_resid = resid_split.energy
        mom_resid = resid_split.momentum

        rhs_split = split_conserved(dim, inviscid_rhs)
        rho_rhs = rhs_split.mass
        rhoe_rhs = rhs_split.energy
        rhov_rhs = rhs_split.momentum

        message = (f"rho_rhs  = {rho_rhs}\n"
                   f"rhoe_rhs = {rhoe_rhs}\n"
                   f"rhov_rhs = {rhov_rhs}")
        logger.info(message)

        assert discr.norm(rho_resid, np.inf) < tolerance
        assert discr.norm(rhoe_resid, np.inf) < tolerance
        for i in range(dim):
            assert discr.norm(mom_resid[i], np.inf) < tolerance

            err_max = discr.norm(rhs_resid[i], np.inf)
            eoc_rec0.add_data_point(1.0 / nel_1d, err_max)
            assert (err_max < tolerance)
            if err_max > maxxerr:
                maxxerr = err_max
        # set a non-zero, but uniform velocity component

        for i in range(len(mom_input)):
            mom_input[i] = discr.zeros(actx) + (-1.0)**i

        boundaries = {BTAG_ALL: DummyBoundary()}
        inviscid_rhs = inviscid_operator(discr,
                                         eos=IdealSingleGas(),
                                         boundaries=boundaries,
                                         q=fields,
                                         t=0.0)
        rhs_resid = inviscid_rhs - expected_rhs

        resid_split = split_conserved(dim, rhs_resid)
        rho_resid = resid_split.mass
        rhoe_resid = resid_split.energy
        mom_resid = resid_split.momentum

        assert discr.norm(rho_resid, np.inf) < tolerance
        assert discr.norm(rhoe_resid, np.inf) < tolerance

        for i in range(dim):
            assert discr.norm(mom_resid[i], np.inf) < tolerance
            err_max = discr.norm(rhs_resid[i], np.inf)
            eoc_rec1.add_data_point(1.0 / nel_1d, err_max)
            assert (err_max < tolerance)
            if err_max > maxxerr:
                maxxerr = err_max

    message = (f"V == 0 Errors:\n{eoc_rec0}" f"V != 0 Errors:\n{eoc_rec1}")
    print(message)

    assert (eoc_rec0.order_estimate() >= order - 0.5
            or eoc_rec0.max_error() < 1e-9)
    assert (eoc_rec1.order_estimate() >= order - 0.5
            or eoc_rec1.max_error() < 1e-9)
Exemplo n.º 17
0
def test_facial_flux(actx_factory, order, dim):
    """Check the flux across element faces by
    prescribing states (q) with known fluxes. Only
    uniform states are tested currently - ensuring
    that the Lax-Friedrichs flux terms which are
    proportional to jumps in state data vanish.

    Since the returned fluxes use state data which
    has been interpolated to-and-from the element
    faces, this test is grid-dependent.
    """
    actx = actx_factory()

    tolerance = 1e-14
    p0 = 1.0

    from meshmode.mesh.generation import generate_regular_rect_mesh
    from pytools.convergence import EOCRecorder

    eoc_rec0 = EOCRecorder()
    eoc_rec1 = EOCRecorder()
    for nel_1d in [4, 8, 12]:

        mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                          b=(0.5, ) * dim,
                                          n=(nel_1d, ) * dim)

        logger.info(f"Number of elements: {mesh.nelements}")

        discr = EagerDGDiscretization(actx, mesh, order=order)

        mass_input = discr.zeros(actx) + 1.0
        energy_input = discr.zeros(actx) + 2.5
        mom_input = flat_obj_array(
            [discr.zeros(actx) for i in range(discr.dim)])

        fields = join_conserved(dim,
                                mass=mass_input,
                                energy=energy_input,
                                momentum=mom_input)

        from mirgecom.euler import _facial_flux

        interior_face_flux = _facial_flux(discr,
                                          eos=IdealSingleGas(),
                                          q_tpair=interior_trace_pair(
                                              discr, fields))

        from functools import partial
        fnorm = partial(discr.norm, p=np.inf, dd="all_faces")

        iff_split = split_conserved(dim, interior_face_flux)
        assert fnorm(iff_split.mass) < tolerance
        assert fnorm(iff_split.energy) < tolerance

        # The expected pressure 1.0 (by design). And the flux diagonal is
        # [rhov_x*v_x + p] (etc) since we have zero velocities it's just p.
        #
        # The off-diagonals are zero. We get a {ndim}-vector for each
        # dimension, the flux for the x-component of momentum (for example) is:
        # f_momx = < 1.0, 0 , 0> , then we return f_momx .dot. normal, which
        # can introduce negative values.
        #
        # (Explanation courtesy of Mike Campbell,
        # https://github.com/illinois-ceesd/mirgecom/pull/44#discussion_r463304292)

        momerr = fnorm(iff_split.momentum) - p0
        assert momerr < tolerance

        eoc_rec0.add_data_point(1.0 / nel_1d, momerr)

        # Check the boundary facial fluxes as called on a boundary
        dir_mass = discr.project("vol", BTAG_ALL, mass_input)
        dir_e = discr.project("vol", BTAG_ALL, energy_input)
        dir_mom = discr.project("vol", BTAG_ALL, mom_input)

        dir_bval = join_conserved(dim,
                                  mass=dir_mass,
                                  energy=dir_e,
                                  momentum=dir_mom)
        dir_bc = join_conserved(dim,
                                mass=dir_mass,
                                energy=dir_e,
                                momentum=dir_mom)

        boundary_flux = _facial_flux(discr,
                                     eos=IdealSingleGas(),
                                     q_tpair=TracePair(BTAG_ALL,
                                                       interior=dir_bval,
                                                       exterior=dir_bc))

        bf_split = split_conserved(dim, boundary_flux)
        assert fnorm(bf_split.mass) < tolerance
        assert fnorm(bf_split.energy) < tolerance

        momerr = fnorm(bf_split.momentum) - p0
        assert momerr < tolerance

        eoc_rec1.add_data_point(1.0 / nel_1d, momerr)

    message = (f"standalone Errors:\n{eoc_rec0}"
               f"boundary Errors:\n{eoc_rec1}")
    logger.info(message)
    assert (eoc_rec0.order_estimate() >= order - 0.5
            or eoc_rec0.max_error() < 1e-9)
    assert (eoc_rec1.order_estimate() >= order - 0.5
            or eoc_rec1.max_error() < 1e-9)
Exemplo n.º 18
0
def test_inviscid_mom_flux_components(actx_factory, dim, livedim):
    r"""Constant pressure, V != 0:
    Checks that the flux terms are returned in the proper
    order by running only 1 non-zero velocity component at-a-time.
    """
    actx = actx_factory()

    eos = IdealSingleGas()

    p0 = 1.0

    from mirgecom.euler import inviscid_flux

    tolerance = 1e-15
    for livedim in range(dim):
        for ntestnodes in [1, 10]:
            discr = MyDiscr(dim, ntestnodes)
            mass = discr.zeros(actx)
            mass_values = np.empty((1, ntestnodes), dtype=np.float64)
            mass_values[0] = np.linspace(1.,
                                         ntestnodes,
                                         ntestnodes,
                                         dtype=np.float64)
            mass[0].set(mass_values)
            mom = make_obj_array([discr.zeros(actx) for _ in range(dim)])
            mom[livedim] = mass
            p = discr.zeros(actx) + p0
            energy = (p / (eos.gamma() - 1.0) + 0.5 * np.dot(mom, mom) / mass)
            q = join_conserved(dim, mass=mass, energy=energy, momentum=mom)
            cv = split_conserved(dim, q)
            p = eos.pressure(cv)

            flux = inviscid_flux(discr, eos, q)

            logger.info(f"{dim}d flux = {flux}")

            # first two components should be nonzero in livedim only
            expected_flux = mom
            logger.info("Testing continuity")
            for i in range(dim):
                assert la.norm((flux[0, i] - expected_flux[i])[0].get()) == 0.0
                if i != livedim:
                    assert la.norm(flux[0, i][0].get()) == 0.0
                else:
                    assert la.norm(flux[0, i][0].get()) > 0.0

            logger.info("Testing energy")
            expected_flux = mom * (energy + p) / mass
            for i in range(dim):
                assert la.norm((flux[1, i] - expected_flux[i])[0].get()) == 0.0
                if i != livedim:
                    assert la.norm(flux[1, i][0].get()) == 0.0
                else:
                    assert la.norm(flux[1, i][0].get()) > 0.0

            logger.info("Testing momentum")
            xpmomflux = make_obj_array([
                (mom[i] * mom[j] / mass + (p if i == j else 0))
                for i in range(dim) for j in range(dim)
            ])

            for i in range(dim):
                expected_flux = xpmomflux[i * dim:(i + 1) * dim]
                for j in range(dim):
                    assert la.norm(
                        (flux[2 + i, j] - expected_flux[j])[0].get()) == 0
                    if i == j:
                        if i == livedim:
                            assert (la.norm(flux[2 + i, j][0].get()) > 0.0)
                        else:
                            # just for sanity - make sure the flux recovered the
                            # prescribed value of p0 (within fp tol)
                            assert (np.abs(flux[2 + i, j][0].get() - p0) <
                                    tolerance).all()
                    else:
                        assert la.norm(flux[2 + i, j][0].get()) == 0.0
Exemplo n.º 19
0
def test_inviscid_flux_components(actx_factory, dim):
    """Uniform pressure test

    Checks that the Euler-internal inviscid flux
    routine :func:`mirgecom.euler.inviscid_flux` returns exactly the
    expected result with a constant pressure and
    no flow.
    Expected inviscid flux is:
      F(q) = <rhoV, (E+p)V, rho(V.x.V) + pI>

    Checks that only diagonal terms of the momentum flux:
      [ rho(V.x.V) + pI ]
    are non-zero and return the correctly calculated p.
    """
    actx = actx_factory()

    eos = IdealSingleGas()

    from mirgecom.euler import inviscid_flux

    p0 = 1.0

    # === this next block tests 1,2,3 dimensions,
    # with single and multiple nodes/states. The
    # purpose of this block is to ensure that when
    # all components of V = 0, the flux recovers
    # the expected values (and p0 within tolerance)
    # === with V = 0, fixed P = p0
    tolerance = 1e-15
    for ntestnodes in [1, 10]:
        discr = MyDiscr(dim, ntestnodes)
        mass = discr.zeros(actx)
        mass_values = np.empty((1, ntestnodes), dtype=np.float64)
        mass_values[0] = np.linspace(1.,
                                     ntestnodes,
                                     ntestnodes,
                                     dtype=np.float64)
        mass[0].set(mass_values)
        mom = make_obj_array([discr.zeros(actx) for _ in range(dim)])
        p = discr.zeros(actx) + p0
        energy = p / 0.4 + 0.5 * np.dot(mom, mom) / mass
        q = join_conserved(dim, mass=mass, energy=energy, momentum=mom)
        cv = split_conserved(dim, q)
        p = eos.pressure(cv)
        flux = inviscid_flux(discr, eos, q)

        logger.info(f"{dim}d flux = {flux}")

        # for velocity zero, these components should be == zero
        for i in range(2):
            for j in range(dim):
                assert (flux[i, j][0].get() == 0.0).all()

        # The momentum diagonal should be p
        # Off-diagonal should be identically 0
        for i in range(dim):
            for j in range(dim):
                print(f"(i,j) = ({i},{j})")
                if i != j:
                    assert (flux[2 + i, j][0].get() == 0.0).all()
                else:
                    assert (flux[2 + i, j] == p)[0].get().all()
                    assert (np.abs(flux[2 + i, j][0].get() - p0) <
                            tolerance).all()
Exemplo n.º 20
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()

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for np1 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, n=(np1,) * dim
        )

        discr = EagerDGDiscretization(actx, mesh, order=order)
        nodes = thaw(actx, discr.nodes())
        nhat = thaw(actx, discr.normal(BTAG_ALL))
        h = 1.0 / np1

        from functools import partial
        bnd_norm = partial(discr.norm, 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(numdim=dim, velocity=vel)
                uniform_state = initializer(0, nodes)
                bnd_pair = wall.boundary_pair(discr, uniform_state, t=0.0,
                                              btag=BTAG_ALL, eos=eos)

                # 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)
                acv = split_conserved(dim, avg_state)
                err_max = max(err_max, bnd_norm(np.dot(acv.momentum, nhat)))

                from mirgecom.euler import _facial_flux
                bnd_flux = split_conserved(dim, _facial_flux(discr, eos,
                                                             bnd_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
    )
Exemplo n.º 21
0
def test_inviscid_mom_flux_components(actx_factory, dim, livedim):
    r"""Constant pressure, V != 0:
    Checks that the flux terms are returned in the proper
    order by running only 1 non-zero velocity component at-a-time.
    """

    queue = actx_factory().queue

    eos = IdealSingleGas()

    class MyDiscr:
        def __init__(self, dim=1):
            self.dim = dim

    p0 = 1.0

    from mirgecom.euler import inviscid_flux

    tolerance = 1e-15
    for livedim in range(dim):
        for ntestnodes in [1, 10]:
            fake_dis = MyDiscr(dim)
            mass = cl.clrandom.rand(queue, (ntestnodes, ), dtype=np.float64)
            energy = cl.clrandom.rand(queue, (ntestnodes, ), dtype=np.float64)
            mom = make_obj_array([
                cl.clrandom.rand(queue, (ntestnodes, ), dtype=np.float64)
                for i in range(dim)
            ])
            p = cl.clrandom.rand(queue, (ntestnodes, ), dtype=np.float64)

            for i in range(ntestnodes):
                mass[i] = 1.0 + i
                p[i] = p0
                for j in range(dim):
                    mom[j][i] = 0.0 * mass[i]
                    mom[livedim][i] = mass[i]
            energy = (p / (eos.gamma() - 1.0) + 0.5 * np.dot(mom, mom) / mass)
            q = join_conserved(dim, mass=mass, energy=energy, momentum=mom)
            cv = split_conserved(dim, q)
            p = eos.pressure(cv)

            flux = inviscid_flux(fake_dis, eos, q)

            logger.info(f"{dim}d flux = {flux}")

            # first two components should be nonzero in livedim only
            expected_flux = mom
            logger.info("Testing continuity")
            for i in range(dim):
                assert la.norm((flux[0, i] - expected_flux[i]).get()) == 0.0
                if i != livedim:
                    assert la.norm(flux[0, i].get()) == 0.0
                else:
                    assert la.norm(flux[0, i].get()) > 0.0

            logger.info("Testing energy")
            expected_flux = mom * make_obj_array([(energy + p) / mass])
            for i in range(dim):
                assert la.norm((flux[1, i] - expected_flux[i]).get()) == 0.0
                if i != livedim:
                    assert la.norm(flux[1, i].get()) == 0.0
                else:
                    assert la.norm(flux[1, i].get()) > 0.0

            logger.info("Testing momentum")
            xpmomflux = make_obj_array([
                (mom[i] * mom[j] / mass + (p if i == j else 0))
                for i in range(dim) for j in range(dim)
            ])

            for i in range(dim):
                expected_flux = xpmomflux[i * dim:(i + 1) * dim]
                for j in range(dim):
                    assert la.norm(
                        (flux[2 + i, j] - expected_flux[j]).get()) == 0
                    if i == j:
                        if i == livedim:
                            assert (la.norm(flux[2 + i, j].get()) > 0.0)
                        else:
                            # just for sanity - make sure the flux recovered the
                            # prescribed value of p0 (within fp tol)
                            for k in range(ntestnodes):
                                assert np.abs(flux[2 + i, j][k] -
                                              p0) < tolerance
                    else:
                        assert la.norm(flux[2 + i, j].get()) == 0.0