示例#1
0
def test_surface_mass_operator_inverse(actx_factory, name):
    actx = actx_factory()

    # {{{ cases

    if name == "2-1-ellipse":
        from mesh_data import EllipseMeshBuilder
        builder = EllipseMeshBuilder(radius=3.1, aspect_ratio=2.0)
    elif name == "spheroid":
        from mesh_data import SpheroidMeshBuilder
        builder = SpheroidMeshBuilder()
    else:
        raise ValueError("unknown geometry name: %s" % name)

    # }}}

    # {{{ convergence

    from pytools.convergence import EOCRecorder
    eoc = EOCRecorder()

    for resolution in builder.resolutions:
        mesh = builder.get_mesh(resolution, builder.mesh_order)
        discr = DiscretizationCollection(actx, mesh, order=builder.order)
        volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME)

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

        # {{{ compute inverse mass

        dd = dof_desc.DD_VOLUME
        sym_f = sym.cos(4.0 * sym.nodes(mesh.ambient_dim, dd)[0])
        sym_op = sym.InverseMassOperator(dd, dd)(sym.MassOperator(dd, dd)(
            sym.var("f")))

        f = bind(discr, sym_f)(actx)
        f_inv = bind(discr, sym_op)(actx, f=f)

        inv_error = bind(
            discr,
            sym.norm(2,
                     sym.var("x") - sym.var("y")) / sym.norm(2, sym.var("y")))(
                         actx, x=f_inv, y=f)

        # }}}

        h_max = bind(
            discr,
            sym.h_max_from_volume(discr.ambient_dim, dim=discr.dim,
                                  dd=dd))(actx)
        eoc.add_data_point(h_max, inv_error)

    # }}}

    logger.info("inverse mass error\n%s", str(eoc))

    # NOTE: both cases give 1.0e-16-ish at the moment, but just to be on the
    # safe side, choose a slightly larger tolerance
    assert eoc.max_error() < 1.0e-14
示例#2
0
def test_1d_mass_mat_trig(ctx_factory):
    """Check the integral of some trig functions on an interval using the mass
    matrix
    """

    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)

    from meshmode.mesh.generation import generate_regular_rect_mesh

    mesh = generate_regular_rect_mesh(a=(-4 * np.pi, ),
                                      b=(9 * np.pi, ),
                                      n=(17, ),
                                      order=1)

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

    x = sym.nodes(1)
    f = bind(discr, sym.cos(x[0])**2)(queue)
    ones = bind(discr, sym.Ones(sym.DD_VOLUME))(queue)

    mass_op = bind(discr, sym.MassOperator()(sym.var("f")))

    num_integral_1 = np.dot(ones.get(), mass_op(queue, f=f))
    num_integral_2 = np.dot(f.get(), mass_op(queue, f=ones))
    num_integral_3 = bind(discr, sym.integral(sym.var("f")))(queue, f=f)

    true_integral = 13 * np.pi / 2
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    err_3 = abs(num_integral_3 - true_integral)

    assert err_1 < 1e-10
    assert err_2 < 1e-10
    assert err_3 < 1e-10
示例#3
0
文件: em.py 项目: majosm/grudge
def get_rectangular_cavity_mode(E_0, mode_indices):  # noqa: N803
    """A rectangular TM cavity mode for a rectangle / cube
    with one corner at the origin and the other at (1,1[,1])."""
    dims = len(mode_indices)
    if dims != 2 and dims != 3:
        raise ValueError("Improper mode_indices dimensions")
    import numpy

    factors = [n * numpy.pi for n in mode_indices]

    kx, ky = factors[0:2]
    if dims == 3:
        kz = factors[2]

    omega = numpy.sqrt(sum(f**2 for f in factors))

    nodes = sym.nodes(dims)
    x = nodes[0]
    y = nodes[1]
    if dims == 3:
        z = nodes[2]

    sx = sym.sin(kx * x)
    cx = sym.cos(kx * x)
    sy = sym.sin(ky * y)
    cy = sym.cos(ky * y)
    if dims == 3:
        sz = sym.sin(kz * z)
        cz = sym.cos(kz * z)

    if dims == 2:
        tfac = sym.ScalarVariable("t") * omega

        result = flat_obj_array(
            0,
            0,
            sym.sin(kx * x) * sym.sin(ky * y) * sym.cos(tfac),  # ez
            -ky * sym.sin(kx * x) * sym.cos(ky * y) * sym.sin(tfac) /
            omega,  # hx
            kx * sym.cos(kx * x) * sym.sin(ky * y) * sym.sin(tfac) /
            omega,  # hy
            0,
        )
    else:
        tdep = sym.exp(-1j * omega * sym.ScalarVariable("t"))

        gamma_squared = ky**2 + kx**2
        result = flat_obj_array(
            -kx * kz * E_0 * cx * sy * sz * tdep / gamma_squared,  # ex
            -ky * kz * E_0 * sx * cy * sz * tdep / gamma_squared,  # ey
            E_0 * sx * sy * cz * tdep,  # ez
            -1j * omega * ky * E_0 * sx * cy * cz * tdep / gamma_squared,  # hx
            1j * omega * kx * E_0 * cx * sy * cz * tdep / gamma_squared,
            0,
        )

    return result
示例#4
0
def test_tri_diff_mat(ctx_factory, dim, order=4):
    """Check differentiation matrix along the coordinate axes on a disk

    Uses sines as the function to differentiate.
    """

    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    from meshmode.mesh.generation import generate_regular_rect_mesh

    from pytools.convergence import EOCRecorder
    axis_eoc_recs = [EOCRecorder() for axis in range(dim)]

    for n in [10, 20]:
        mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                          b=(0.5, ) * dim,
                                          n=(n, ) * dim,
                                          order=4)

        discr = DGDiscretizationWithBoundaries(actx, mesh, order=4)
        nabla = sym.nabla(dim)

        for axis in range(dim):
            x = sym.nodes(dim)

            f = bind(discr, sym.sin(3 * x[axis]))(actx)
            df = bind(discr, 3 * sym.cos(3 * x[axis]))(actx)

            sym_op = nabla[axis](sym.var("f"))
            bound_op = bind(discr, sym_op)
            df_num = bound_op(f=f)

            linf_error = flat_norm(df_num - df, np.Inf)
            axis_eoc_recs[axis].add_data_point(1 / n, linf_error)

    for axis, eoc_rec in enumerate(axis_eoc_recs):
        logger.info("axis %d\n%s", axis, eoc_rec)
        assert eoc_rec.order_estimate() >= order
示例#5
0
def test_tri_diff_mat(actx_factory, dim, order=4):
    """Check differentiation matrix along the coordinate axes on a disk

    Uses sines as the function to differentiate.
    """

    actx = actx_factory()

    from pytools.convergence import EOCRecorder
    axis_eoc_recs = [EOCRecorder() for axis in range(dim)]

    for n in [4, 8, 16]:
        mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dim,
                                               b=(0.5, ) * dim,
                                               nelements_per_axis=(n, ) * dim,
                                               order=4)

        discr = DiscretizationCollection(actx, mesh, order=4)
        nabla = sym.nabla(dim)

        for axis in range(dim):
            x = sym.nodes(dim)

            f = bind(discr, sym.sin(3 * x[axis]))(actx)
            df = bind(discr, 3 * sym.cos(3 * x[axis]))(actx)

            sym_op = nabla[axis](sym.var("f"))
            bound_op = bind(discr, sym_op)
            df_num = bound_op(f=f)

            linf_error = actx.np.linalg.norm(df_num - df, ord=np.inf)
            axis_eoc_recs[axis].add_data_point(1 / n, linf_error)

    for axis, eoc_rec in enumerate(axis_eoc_recs):
        logger.info("axis %d\n%s", axis, eoc_rec)
        assert eoc_rec.order_estimate() > order - 0.25
示例#6
0
def test_mass_mat_trig(ctx_factory, ambient_dim, quad_tag):
    """Check the integral of some trig functions on an interval using the mass
    matrix.
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    nelements = 17
    order = 4

    a = -4.0 * np.pi
    b = +9.0 * np.pi
    true_integral = 13 * np.pi / 2 * (b - a)**(ambient_dim - 1)

    from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory
    dd_quad = sym.DOFDesc(sym.DTAG_VOLUME_ALL, quad_tag)
    if quad_tag is sym.QTAG_NONE:
        quad_tag_to_group_factory = {}
    else:
        quad_tag_to_group_factory = {
            quad_tag: QuadratureSimplexGroupFactory(order=2 * order)
        }

    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(a, ) * ambient_dim,
                                      b=(b, ) * ambient_dim,
                                      n=(nelements, ) * ambient_dim,
                                      order=1)
    discr = DGDiscretizationWithBoundaries(
        actx,
        mesh,
        order=order,
        quad_tag_to_group_factory=quad_tag_to_group_factory)

    def _get_variables_on(dd):
        sym_f = sym.var("f", dd=dd)
        sym_x = sym.nodes(ambient_dim, dd=dd)
        sym_ones = sym.Ones(dd)

        return sym_f, sym_x, sym_ones

    sym_f, sym_x, sym_ones = _get_variables_on(sym.DD_VOLUME)
    f_volm = actx.to_numpy(flatten(bind(discr, sym.cos(sym_x[0])**2)(actx)))
    ones_volm = actx.to_numpy(flatten(bind(discr, sym_ones)(actx)))

    sym_f, sym_x, sym_ones = _get_variables_on(dd_quad)
    f_quad = bind(discr, sym.cos(sym_x[0])**2)(actx)
    ones_quad = bind(discr, sym_ones)(actx)

    mass_op = bind(discr, sym.MassOperator(dd_quad, sym.DD_VOLUME)(sym_f))

    num_integral_1 = np.dot(ones_volm,
                            actx.to_numpy(flatten(mass_op(f=f_quad))))
    err_1 = abs(num_integral_1 - true_integral)
    assert err_1 < 1e-9, err_1

    num_integral_2 = np.dot(f_volm,
                            actx.to_numpy(flatten(mass_op(f=ones_quad))))
    err_2 = abs(num_integral_2 - true_integral)
    assert err_2 < 1.0e-9, err_2

    if quad_tag is sym.QTAG_NONE:
        # NOTE: `integral` always makes a square mass matrix and
        # `QuadratureSimplexGroupFactory` does not have a `mass_matrix` method.
        num_integral_3 = bind(discr, sym.integral(sym_f, dd=dd_quad))(f=f_quad)
        err_3 = abs(num_integral_3 - true_integral)
        assert err_3 < 5.0e-10, err_3
示例#7
0
 def f(x):
     return flat_obj_array(
         sym.sin(3 * x[0]) + sym.cos(3 * x[1]),
         sym.sin(2 * x[0]) + sym.cos(x[1]))
示例#8
0
 def f(x):
     return sym.join_fields(
         sym.sin(3 * x[0]) + sym.cos(3 * x[1]),
         sym.sin(2 * x[0]) + sym.cos(x[1]))
示例#9
0
def test_mass_mat_trig(actx_factory, ambient_dim, discr_tag):
    """Check the integral of some trig functions on an interval using the mass
    matrix.
    """
    actx = actx_factory()

    nel_1d = 16
    order = 4

    a = -4.0 * np.pi
    b = +9.0 * np.pi
    true_integral = 13 * np.pi / 2 * (b - a)**(ambient_dim - 1)

    from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory
    dd_quad = dof_desc.DOFDesc(dof_desc.DTAG_VOLUME_ALL, discr_tag)
    if discr_tag is dof_desc.DISCR_TAG_BASE:
        discr_tag_to_group_factory = {}
    else:
        discr_tag_to_group_factory = {
            discr_tag: QuadratureSimplexGroupFactory(order=2 * order)
        }

    mesh = mgen.generate_regular_rect_mesh(a=(a, ) * ambient_dim,
                                           b=(b, ) * ambient_dim,
                                           nelements_per_axis=(nel_1d, ) *
                                           ambient_dim,
                                           order=1)
    discr = DiscretizationCollection(
        actx,
        mesh,
        order=order,
        discr_tag_to_group_factory=discr_tag_to_group_factory)

    def _get_variables_on(dd):
        sym_f = sym.var("f", dd=dd)
        sym_x = sym.nodes(ambient_dim, dd=dd)
        sym_ones = sym.Ones(dd)

        return sym_f, sym_x, sym_ones

    sym_f, sym_x, sym_ones = _get_variables_on(dof_desc.DD_VOLUME)
    f_volm = actx.to_numpy(flatten(bind(discr, sym.cos(sym_x[0])**2)(actx)))
    ones_volm = actx.to_numpy(flatten(bind(discr, sym_ones)(actx)))

    sym_f, sym_x, sym_ones = _get_variables_on(dd_quad)
    f_quad = bind(discr, sym.cos(sym_x[0])**2)(actx)
    ones_quad = bind(discr, sym_ones)(actx)

    mass_op = bind(discr, sym.MassOperator(dd_quad, dof_desc.DD_VOLUME)(sym_f))

    num_integral_1 = np.dot(ones_volm,
                            actx.to_numpy(flatten(mass_op(f=f_quad))))
    err_1 = abs(num_integral_1 - true_integral)
    assert err_1 < 2e-9, err_1

    num_integral_2 = np.dot(f_volm,
                            actx.to_numpy(flatten(mass_op(f=ones_quad))))
    err_2 = abs(num_integral_2 - true_integral)
    assert err_2 < 2e-9, err_2

    if discr_tag is dof_desc.DISCR_TAG_BASE:
        # NOTE: `integral` always makes a square mass matrix and
        # `QuadratureSimplexGroupFactory` does not have a `mass_matrix` method.
        num_integral_3 = bind(discr, sym.integral(sym_f, dd=dd_quad))(f=f_quad)
        err_3 = abs(num_integral_3 - true_integral)
        assert err_3 < 5.0e-10, err_3
示例#10
0
 def f(x):
     return flat_obj_array(
         sym.sin(3 * x[1]) + sym.cos(3 * x[0]) + 1.0,
         sym.sin(2 * x[0]) + sym.cos(x[1]),
         3.0 * sym.cos(x[0] / 2) + sym.cos(x[1]),
     )[:ambient_dim]