Mixed Poisson Demo with dolfinx_mpc periodic BC

Hello!

I am trying to solve the mixed poisson equation based on this demo with periodic boundary conditions in y-direction on the unit square with dolfinx_mpc.

tl;dr:

Non-periodic code works with (RT, DG) and (CG, CG) spaces for (\sigma, u). Periodic code produces non-periodic result with (CG, CG) spaces and does not work at all with (RT, DG) spaces.

Question: How to make it work with periodicity and (RT, DG) spaces?

I made this MWE for a non-periodic case to show that in principle my code works:

File non-periodic.py:

from mpi4py import MPI
from basix.ufl import element, mixed_element
from dolfinx import default_real_type, fem, io, mesh
from ufl import Measure, TestFunctions, TrialFunctions, div, inner
from dolfinx.fem.petsc import LinearProblem


petsc_options={
    "ksp_type": "preonly",
    "pc_type": "lu",
    "pc_factor_mat_solver_type": "mumps"
}


msh = mesh.create_unit_square(MPI.COMM_WORLD, 64, 64)

# RT and DG spaces are used. But this example also works with CG for both elements.
k = 2
VE = element("RT", msh.basix_cell(), k, shape=(msh.geometry.dim,), dtype=default_real_type)
SE = element("DG", msh.basix_cell(), k - 1, dtype=default_real_type)
ME = mixed_element([VE, SE])
V = fem.functionspace(msh, ME)


(sigma, u) = TrialFunctions(V)
(tau, v) = TestFunctions(V)


f = 1.0 # Source


dx = Measure("dx", msh)
a = inner(sigma, tau) * dx + inner(u, div(tau)) * dx + inner(div(sigma), v) * dx
L = -inner(f, v) * dx


problem = LinearProblem(a, L, petsc_options=petsc_options)
w_h = problem.solve()
sigma_h, u_h = w_h.split()


VIS = fem.functionspace(msh, ("CG", 1))
u_vis = fem.Function(VIS)
u_vis.interpolate(u_h)


with io.XDMFFile(msh.comm, "results/u.xdmf", "w") as file:
    file.write_mesh(msh)
    file.write_function(u_vis)

This code has RT elements for the \sigma-space and DG for the u-space. However chosing CG elements for both spaces also works. The result looks as follows:

Now I tried to extend the code to include periodicity, but the result looks exactly the same as in the above screenshot, i.e. the periodic BC is not applied:

File periodic.py:

from mpi4py import MPI
from basix.ufl import element, mixed_element
from dolfinx import default_real_type, fem, io, mesh
from ufl import Measure, TestFunctions, TrialFunctions, div, inner
import numpy as np
from dolfinx_mpc import LinearProblem, MultiPointConstraint


petsc_options={
    "ksp_type": "preonly",
    "pc_type": "lu",
    "pc_factor_mat_solver_type": "mumps"
}


def periodic_boundary(x):
    return np.isclose(x[1], 1.0)


def periodic_relation(x):
    out_x = np.zeros_like(x)
    out_x[0] = x[0]
    out_x[1] = 1.0 - x[1]
    return out_x


msh = mesh.create_unit_square(MPI.COMM_WORLD, 64, 64)

# Setting CG for both elements leads to a non periodic solution as if periodicity 
# was never set. Changing to RT and DG elements does not work at all because an
# error is thrown.
k = 2
VE = element("CG", msh.basix_cell(), k, shape=(msh.geometry.dim,), dtype=default_real_type)
SE = element("CG", msh.basix_cell(), k - 1, dtype=default_real_type)
ME = mixed_element([VE, SE])
V = fem.functionspace(msh, ME)


(sigma, u) = TrialFunctions(V)
(tau, v) = TestFunctions(V)


f = 1.0


dx = Measure("dx", msh)
a = inner(sigma, tau) * dx + inner(u, div(tau)) * dx + inner(div(sigma), v) * dx
L = -inner(f, v) * dx


# Periodicity in y-direction:
mpc = MultiPointConstraint(V)
mpc.create_periodic_constraint_geometrical(V.sub(0), periodic_boundary, periodic_relation, bcs = []) # sigma
mpc.create_periodic_constraint_geometrical(V.sub(1), periodic_boundary, periodic_relation, bcs = []) # u
mpc.finalize()


problem = LinearProblem(a, L, mpc, bcs = [], petsc_options=petsc_options)
w_h = problem.solve()
sigma_h, u_h = w_h.split()


VIS = fem.functionspace(msh, ("CG", 1))
u_vis = fem.Function(VIS)
u_vis.interpolate(u_h)


with io.XDMFFile(msh.comm, "results/u.xdmf", "w") as file:
    file.write_mesh(msh)
    file.write_function(u_vis)

For the periodic case I chose CG elements for both spaces because using RT and DG causes an error. You can find the error message below.

Error message:

Traceback (most recent call last):
  File "/mnt/d/sim/mixed_poisson/question/periodic.py", line 53, in <module>
    mpc.create_periodic_constraint_geometrical(V.sub(0), periodic_boundary, periodic_relation, bcs = []) # sigma
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/pbi/miniconda3/envs/fenicsx/lib/python3.13/site-packages/dolfinx_mpc/multipointconstraint.py", line 290, in create_periodic_constraint_geometrical
    mpc_data = dolfinx_mpc.cpp.mpc.create_periodic_constraint_geometrical(
        V._cpp_object, indicator, relation, bcs, scale, True
    )
RuntimeError: Cannot evaluate dof coordinates - this element does not have pointwise evaluation.

This question is related to one of my other questions:

See:

Thank you! I will have a look at it. But one more question: do you know if legacy fenics 2019.1 supports periodicity for the RT element out of the box?

I don’t know, as I’ve never tested it.