Here is a MWE:
import gmsh
import numpy as np
import dolfinx as df
from mpi4py import MPI
import dolfinx_mpc as df_mpc
###############################################################
# Set up rectangular mesh
Lx,Ly = [1,2]
gmsh.initialize()
gmsh.model.add('periodic rectangle')
gmsh.model.occ.addRectangle(0,0,0,Lx,Ly)
gmsh.model.occ.synchronize()
cells = gmsh.model.getEntities(2)
tagPhys = 1+np.arange(len(cells))
gmsh.model.addPhysicalGroup(2,tagPhys,name=f'2D Domain')
gmsh.model.mesh.generate(2)
df_mesh, _, _ = df.io.gmshio.model_to_mesh(gmsh.model, MPI.COMM_WORLD, 0, 2)
###############################################################
# Define periodic constraint data
pbc_EW_slave_tag = 2
pbc_EW_is_slave = lambda x: np.isclose(x[0],Lx) # identifier for East-West slave boundary
pbc_EW_is_master = lambda x: np.isclose(x[0],0) # identifier for East-West master boundary
facetsEW = df.mesh.locate_entities_boundary(df_mesh, 1, pbc_EW_is_slave)
arg_sortEW = np.argsort(facetsEW)
pbc_EW_mt = df.mesh.meshtags(df_mesh, 1, facetsEW[arg_sortEW], np.full(len(facetsEW), pbc_EW_slave_tag, dtype=np.int32))
def pbc_EW_s2m_map(x):
out_x = np.zeros(x.shape)
out_x[0] = x[0] - Lx
out_x[1] = x[1]
out_x[2] = x[2]
return out_x
###############################################################
# mpc implementation #1
Va = df.fem.VectorFunctionSpace(df_mesh, ("DG", 1))
mpc_a = df_mpc.MultiPointConstraint(Va)
if Va.num_sub_spaces > 0: # For mixed functionspaces or vector-valued functionspaces
for i in range(Va.num_sub_spaces):
mpc_a.create_periodic_constraint_topological(V=Va.sub(i), meshtag=pbc_EW_mt, tag=pbc_EW_slave_tag, relation=pbc_EW_s2m_map, bcs=[])
else:
mpc_a.create_periodic_constraint_topological(V=Va, meshtag=pbc_EW_mt, tag=pbc_EW_slave_tag, relation=pbc_EW_s2m_map, bcs=[])
###############################################################
# mpc implementation #2
Vb = df.fem.FunctionSpace(df_mesh,("N1E",1))
mpc_b = df_mpc.MultiPointConstraint(Vb)
if Vb.num_sub_spaces > 0: # For mixed functionspaces or vector-valued functionspaces
for i in range(Vb.num_sub_spaces):
mpc_b.create_periodic_constraint_topological(V=Vb.sub(i), meshtag=pbc_EW_mt, tag=pbc_EW_slave_tag, relation=pbc_EW_s2m_map, bcs=[])
else:
mpc_b.create_periodic_constraint_topological(V=Vb, meshtag=pbc_EW_mt, tag=pbc_EW_slave_tag, relation=pbc_EW_s2m_map, bcs=[])
While the VectorFunctionSpace Va is handled correctly by dolfinx_mpc, functionspace Vb throws the following error:
Traceback (most recent call last):
File "mwe_question.py", line 56, in <module>
mpc_b.create_periodic_constraint_topological(V=Vb, meshtag=pbc_EW_mt, tag=pbc_EW_slave_tag, relation=pbc_EW_s2m_map, bcs=[])
File "/usr/local/anaconda3/envs/env-dolfinx/lib/python3.10/site-packages/dolfinx_mpc/multipointconstraint.py", line 119, in create_periodic_constraint_topological
mpc_data = dolfinx_mpc.cpp.mpc.create_periodic_constraint_topological(
RuntimeError: Periodic conditions for vector valued spaces are not implemented
I see that Vb.num_sub_spaces = 0, and Vb.element.value_shape=[2]. Is there a straightforward way to use dolfinx_mpc for functionspaces like Vb (i.e. functionspaces that are more “implicitly” vector-valued)? Naively, this would appear straightforward at least in cases where periodic mesh faces are conforming. Is such a feature available?
I am using dolfinx 0.6.0 and dolfinx_mpc 0.6.1, both installed via conda-forge.