Пример #1
0
 def quadrature_rule(self):
     dims = self.mesh_el_group.dim
     if dims == 0:
         return mp.ZeroDimensionalQuadrature()
     elif dims == 1:
         return mp.LegendreGaussQuadrature(self.order)
     else:
         return mp.VioreanuRokhlinSimplexQuadrature(self.order, dims)
Пример #2
0
 def _quadrature_rule(self):
     dims = self.mesh_el_group.dim
     if dims == 0:
         return mp.Quadrature(np.empty((0, 1)), np.empty((0, 1)))
     elif dims == 1:
         return mp.LegendreGaussQuadrature(self.order)
     else:
         return mp.VioreanuRokhlinSimplexQuadrature(self.order, dims)
Пример #3
0
def test_mesh_with_interior_unit_nodes(actx_factory, ambient_dim):
    actx = actx_factory()

    # NOTE: smaller orders or coarser meshes make the cases fail the
    # node_vertex_consistency test; the default warp_and_blend_nodes have
    # nodes at the vertices, so they pass for much smaller tolerances

    order = 8
    nelements = 32
    n_minor = 2 * nelements
    uniform_refinement_rounds = 4

    import modepy as mp
    if ambient_dim == 2:
        unit_nodes = mp.LegendreGaussQuadrature(order,
                                                force_dim_axis=True).nodes

        mesh = mgen.make_curve_mesh(partial(mgen.ellipse, 2.0),
                                    np.linspace(0.0, 1.0, nelements + 1),
                                    order=order,
                                    unit_nodes=unit_nodes)
    elif ambient_dim == 3:
        unit_nodes = mp.VioreanuRokhlinSimplexQuadrature(order, 2).nodes

        mesh = mgen.generate_torus(4.0,
                                   2.0,
                                   n_major=2 * n_minor,
                                   n_minor=n_minor,
                                   order=order,
                                   unit_nodes=unit_nodes)

        mesh = mgen.generate_icosphere(
            1.0,
            uniform_refinement_rounds=uniform_refinement_rounds,
            order=order,
            unit_nodes=unit_nodes)
    else:
        raise ValueError(f"unsupported dimension: '{ambient_dim}'")

    assert mesh.facial_adjacency_groups
    assert mesh.nodal_adjacency

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory
    discr = Discretization(actx, mesh, QuadratureSimplexGroupFactory(order))

    from meshmode.discretization.connection import make_face_restriction
    conn = make_face_restriction(
        actx,
        discr,
        group_factory=QuadratureSimplexGroupFactory(order),
        boundary_tag=FACE_RESTR_ALL)
    assert conn
Пример #4
0
def run(actx, *,
        ambient_dim: int = 3,
        resolution: int = None,
        target_order: int = 4,
        tmax: float = 1.0,
        timestep: float = 1.0e-2,
        group_factory_name: str = "warp_and_blend",
        visualize: bool = True):
    if ambient_dim not in (2, 3):
        raise ValueError(f"unsupported dimension: {ambient_dim}")

    mesh_order = target_order
    radius = 1.0

    # {{{ geometry

    # {{{ element groups

    import modepy as mp
    import meshmode.discretization.poly_element as poly

    # NOTE: picking the same unit nodes for the mesh and the discr saves
    # a bit of work when reconstructing after a time step

    if group_factory_name == "warp_and_blend":
        group_factory_cls = poly.PolynomialWarpAndBlendGroupFactory

        unit_nodes = mp.warp_and_blend_nodes(ambient_dim - 1, mesh_order)
    elif group_factory_name == "quadrature":
        group_factory_cls = poly.InterpolatoryQuadratureSimplexGroupFactory

        if ambient_dim == 2:
            unit_nodes = mp.LegendreGaussQuadrature(
                    mesh_order, force_dim_axis=True).nodes
        else:
            unit_nodes = mp.VioreanuRokhlinSimplexQuadrature(mesh_order, 2).nodes
    else:
        raise ValueError(f"unknown group factory: '{group_factory_name}'")

    # }}}

    # {{{ discretization

    import meshmode.mesh.generation as gen
    if ambient_dim == 2:
        nelements = 8192 if resolution is None else resolution
        mesh = gen.make_curve_mesh(
                lambda t: radius * gen.ellipse(1.0, t),
                np.linspace(0.0, 1.0, nelements + 1),
                order=mesh_order,
                unit_nodes=unit_nodes)
    else:
        nrounds = 4 if resolution is None else resolution
        mesh = gen.generate_icosphere(radius,
                uniform_refinement_rounds=nrounds,
                order=mesh_order,
                unit_nodes=unit_nodes)

    from meshmode.discretization import Discretization
    discr0 = Discretization(actx, mesh, group_factory_cls(target_order))

    logger.info("ndofs:     %d", discr0.ndofs)
    logger.info("nelements: %d", discr0.mesh.nelements)

    # }}}

    if visualize:
        from meshmode.discretization.visualization import make_visualizer
        vis = make_visualizer(actx, discr0,
                vis_order=target_order,
                # NOTE: setting this to True will add some unnecessary
                # resampling in Discretization.nodes for the vis_discr underneath
                force_equidistant=False)

    # }}}

    # {{{ ode

    def velocity_field(nodes, alpha=1.0):
        return make_obj_array([
            alpha * nodes[0], -alpha * nodes[1], 0.0 * nodes[0]
            ][:ambient_dim])

    def source(t, x):
        discr = reconstruct_discr_from_nodes(actx, discr0, x)
        u = velocity_field(thaw(discr.nodes(), actx))

        # {{{

        # NOTE: these are just here because this was at some point used to
        # profile some more operators (turned out well!)

        from meshmode.discretization import num_reference_derivative
        x = thaw(discr.nodes()[0], actx)
        gradx = sum(
                num_reference_derivative(discr, (i,), x)
                for i in range(discr.dim))
        intx = sum(actx.np.sum(xi * wi) for xi, wi in zip(x, discr.quad_weights()))

        assert gradx is not None
        assert intx is not None

        # }}}

        return u

    # }}}

    # {{{ evolve

    maxiter = int(tmax // timestep) + 1
    dt = tmax / maxiter + 1.0e-15

    x = thaw(discr0.nodes(), actx)
    t = 0.0

    if visualize:
        filename = f"moving-geometry-{0:09d}.vtu"
        plot_solution(actx, vis, filename, discr0, t, x)

    for n in range(1, maxiter + 1):
        x = advance(actx, dt, t, x, source)
        t += dt

        if visualize:
            discr = reconstruct_discr_from_nodes(actx, discr0, x)
            vis = make_visualizer(actx, discr, vis_order=target_order)
            # vis = vis.copy_with_same_connectivity(actx, discr)

            filename = f"moving-geometry-{n:09d}.vtu"
            plot_solution(actx, vis, filename, discr, t, x)

        logger.info("[%05d/%05d] t = %.5e/%.5e dt = %.5e",
                n, maxiter, t, tmax, dt)