예제 #1
0
def test_norm_obj_array(actx_factory, p):
    """Test :func:`grudge.symbolic.operators.norm` for object arrays."""

    actx = actx_factory()

    dim = 2
    mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                           b=(0.5, ) * dim,
                                           nelements_per_axis=(8, ) * dim,
                                           order=1)
    discr = DiscretizationCollection(actx, mesh, order=4)

    w = make_obj_array([1.0, 2.0, 3.0])[:dim]

    # {{ scalar

    sym_w = sym.var("w")
    norm = bind(discr, sym.norm(p, sym_w))(actx, w=w[0])

    norm_exact = w[0]
    logger.info("norm: %.5e %.5e", norm, norm_exact)
    assert abs(norm - norm_exact) < 1.0e-14

    # }}}

    # {{{ vector

    sym_w = sym.make_sym_array("w", dim)
    norm = bind(discr, sym.norm(p, sym_w))(actx, w=w)

    norm_exact = np.sqrt(np.sum(w**2)) if p == 2 else np.max(w)
    logger.info("norm: %.5e %.5e", norm, norm_exact)
    assert abs(norm - norm_exact) < 1.0e-14
예제 #2
0
def test_function_symbol_array(ctx_factory, array_type):
    ctx = ctx_factory()
    queue = cl.CommandQueue(ctx)
    actx = PyOpenCLArrayContext(queue)

    from meshmode.mesh.generation import generate_regular_rect_mesh
    dim = 2
    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                      b=(0.5, ) * dim,
                                      n=(8, ) * dim,
                                      order=4)
    discr = DGDiscretizationWithBoundaries(actx, mesh, order=4)
    volume_discr = discr.discr_from_dd(sym.DD_VOLUME)
    ndofs = sum(grp.ndofs for grp in volume_discr.groups)

    import pyopencl.clrandom  # noqa: F401
    if array_type == "scalar":
        sym_x = sym.var("x")
        x = unflatten(actx, volume_discr,
                      cl.clrandom.rand(queue, ndofs, dtype=np.float))
    elif array_type == "vector":
        sym_x = sym.make_sym_array("x", dim)
        x = make_obj_array([
            unflatten(actx, volume_discr,
                      cl.clrandom.rand(queue, ndofs, dtype=np.float))
            for _ in range(dim)
        ])
    else:
        raise ValueError("unknown array type")

    norm = bind(discr, sym.norm(2, sym_x))(x=x)
    assert isinstance(norm, float)
예제 #3
0
파일: em.py 프로젝트: majosm/grudge
    def sym_operator(self, w=None):
        """The full operator template - the high level description of
        the Maxwell operator.

        Combines the relevant operator templates for spatial
        derivatives, flux, boundary conditions etc.
        """
        from grudge.tools import count_subset
        w = sym.make_sym_array("w", count_subset(self.get_eh_subset()))

        elec_components = count_subset(self.get_eh_subset()[0:3])
        mag_components = count_subset(self.get_eh_subset()[3:6])

        if self.fixed_material:
            # need to check this
            material_divisor = ([self.epsilon] * elec_components +
                                [self.mu] * mag_components)

        tags_and_bcs = [
            (self.pec_tag, self.pec_bc(w)),
            (self.pmc_tag, self.pmc_bc(w)),
            (self.absorb_tag, self.absorbing_bc(w)),
            (self.incident_tag, self.incident_bc(w)),
        ]

        def flux(pair):
            return sym.project(pair.dd, "all_faces")(self.flux(pair))

        return (-self.local_derivatives(w) - sym.InverseMassOperator()
                (sym.FaceMassOperator()(flux(sym.int_tpair(w)) + sum(
                    flux(sym.bv_tpair(tag, w, bc))
                    for tag, bc in tags_and_bcs)))) / material_divisor
예제 #4
0
def test_incorrect_assignment_aggregation(actx_factory, ambient_dim):
    """Tests that the greedy assignemnt aggregation code works on a non-trivial
    expression (on which it didn't work at the time of writing).
    """

    actx = actx_factory()

    target_order = 4

    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(-0.5, ) * ambient_dim,
                                      b=(0.5, ) * ambient_dim,
                                      n=(8, ) * ambient_dim,
                                      order=1)
    discr = DiscretizationCollection(actx, mesh, order=target_order)

    # {{{ test with a relative norm

    from grudge.dof_desc import DD_VOLUME
    dd = DD_VOLUME
    sym_x = sym.make_sym_array("y", ambient_dim, dd=dd)
    sym_y = sym.make_sym_array("y", ambient_dim, dd=dd)

    sym_norm_y = sym.norm(2, sym_y, dd=dd)
    sym_norm_d = sym.norm(2, sym_x - sym_y, dd=dd)
    sym_op = sym_norm_d / sym_norm_y
    logger.info("%s", sym.pretty(sym_op))

    # FIXME: this shouldn't raise a RuntimeError
    with pytest.raises(RuntimeError):
        bind(discr, sym_op)(actx, x=1.0, y=discr.discr_from_dd(dd).nodes())

    # }}}

    # {{{ test with repeated mass inverses

    sym_minv_y = sym.cse(sym.InverseMassOperator()(sym_y), "minv_y")

    sym_u = make_obj_array([0.5 * sym.Ones(dd), 0.0, 0.0])[:ambient_dim]
    sym_div_u = sum(d(u) for d, u in zip(sym.nabla(ambient_dim), sym_u))

    sym_op = sym.MassOperator(dd)(sym_u) \
            + sym.MassOperator(dd)(sym_minv_y * sym_div_u)
    logger.info("%s", sym.pretty(sym_op))

    # FIXME: this shouldn't raise a RuntimeError either
    bind(discr, sym_op)(actx, y=discr.discr_from_dd(dd).nodes())
예제 #5
0
    def sym_operator(self):
        d = self.ambient_dim

        w = sym.make_sym_array("w", d + 1)
        u = w[0]
        v = w[1:]

        # boundary conditions -------------------------------------------------

        # dirichlet BCs -------------------------------------------------------
        dir_u = sym.cse(sym.interp("vol", self.dirichlet_tag)(u))
        dir_v = sym.cse(sym.interp("vol", self.dirichlet_tag)(v))
        if self.dirichlet_bc_f:
            # FIXME
            from warnings import warn
            warn("Inhomogeneous Dirichlet conditions on the wave equation "
                 "are still having issues.")

            dir_g = sym.Field("dir_bc_u")
            dir_bc = join_fields(2 * dir_g - dir_u, dir_v)
        else:
            dir_bc = join_fields(-dir_u, dir_v)

        dir_bc = sym.cse(dir_bc, "dir_bc")

        # neumann BCs ---------------------------------------------------------
        neu_u = sym.cse(sym.interp("vol", self.neumann_tag)(u))
        neu_v = sym.cse(sym.interp("vol", self.neumann_tag)(v))
        neu_bc = sym.cse(join_fields(neu_u, -neu_v), "neu_bc")

        # radiation BCs -------------------------------------------------------
        rad_normal = sym.normal(self.radiation_tag, d)

        rad_u = sym.cse(sym.interp("vol", self.radiation_tag)(u))
        rad_v = sym.cse(sym.interp("vol", self.radiation_tag)(v))

        rad_bc = sym.cse(
            join_fields(
                0.5 * (rad_u - self.sign * np.dot(rad_normal, rad_v)), 0.5 *
                rad_normal * (np.dot(rad_normal, rad_v) - self.sign * rad_u)),
            "rad_bc")

        # entire operator -----------------------------------------------------
        def flux(pair):
            return sym.interp(pair.dd, "all_faces")(self.flux(pair))

        result = sym.InverseMassOperator()(
            join_fields(-self.c *
                        np.dot(sym.stiffness_t(self.ambient_dim), v), -self.c *
                        (sym.stiffness_t(self.ambient_dim) * u)) -
            sym.FaceMassOperator()
            (flux(sym.int_tpair(w)) +
             flux(sym.bv_tpair(self.dirichlet_tag, w, dir_bc)) +
             flux(sym.bv_tpair(self.neumann_tag, w, neu_bc)) +
             flux(sym.bv_tpair(self.radiation_tag, w, rad_bc))))

        result[0] += self.source_f

        return result
예제 #6
0
def get_strong_wave_op_with_discr_direct(cl_ctx, dims=2, order=4):
    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(-0.5, ) * dims,
                                      b=(0.5, ) * dims,
                                      n=(16, ) * dims)

    logger.debug("%d elements", mesh.nelements)

    discr = DGDiscretizationWithBoundaries(cl_ctx, mesh, order=order)

    source_center = np.array([0.1, 0.22, 0.33])[:dims]
    source_width = 0.05
    source_omega = 3

    sym_x = sym.nodes(mesh.dim)
    sym_source_center_dist = sym_x - source_center
    sym_t = sym.ScalarVariable("t")

    from meshmode.mesh import BTAG_ALL

    c = -0.1
    sign = -1

    w = sym.make_sym_array("w", dims + 1)
    u = w[0]
    v = w[1:]

    source_f = (
        sym.sin(source_omega * sym_t) *
        sym.exp(-np.dot(sym_source_center_dist, sym_source_center_dist) /
                source_width**2))

    rad_normal = sym.normal(BTAG_ALL, dims)

    rad_u = sym.cse(sym.interp("vol", BTAG_ALL)(u))
    rad_v = sym.cse(sym.interp("vol", BTAG_ALL)(v))

    rad_bc = sym.cse(
        sym.join_fields(
            0.5 * (rad_u - sign * np.dot(rad_normal, rad_v)),
            0.5 * rad_normal * (np.dot(rad_normal, rad_v) - sign * rad_u)),
        "rad_bc")

    sym_operator = (
        -sym.join_fields(-c * np.dot(sym.nabla(dims), v) - source_f, -c *
                         (sym.nabla(dims) * u)) + sym.InverseMassOperator()(
                             sym.FaceMassOperator()
                             (dg_flux(c, sym.int_tpair(w)) +
                              dg_flux(c, sym.bv_tpair(BTAG_ALL, w, rad_bc)))))

    return (sym_operator, discr)
예제 #7
0
def test_function_symbol_array(actx_factory, array_type):
    """Test if `FunctionSymbol` distributed properly over object arrays."""

    actx = actx_factory()

    dim = 2
    mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                           b=(0.5, ) * dim,
                                           nelements_per_axis=(8, ) * dim,
                                           order=4)
    discr = DiscretizationCollection(actx, mesh, order=4)
    volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME)

    if array_type == "scalar":
        sym_x = sym.var("x")
        x = thaw(actx, actx.np.cos(volume_discr.nodes()[0]))
    elif array_type == "vector":
        sym_x = sym.make_sym_array("x", dim)
        x = thaw(actx, volume_discr.nodes())
    else:
        raise ValueError("unknown array type")

    norm = bind(discr, sym.norm(2, sym_x))(x=x)
    assert isinstance(norm, float)
예제 #8
0
def transcribe_phase(dag, field_var_name, field_components, phase_name,
                     sym_operator):
    """Generate a Grudge operator for a Dagrt time integrator phase.

    Arguments:

        dag: The Dagrt code object for the time integrator

        field_var_name: The name of the simulation variable

        field_components: The number of components (fields) in the variable

        phase_name: The name of the phase to transcribe

        sym_operator: The Grudge symbolic expression to substitue for the
            right-hand side evaluation in the Dagrt code
    """
    sym_operator = gmap.OperatorBinder()(sym_operator)
    phase = dag.phases[phase_name]

    ctx = {
            "<t>": sym.var("input_t", dof_desc.DD_SCALAR),
            "<dt>": sym.var("input_dt", dof_desc.DD_SCALAR),
            f"<state>{field_var_name}": sym.make_sym_array(
                f"input_{field_var_name}", field_components),
            "<p>residual": sym.make_sym_array(
                "input_residual", field_components),
    }

    rhs_name = f"<func>{field_var_name}"
    output_vars = [v for v in ctx]
    yielded_states = []

    ordered_stmts = topological_sort(
            isolate_function_calls_in_phase(
                phase,
                dag.get_stmt_id_generator(),
                dag.get_var_name_generator()).statements,
            phase.depends_on)

    for stmt in ordered_stmts:
        if stmt.condition is not True:
            raise NotImplementedError(
                "non-True condition (in statement '%s') not supported"
                % stmt.id)

        if isinstance(stmt, lang.Nop):
            pass

        elif isinstance(stmt, lang.Assign):
            if not isinstance(stmt.lhs, p.Variable):
                raise NotImplementedError("lhs of statement %s is not a variable: %s"
                        % (stmt.id, stmt.lhs))
            ctx[stmt.lhs.name] = sym.cse(
                    DagrtToGrudgeRewriter(ctx)(stmt.rhs),
                    (
                        stmt.lhs.name
                        .replace("<", "")
                        .replace(">", "")))

        elif isinstance(stmt, lang.AssignFunctionCall):
            if stmt.function_id != rhs_name:
                raise NotImplementedError(
                        "statement '%s' calls unsupported function '%s'"
                        % (stmt.id, stmt.function_id))

            if stmt.parameters:
                raise NotImplementedError(
                    "statement '%s' calls function '%s' with positional arguments"
                    % (stmt.id, stmt.function_id))

            kwargs = {name: sym.cse(DagrtToGrudgeRewriter(ctx)(arg))
                      for name, arg in stmt.kw_parameters.items()}

            if len(stmt.assignees) != 1:
                raise NotImplementedError(
                    "statement '%s' calls function '%s' "
                    "with more than one LHS"
                    % (stmt.id, stmt.function_id))

            assignee, = stmt.assignees
            ctx[assignee] = GrudgeArgSubstitutor(kwargs)(sym_operator)

        elif isinstance(stmt, lang.YieldState):
            d2g = DagrtToGrudgeRewriter(ctx)
            yielded_states.append(
                    (
                        stmt.time_id,
                        d2g(stmt.time),
                        stmt.component_id,
                        d2g(stmt.expression)))

        else:
            raise NotImplementedError("statement %s is of unsupported type ''%s'"
                        % (stmt.id, type(stmt).__name__))

    return output_vars, [ctx[ov] for ov in output_vars], yielded_states