Checkpoint on input mesh

Checkpoint on input mesh#

As we have discussed earlier, one can choose to store function data in a way that is N-to-M compatible by using adios4dolfinx.write_checkpoint. This stores the distributed mesh in it’s current (partitioned) ordering, and does use the original input data ordering for the cells and connectivity. This means that you cannot use your original mesh (from .xdmf files) or mesh tags together with the checkpoint. The checkpoint has to store the mesh and associated mesh-tags.

An optional way of store an N-to-M checkpoint is to store the function data in the same ordering as the mesh. The write operation will be more expensive, as it requires data communication to ensure contiguous data being written to the checkpoint. The method is exposed as adios4dolfinx.write_function_on_input_mesh. Below we will demonstrate this method.

import logging
from pathlib import Path
from typing import Tuple
import ipyparallel as ipp
def locate_facets(x, tol=1.0e-12):
    return abs(x[0]) < tol
def create_xdmf_mesh(filename: Path):
    from mpi4py import MPI

    import dolfinx

    mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)
    facets = dolfinx.mesh.locate_entities_boundary(mesh, mesh.topology.dim - 1, locate_facets)
    facet_tag = dolfinx.mesh.meshtags(mesh, mesh.topology.dim - 1, facets, 1)
    facet_tag.name = "FacetTag"
    with dolfinx.io.XDMFFile(MPI.COMM_WORLD, filename.with_suffix(".xdmf"), "w") as xdmf:
        xdmf.write_mesh(mesh)
        xdmf.write_meshtags(facet_tag, mesh.geometry)
    print(f"{mesh.comm.rank+1}/{mesh.comm.size} Mesh written to {filename.with_suffix('.xdmf')}")
mesh_file = Path("MyMesh.xdmf")
with ipp.Cluster(engines="mpi", n=4, log_level=logging.ERROR) as cluster:
    # Create a mesh and write to XDMFFile
    cluster[:].push({"locate_facets": locate_facets})
    query = cluster[:].apply_async(create_xdmf_mesh, mesh_file)
    query.wait()
    assert query.successful(), query.error
    print("".join(query.stdout))
1/4 Mesh written to MyMesh.xdmf
2/4 Mesh written to MyMesh.xdmf
3/4 Mesh written to MyMesh.xdmf
4/4 Mesh written to MyMesh.xdmf

Next, we will create a function on the mesh and write it to a checkpoint.

def f(x):
    return (x[0] + x[1]) * (x[0] < 0.5), x[1], x[2] - x[1]
def write_function(
    mesh_filename: Path, function_filename: Path, element: Tuple[str, int, Tuple[int,]]
):
    from mpi4py import MPI

    import dolfinx

    import adios4dolfinx

    with dolfinx.io.XDMFFile(MPI.COMM_WORLD, mesh_filename, "r") as xdmf:
        mesh = xdmf.read_mesh()
    V = dolfinx.fem.functionspace(mesh, element)
    u = dolfinx.fem.Function(V)
    u.interpolate(f)

    adios4dolfinx.write_function_on_input_mesh(
        function_filename.with_suffix(".bp"),
        u,
        mode=adios4dolfinx.adios2_helpers.adios2.Mode.Write,
        time=0.0,
        name="Output",
    )
    print(
        f"{mesh.comm.rank+1}/{mesh.comm.size} Function written to ",
        f"{function_filename.with_suffix('.bp')}",
    )

Read in mesh and write function to file

element = ("DG", 4, (3,))
function_file = Path("MyFunction.bp")
with ipp.Cluster(engines="mpi", n=2, log_level=logging.ERROR) as cluster:
    cluster[:].push({"f": f})
    query = cluster[:].apply_async(write_function, mesh_file, function_file, element)
    query.wait()
    assert query.successful(), query.error
    print("".join(query.stdout))
1/2 Function written to  MyFunction.bp
2/2 Function written to  MyFunction.bp

Finally, we will read in the mesh from file and the function from the checkpoint and compare it with the analytical solution.

def verify_checkpoint(
    mesh_filename: Path, function_filename: Path, element: Tuple[str, int, Tuple[int,]]
):
    from mpi4py import MPI

    import dolfinx
    import numpy as np

    import adios4dolfinx

    with dolfinx.io.XDMFFile(MPI.COMM_WORLD, mesh_filename, "r") as xdmf:
        in_mesh = xdmf.read_mesh()
    V = dolfinx.fem.functionspace(in_mesh, element)
    u_in = dolfinx.fem.Function(V)
    adios4dolfinx.read_function(function_filename.with_suffix(".bp"), u_in, time=0.0, name="Output")

    # Compute exact interpolation
    u_ex = dolfinx.fem.Function(V)
    u_ex.interpolate(f)

    np.testing.assert_allclose(u_in.x.array, u_ex.x.array)
    print(
        "Successfully read checkpoint onto mesh on rank ",
        f"{in_mesh.comm.rank + 1}/{in_mesh.comm.size}",
    )

Verify checkpoint by comparing to exact solution

with ipp.Cluster(engines="mpi", n=5, log_level=logging.ERROR) as cluster:
    cluster[:].push({"f": f})
    query = cluster[:].apply_async(verify_checkpoint, mesh_file, function_file, element)
    query.wait()
    assert query.successful(), query.error
    print("".join(query.stdout))
Successfully read checkpoint onto mesh on rank  1/5
Successfully read checkpoint onto mesh on rank  2/5
Successfully read checkpoint onto mesh on rank  3/5
Successfully read checkpoint onto mesh on rank  4/5
Successfully read checkpoint onto mesh on rank  5/5