Ejemplo n.º 1
0
def test_to_fd_consistency(ctx_factory, mm_mesh, fspace_degree):
    fspace_degree += mm_mesh.groups[0].order

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

    factory = InterpolatoryQuadratureSimplexGroupFactory(fspace_degree)
    discr = Discretization(actx, mm_mesh, factory)
    fdrake_connection = build_connection_to_firedrake(discr)
    fdrake_fspace = fdrake_connection.firedrake_fspace()
    # Check consistency
    check_consistency(fdrake_fspace, discr)
Ejemplo n.º 2
0
def test_to_fd_idempotency(ctx_factory, mm_mesh, fspace_degree):
    """
    Make sure mm->fd->mm and (mm->)->fd->mm->fd are identity
    """
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    # make sure degree is higher order than mesh
    fspace_degree += mm_mesh.groups[0].order

    # Make a function space and a function with unique values at each node
    factory = InterpolatoryQuadratureSimplexGroupFactory(fspace_degree)
    discr = Discretization(actx, mm_mesh, factory)
    fdrake_connection = build_connection_to_firedrake(discr)
    fdrake_mesh = fdrake_connection.firedrake_fspace().mesh()
    dtype = fdrake_mesh.coordinates.dat.data.dtype

    mm_unique = discr.zeros(actx, dtype=dtype)
    unique_vals = np.arange(np.size(mm_unique[0]), dtype=dtype)
    mm_unique[0].set(unique_vals.reshape(mm_unique[0].shape))
    mm_unique_copy = DOFArray(actx, (mm_unique[0].copy(), ))

    # Test for idempotency mm->fd->mm
    fdrake_unique = fdrake_connection.from_meshmode(mm_unique)
    fdrake_connection.from_firedrake(fdrake_unique, out=mm_unique_copy)

    np.testing.assert_allclose(actx.to_numpy(mm_unique_copy[0]),
                               actx.to_numpy(mm_unique[0]),
                               atol=CLOSE_ATOL)

    # Test for idempotency (mm->)fd->mm->fd
    fdrake_unique_copy = fdrake_connection.from_meshmode(mm_unique_copy)
    np.testing.assert_allclose(fdrake_unique_copy.dat.data,
                               fdrake_unique.dat.data,
                               atol=CLOSE_ATOL)
Ejemplo n.º 3
0
def test_to_fd_transfer(ctx_factory, fspace_degree, mesh_name, mesh_pars, dim):
    """
    Make sure creating a function which projects onto
    one dimension then transports it is the same
    (up to resampling error) as projecting to one
    dimension on the transported mesh
    """
    # build estimate-of-convergence recorder
    from pytools.convergence import EOCRecorder
    # dimension projecting onto -> EOCRecorder
    eoc_recorders = {d: EOCRecorder() for d in range(dim)}

    # make a computing context
    cl_ctx = ctx_factory()
    queue = cl.CommandQueue(cl_ctx)
    actx = PyOpenCLArrayContext(queue)

    # Get each of the refinements of the meshmeshes and record
    # conversions errors
    for mesh_par in mesh_pars:
        if mesh_name in ("blob2d-order1", "blob2d-order4"):
            assert dim == 2
            from meshmode.mesh.io import read_gmsh
            mm_mesh = read_gmsh(f"{mesh_name}-h{mesh_par}.msh",
                                force_ambient_dim=dim)
            h = float(mesh_par)
        elif mesh_name == "warp":
            from meshmode.mesh.generation import generate_warped_rect_mesh
            mm_mesh = generate_warped_rect_mesh(dim, order=4, n=mesh_par)
            h = 1 / mesh_par
        else:
            raise ValueError("mesh_name not recognized")

        # Make discr and connect it to firedrake
        factory = InterpolatoryQuadratureSimplexGroupFactory(fspace_degree)
        discr = Discretization(actx, mm_mesh, factory)

        fdrake_connection = build_connection_to_firedrake(discr)
        fdrake_fspace = fdrake_connection.firedrake_fspace()
        spatial_coord = SpatialCoordinate(fdrake_fspace.mesh())

        # get the group's nodes in a numpy array
        nodes = discr.nodes()
        group_nodes = np.array(
            [actx.to_numpy(dof_arr[0]) for dof_arr in nodes])

        for d in range(dim):
            meshmode_f = discr.zeros(actx)
            meshmode_f[0][:] = group_nodes[d, :, :]

            # connect to firedrake and evaluate expr in firedrake
            fdrake_f = Function(fdrake_fspace).interpolate(spatial_coord[d])

            # transport to firedrake and record error
            mm2fd_f = fdrake_connection.from_meshmode(meshmode_f)

            err = np.max(np.abs(fdrake_f.dat.data - mm2fd_f.dat.data))
            eoc_recorders[d].add_data_point(h, err)

    # assert that order is correct or error is "low enough"
    for d, eoc_rec in eoc_recorders.items():
        print("\nvector *x* -> *x[%s]*\n" % d, eoc_rec)
        assert (eoc_rec.order_estimate() >= fspace_degree
                or eoc_rec.max_error() < 2e-14)
Ejemplo n.º 4
0
def main():
    # If can't import firedrake, do nothing
    #
    # filename MUST include "firedrake" (i.e. match *firedrake*.py) in order
    # to be run during CI
    try:
        import firedrake  # noqa : F401
    except ImportError:
        return 0

    # For this example, imagine we wish to solve the Laplace equation
    # on a meshmode mesh with some given Dirichlet boundary conditions,
    # and decide to use firedrake.
    #
    # To verify this is working, we use a solution to the wave equation
    # to get our boundary conditions

    # {{{ First we make a discretization in meshmode and get our bcs

    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)
    from meshmode.array_context import PyOpenCLArrayContext
    actx = PyOpenCLArrayContext(queue)

    nel_1d = 16
    from meshmode.mesh.generation import generate_regular_rect_mesh
    mesh = generate_regular_rect_mesh(a=(-0.5, -0.5),
                                      b=(0.5, 0.5),
                                      n=(nel_1d, nel_1d))

    order = 3

    from meshmode.discretization import Discretization
    from meshmode.discretization.poly_element import \
        InterpolatoryQuadratureSimplexGroupFactory
    group_factory = InterpolatoryQuadratureSimplexGroupFactory(order=order)
    discr = Discretization(actx, mesh, group_factory)

    # Get our solution: we will use
    # Real(e^z) = Real(e^{x+iy})
    #           = e^x Real(e^{iy})
    #           = e^x cos(y)
    nodes = discr.nodes()
    from meshmode.dof_array import thaw
    for i in range(len(nodes)):
        nodes[i] = thaw(actx, nodes[i])
    # First index is dimension
    candidate_sol = actx.np.exp(nodes[0]) * actx.np.cos(nodes[1])

    # }}}

    # {{{ Now send candidate_sol into firedrake and use it for boundary conditions

    from meshmode.interop.firedrake import build_connection_to_firedrake
    fd_connection = build_connection_to_firedrake(discr, group_nr=0)
    # convert candidate_sol to firedrake
    fd_candidate_sol = fd_connection.from_meshmode(candidate_sol)
    # get the firedrake function space
    fd_fspace = fd_connection.firedrake_fspace()

    # set up dirichlet laplace problem in fd and solve
    from firedrake import (FunctionSpace, TrialFunction, TestFunction,
                           Function, inner, grad, dx, Constant, project,
                           DirichletBC, solve)

    # because it's easier to write down the variational problem,
    # we're going to project from our "DG" space
    # into a continuous one.
    cfd_fspace = FunctionSpace(fd_fspace.mesh(), "CG", order)
    u = TrialFunction(cfd_fspace)
    v = TestFunction(cfd_fspace)
    sol = Function(cfd_fspace)

    a = inner(grad(u), grad(v)) * dx
    rhs = Constant(0.0) * v * dx
    bc_value = project(fd_candidate_sol, cfd_fspace)
    bc = DirichletBC(cfd_fspace, bc_value, "on_boundary")
    params = {"ksp_monitor": None}
    solve(a == rhs, sol, bcs=[bc], solver_parameters=params)

    # project back into our "DG" space
    sol = project(sol, fd_fspace)

    # }}}

    # {{{ Take the solution from firedrake and compare it to candidate_sol

    true_sol = fd_connection.from_firedrake(sol, actx=actx)
    # pull back into numpy
    true_sol = actx.to_numpy(true_sol[0])
    candidate_sol = actx.to_numpy(candidate_sol[0])
    print("l^2 difference between candidate solution and firedrake solution=",
          np.linalg.norm(true_sol - candidate_sol))