How to impose a Dirichlet bc on a vector sub-space?

I have a function space, created from a MixedElement, consisting of a number of scalar function spaces and 1 vector function space. I can apply a Dirichlet boundary condition to the scalar function spaces, but I haven’t been able to do the same for the vector function space.

A MWE is:

import ufl
import numpy as np

from mpi4py import MPI
from dolfinx import fem, mesh
from petsc4py.PETSc import ScalarType

# dolfinx version is 0.4.2.0 - run with docker 
domain = mesh.create_unit_square(MPI.COMM_WORLD, 20, 20, mesh.CellType.triangle)

aFE = ufl.FiniteElement("CG", domain.ufl_cell(), 1)
bFE = ufl.VectorElement("CG", domain.ufl_cell(), 1)
ME = fem.FunctionSpace(domain, ufl.MixedElement([aFE, bFE]))

# Determine boundary facets
tdim = domain.topology.dim
fdim = tdim - 1
domain.topology.create_connectivity(fdim, tdim)
boundary_facets = np.flatnonzero(mesh.compute_boundary_facets(domain.topology))

# Dirichlet bc for a - no errors 
boundary_dofs_a = fem.locate_dofs_topological(ME.sub(0), fdim, boundary_facets)
bc_a = fem.dirichletbc(ScalarType(1.0), boundary_dofs_a, ME.sub(0))

# Dirichlet bc for b
b_D = np.array((1.0,)*domain.geometry.dim, dtype=ScalarType)
boundary_dofs_b = fem.locate_dofs_topological(ME.sub(1), fdim, boundary_facets)
# The below line results in a runtime error
bc_b = fem.dirichletbc(b_D, boundary_dofs_b, ME.sub(1))

This results in the runtime error:

RuntimeError: Creating a DirichletBC using a Constant is not supported when the Constant size is not equal to the block size of the constrained (sub-)space. Use a Function to create the DirichletBC.

I have tried using a function instead but with no success. The full error message from the MWE is

Traceback (most recent call last):
  File "/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/fem/bcs.py", line 136, in __init__
    super().__init__(_value, dofs, V)
TypeError: __init__(): incompatible constructor arguments. The following argument types are supported:
    1. dolfinx.cpp.fem.DirichletBC_float64(g: float, dofs: numpy.ndarray[numpy.int32], V: dolfinx::fem::FunctionSpace)
    2. dolfinx.cpp.fem.DirichletBC_float64(g: numpy.ndarray[numpy.float64], dofs: numpy.ndarray[numpy.int32], V: dolfinx::fem::FunctionSpace)
    3. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Constant<double>, dofs: numpy.ndarray[numpy.int32], V: dolfinx::fem::FunctionSpace)
    4. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Function<double>, dofs: numpy.ndarray[numpy.int32])
    5. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Function<double>, dofs: List[numpy.ndarray[numpy.int32][2]], V: dolfinx::fem::FunctionSpace)

Invoked with: array([1., 1.]), array([   3,    4,    5,    6,    7,    8,   13,   14,   16,   17,   25,
         26,   28,   29,   40,   41,   43,   44,   58,   59,   61,   62,
         79,   80,   82,   83,  103,  104,  106,  107,  130,  131,  133,
        134,  160,  161,  163,  164,  193,  194,  196,  197,  229,  230,
        232,  233,  268,  269,  271,  272,  310,  311,  313,  314,  355,
        356,  358,  359,  403,  404,  406,  407,  454,  455,  457,  458,
        508,  509,  511,  512,  565,  566,  568,  569,  625,  626,  628,
        629,  688,  689,  691,  692,  694,  695,  751,  752,  754,  755,
        808,  809,  811,  812,  862,  863,  865,  866,  913,  914,  916,
        917,  961,  962,  964,  965, 1006, 1007, 1009, 1010, 1048, 1049,
       1051, 1052, 1087, 1088, 1090, 1091, 1123, 1124, 1126, 1127, 1156,
       1157, 1159, 1160, 1186, 1187, 1189, 1190, 1213, 1214, 1216, 1217,
       1237, 1238, 1240, 1241, 1258, 1259, 1261, 1262, 1276, 1277, 1279,
       1280, 1291, 1292, 1294, 1295, 1303, 1304, 1306, 1307, 1312, 1313,
       1315, 1316, 1318, 1319, 1321, 1322], dtype=int32), FunctionSpace(Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 0), VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/root/fenicsx/thickness/testFS.py", line 58, in <module>
    bc_b = fem.dirichletbc(b_D, boundary_dofs_b, ME.sub(1))
  File "/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/fem/bcs.py", line 181, in dirichletbc
    return formcls(value, dofs, V)
  File "/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/fem/bcs.py", line 138, in __init__
    super().__init__(_value, dofs, V._cpp_object)
RuntimeError: Creating a DirichletBC using a Constant is not supported when the Constant size is not equal to the block size of the constrained (sub-)space. Use a Function to create the DirichletBC.

Thanks in advance!

As the error message says, the first input has to be a function.
In your code you invoke it with a Constant value:

V1, _ = ME.sub(1).collapse()
u_D = fem.Function(V1)
u_D.x.array[:] =1

boundary_dofs_b = fem.locate_dofs_topological((ME.sub(1), V1), fdim, boundary_facets)
bc_b = fem.dirichletbc(u_D, boundary_dofs_b, ME.sub(1))
3 Likes

Hi dokken,

I have a question: This code seems you fix the boundary by setting the first component of displacements by 1 and the second component free. How to write the codes if I want to impose (1.0,1.0) at the boundary nodes?

See for instance: Implementation — FEniCSx tutorial

Thanks dokken
this works when if I use a single-element space. When I have a mixed-function space it doesn’t work:
“u_D = np.array([0, 0], dtype=default_scalar_type)
bc = fem.dirichletbc(u_D, boundary_dofs_b, ME.sub(1))”

Without a minimal reproducible example, it is quite tedious for me to help you.
You should use something along the lines of what is written in

Thanks! I create a new post. Please seehttps://fenicsproject.discourse.group/t/impose-a-dirichlet-bc-on-a-vector-sub-space/14346