예제 #1
0
def test_nodal_reductions(actx_factory):
    actx = actx_factory()

    from mesh_data import BoxMeshBuilder
    builder = BoxMeshBuilder(ambient_dim=1)

    mesh = builder.get_mesh(4, builder.mesh_order)
    dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
    x = thaw(dcoll.nodes(), actx)

    def f(x):
        return -actx.np.sin(10 * x[0])

    def g(x):
        return actx.np.cos(2 * x[0])

    def h(x):
        return -actx.np.tan(5 * x[0])

    fields = make_obj_array([f(x), g(x), h(x)])

    f_ref = actx.to_numpy(flatten(fields[0]))
    g_ref = actx.to_numpy(flatten(fields[1]))
    h_ref = actx.to_numpy(flatten(fields[2]))
    concat_fields = np.concatenate([f_ref, g_ref, h_ref])

    for inner_grudge_op, np_op in [(op.nodal_sum, np.sum),
                                   (op.nodal_max, np.max),
                                   (op.nodal_min, np.min)]:

        # FIXME: Remove this once all grudge reductions return device scalars
        def grudge_op(dcoll, dd, vec):
            res = inner_grudge_op(dcoll, dd, vec)

            from numbers import Number
            if not isinstance(res, Number):
                return actx.to_numpy(res)
            else:
                return res

        # Componentwise reduction checks
        assert np.isclose(grudge_op(dcoll, "vol", fields[0]),
                          np_op(f_ref),
                          rtol=1e-13)
        assert np.isclose(grudge_op(dcoll, "vol", fields[1]),
                          np_op(g_ref),
                          rtol=1e-13)
        assert np.isclose(grudge_op(dcoll, "vol", fields[2]),
                          np_op(h_ref),
                          rtol=1e-13)

        # Test nodal reductions work on object arrays
        assert np.isclose(grudge_op(dcoll, "vol", fields),
                          np_op(concat_fields),
                          rtol=1e-13)
예제 #2
0
def test_nodal_reductions_with_container(actx_factory):
    actx = actx_factory()

    from mesh_data import BoxMeshBuilder
    builder = BoxMeshBuilder(ambient_dim=2)

    mesh = builder.get_mesh(4, builder.mesh_order)
    dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
    x = thaw(dcoll.nodes(), actx)

    def f(x):
        return -actx.np.sin(10 * x[0]) * actx.np.cos(2 * x[1])

    def g(x):
        return actx.np.cos(2 * x[0]) * actx.np.sin(10 * x[1])

    def h(x):
        return -actx.np.tan(5 * x[0]) * actx.np.tan(0.5 * x[1])

    mass = f(x) + g(x)
    momentum = make_obj_array([f(x) / g(x), h(x)])
    enthalpy = h(x) - g(x)

    ary_container = MyContainer(name="container",
                                mass=mass,
                                momentum=momentum,
                                enthalpy=enthalpy)

    mass_ref = actx.to_numpy(flatten(mass))
    momentum_ref = np.concatenate(
        [actx.to_numpy(mom_i) for mom_i in flatten(momentum)])
    enthalpy_ref = actx.to_numpy(flatten(enthalpy))
    concat_fields = np.concatenate([mass_ref, momentum_ref, enthalpy_ref])

    for grudge_op, np_op in [(op.nodal_sum, np.sum), (op.nodal_max, np.max),
                             (op.nodal_min, np.min)]:

        assert np.isclose(actx.to_numpy(grudge_op(dcoll, "vol",
                                                  ary_container)),
                          np_op(concat_fields),
                          rtol=1e-13)

    # Check norm reduction
    assert np.isclose(actx.to_numpy(op.norm(dcoll, ary_container, np.inf)),
                      np.linalg.norm(concat_fields, ord=np.inf),
                      rtol=1e-13)
예제 #3
0
def test_non_geometric_factors(actx_factory, name):
    from grudge.dt_utils import dt_non_geometric_factors

    actx = actx_factory()

    # {{{ cases

    if name == "interval":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=1)
    elif name == "box2d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=2)
    elif name == "box3d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=3)
    else:
        raise ValueError("unknown geometry name: %s" % name)

    # }}}

    factors = []
    degrees = list(range(1, 8))
    for degree in degrees:
        mesh = builder.get_mesh(1, degree)
        dcoll = DiscretizationCollection(actx, mesh, order=degree)
        factors.append(min(dt_non_geometric_factors(dcoll)))

    # Crude estimate, factors should behave like 1/N**2
    factors = np.asarray(factors)
    lower_bounds = 1 / (np.asarray(degrees)**2)
    upper_bounds = 6.295 * lower_bounds

    assert all(lower_bounds <= factors)
    assert all(factors <= upper_bounds)
예제 #4
0
def test_geometric_factors_regular_refinement(actx_factory, name):
    from grudge.dt_utils import dt_geometric_factors

    actx = actx_factory()

    # {{{ cases

    if name == "interval":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=1)
    elif name == "box2d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=2)
    elif name == "box3d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=3)
    else:
        raise ValueError("unknown geometry name: %s" % name)

    # }}}

    min_factors = []
    for resolution in builder.resolutions:
        mesh = builder.get_mesh(resolution, builder.mesh_order)
        dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
        min_factors.append(
            actx.to_numpy(
                op.nodal_min(dcoll, "vol",
                             thaw(dt_geometric_factors(dcoll), actx))))

    # Resolution is doubled each refinement, so the ratio of consecutive
    # geometric factors should satisfy: gfi+1 / gfi = 2
    min_factors = np.asarray(min_factors)
    ratios = min_factors[:-1] / min_factors[1:]
    assert np.all(np.isclose(ratios, 2))
예제 #5
0
def test_elementwise_reductions(actx_factory):
    actx = actx_factory()

    from mesh_data import BoxMeshBuilder
    builder = BoxMeshBuilder(ambient_dim=1)

    nelements = 4
    mesh = builder.get_mesh(nelements, builder.mesh_order)
    dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
    x = thaw(dcoll.nodes(), actx)

    def f(x):
        return actx.np.sin(x[0])

    field = f(x)
    mins = []
    maxs = []
    sums = []
    for gidx, grp_f in enumerate(field):
        min_res = np.empty(grp_f.shape)
        max_res = np.empty(grp_f.shape)
        sum_res = np.empty(grp_f.shape)
        for eidx in range(dcoll._volume_discr.groups[gidx].nelements):
            element_data = actx.to_numpy(grp_f[eidx])
            min_res[eidx, :] = np.min(element_data)
            max_res[eidx, :] = np.max(element_data)
            sum_res[eidx, :] = np.sum(element_data)
        mins.append(actx.from_numpy(min_res))
        maxs.append(actx.from_numpy(max_res))
        sums.append(actx.from_numpy(sum_res))

    from meshmode.dof_array import DOFArray, flat_norm

    ref_mins = DOFArray(actx, data=tuple(mins))
    ref_maxs = DOFArray(actx, data=tuple(maxs))
    ref_sums = DOFArray(actx, data=tuple(sums))

    elem_mins = op.elementwise_min(dcoll, field)
    elem_maxs = op.elementwise_max(dcoll, field)
    elem_sums = op.elementwise_sum(dcoll, field)

    assert flat_norm(elem_mins - ref_mins, ord=np.inf) < 1.e-15
    assert flat_norm(elem_maxs - ref_maxs, ord=np.inf) < 1.e-15
    assert flat_norm(elem_sums - ref_sums, ord=np.inf) < 1.e-15
예제 #6
0
def test_mass_surface_area(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)
        surface_area = _ellipse_surface_area(builder.radius,
                                             builder.aspect_ratio)
    elif name == "spheroid":
        from mesh_data import SpheroidMeshBuilder
        builder = SpheroidMeshBuilder()
        surface_area = _spheroid_surface_area(builder.radius,
                                              builder.aspect_ratio)
    elif name == "box2d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=2)
        surface_area = 1.0
    elif name == "box3d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=3)
        surface_area = 1.0
    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 surface area

        dd = dof_desc.DD_VOLUME
        sym_op = sym.NodalSum(dd)(sym.MassOperator(dd, dd)(sym.Ones(dd)))
        approx_surface_area = bind(discr, sym_op)(actx)

        logger.info("surface: got {:.5e} / expected {:.5e}".format(
            approx_surface_area, surface_area))
        area_error = abs(approx_surface_area -
                         surface_area) / abs(surface_area)

        # }}}

        h_max = bind(
            discr,
            sym.h_max_from_volume(discr.ambient_dim, dim=discr.dim,
                                  dd=dd))(actx)
        eoc.add_data_point(h_max, area_error + 1.0e-16)

    # }}}

    logger.info("surface area error\n%s", str(eoc))

    assert eoc.max_error() < 1.0e-14 \
            or eoc.order_estimate() > builder.order
예제 #7
0
def test_mass_surface_area(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)
        surface_area = _ellipse_surface_area(builder.radius,
                                             builder.aspect_ratio)
    elif name == "spheroid":
        from mesh_data import SpheroidMeshBuilder
        builder = SpheroidMeshBuilder()
        surface_area = _spheroid_surface_area(builder.radius,
                                              builder.aspect_ratio)
    elif name == "box2d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=2)
        surface_area = 1.0
    elif name == "box3d":
        from mesh_data import BoxMeshBuilder
        builder = BoxMeshBuilder(ambient_dim=3)
        surface_area = 1.0
    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)
        dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
        volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME)

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

        # {{{ compute surface area

        dd = dof_desc.DD_VOLUME
        ones_volm = volume_discr.zeros(actx) + 1
        approx_surface_area = actx.to_numpy(op.integral(dcoll, dd, ones_volm))

        logger.info("surface: got {:.5e} / expected {:.5e}".format(
            approx_surface_area, surface_area))
        area_error = abs(approx_surface_area -
                         surface_area) / abs(surface_area)

        # }}}

        # compute max element size
        from grudge.dt_utils import h_max_from_volume

        h_max = h_max_from_volume(dcoll)

        eoc.add_data_point(h_max, area_error)

    # }}}

    logger.info("surface area error\n%s", str(eoc))

    assert eoc.max_error() < 3e-13 or eoc.order_estimate() > builder.order
예제 #8
0
def test_elementwise_reductions_with_container(actx_factory):
    actx = actx_factory()

    from mesh_data import BoxMeshBuilder
    builder = BoxMeshBuilder(ambient_dim=2)

    nelements = 4
    mesh = builder.get_mesh(nelements, builder.mesh_order)
    dcoll = DiscretizationCollection(actx, mesh, order=builder.order)
    x = thaw(dcoll.nodes(), actx)

    def f(x):
        return actx.np.sin(x[0]) * actx.np.sin(x[1])

    def g(x):
        return actx.np.cos(x[0]) * actx.np.cos(x[1])

    def h(x):
        return actx.np.cos(x[0]) * actx.np.sin(x[1])

    mass = 2 * f(x) + 0.5 * g(x)
    momentum = make_obj_array([f(x) / g(x), h(x)])
    enthalpy = 3 * h(x) - g(x)

    ary_container = MyContainer(name="container",
                                mass=mass,
                                momentum=momentum,
                                enthalpy=enthalpy)

    def _get_ref_data(field):
        mins = []
        maxs = []
        sums = []
        for grp_f in field:
            min_res = np.empty(grp_f.shape)
            max_res = np.empty(grp_f.shape)
            sum_res = np.empty(grp_f.shape)
            for eidx in range(dcoll.mesh.nelements):
                element_data = actx.to_numpy(grp_f[eidx])
                min_res[eidx, :] = np.min(element_data)
                max_res[eidx, :] = np.max(element_data)
                sum_res[eidx, :] = np.sum(element_data)
            mins.append(actx.from_numpy(min_res))
            maxs.append(actx.from_numpy(max_res))
            sums.append(actx.from_numpy(sum_res))
        min_field = DOFArray(actx, data=tuple(mins))
        max_field = DOFArray(actx, data=tuple(maxs))
        sums_field = DOFArray(actx, data=tuple(sums))
        return min_field, max_field, sums_field

    min_mass, max_mass, sums_mass = _get_ref_data(mass)
    min_enthalpy, max_enthalpy, sums_enthalpy = _get_ref_data(enthalpy)
    min_mom_x, max_mom_x, sums_mom_x = _get_ref_data(momentum[0])
    min_mom_y, max_mom_y, sums_mom_y = _get_ref_data(momentum[1])
    min_momentum = make_obj_array([min_mom_x, min_mom_y])
    max_momentum = make_obj_array([max_mom_x, max_mom_y])
    sums_momentum = make_obj_array([sums_mom_x, sums_mom_y])

    reference_min = MyContainer(name="Reference min",
                                mass=min_mass,
                                momentum=min_momentum,
                                enthalpy=min_enthalpy)

    reference_max = MyContainer(name="Reference max",
                                mass=max_mass,
                                momentum=max_momentum,
                                enthalpy=max_enthalpy)

    reference_sum = MyContainer(name="Reference sums",
                                mass=sums_mass,
                                momentum=sums_momentum,
                                enthalpy=sums_enthalpy)

    elem_mins = op.elementwise_min(dcoll, ary_container)
    elem_maxs = op.elementwise_max(dcoll, ary_container)
    elem_sums = op.elementwise_sum(dcoll, ary_container)

    assert actx.to_numpy(op.norm(dcoll, elem_mins - reference_min,
                                 np.inf)) < 1.e-14
    assert actx.to_numpy(op.norm(dcoll, elem_maxs - reference_max,
                                 np.inf)) < 1.e-14
    assert actx.to_numpy(op.norm(dcoll, elem_sums - reference_sum,
                                 np.inf)) < 1.e-14