Impose a Dirichlet bc on a vector sub-space?

Hello
I have a question about imposing a Dirichlet bc on a vector sub-space
I consider a rectangle domain with mixed elements. I would like to clamp the left end.
here is the minimal code about setting the boundary conditions

import dolfinx
from dolfinx import nls
import ufl 
import numpy as np
from mpi4py import MPI
from petsc4py.PETSc import ScalarType

import dolfinx.fem.petsc
import dolfinx.nls.petsc

from dolfinx import geometry
import matplotlib.pyplot as plt
from dolfinx import fem, io, mesh
import math
from ufl import (Measure, SpatialCoordinate, TestFunctions, TrialFunctions,
                 div, exp, inner)

L = 0.166  # total length
delta = 2.0  # aspect ratio
d=L *delta  # thickness
l=0.004 # mesh length in discrete model
Delta = 0.01  # displacement at the right end
phi0 = 3  # value of phi0 at both ends

# Create domain
my_domain = dolfinx.mesh.create_rectangle(MPI.COMM_WORLD, [np.array([0, 0]), np.array([L, d])], [40,90], cell_type=dolfinx.mesh.CellType.quadrilateral)

# Define mixed mesh
u_el = ufl.VectorElement('Lagrange', my_domain.ufl_cell(), degree=1, dim=2)
phi_el = ufl.FiniteElement('Lagrange', my_domain.ufl_cell(), degree=1)
mixed_el = ufl.MixedElement([u_el, phi_el]) # mixed element
V = dolfinx.fem.FunctionSpace(my_domain, mixed_el) 

fdim = my_domain.topology.dim - 1
facets_left = mesh.locate_entities_boundary(my_domain, fdim, lambda x: np.isclose(x[0], 0.0))
Q, _ = V.sub(0).collapse()

#find the dofs
dofs_left_u = fem.locate_dofs_topological((V.sub(0), Q), fdim, facets_left)
u_D_L=np.array([0,0], dtype=ScalarType)
bc_u_left = fem.dirichletbc(u_D_L, dofs_left_u, V.sub(0))

and the notebook complains

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File ~/anaconda3/envs/fenicsx-env/lib/python3.12/site-packages/dolfinx/fem/bcs.py:175, in dirichletbc(value, dofs, V)
    174 try:
--> 175     bc = bctype(_value, dofs, V)
    176 except TypeError:

TypeError: __init__(): incompatible constructor arguments. The following argument types are supported:
    1. dolfinx.cpp.fem.DirichletBC_float64(g: numpy.ndarray[numpy.float64], dofs: numpy.ndarray[numpy.int32], V: dolfinx::fem::FunctionSpace<double>)
    2. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Constant<double>, dofs: numpy.ndarray[numpy.int32], V: dolfinx::fem::FunctionSpace<double>)
    3. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Function<double, double>, dofs: numpy.ndarray[numpy.int32])
    4. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Function<double, double>, dofs: Annotated[List[numpy.ndarray[numpy.int32]], FixedSize(2)], V: dolfinx::fem::FunctionSpace<double>)

Invoked with: array([0., 0.]), [array([   0,    1,    2,    3,   12,   13,   24,   25,   39,   40,   57,
         58,   78,   79,  102,  103,  129,  130,  159,  160,  192,  193,
        228,  229,  267,  268,  309,  310,  354,  355,  402,  403,  453,
        454,  507,  508,  564,  565,  624,  625,  687,  688,  753,  754,
        822,  823,  894,  895,  969,  970, 1047, 1048, 1128, 1129, 1212,
       1213, 1299, 1300, 1389, 1390, 1482, 1483, 1578, 1579, 1677, 1678,
       1779, 1780, 1884, 1885, 1992, 1993, 2103, 2104, 2217, 2218, 2334,
       2335, 2454, 2455, 2577, 2578, 2703, 2704, 2826, 2827, 2949, 2950,
       3072, 3073, 3195, 3196, 3318, 3319, 3441, 3442, 3564, 3565, 3687,
       3688, 3810, 3811, 3933, 3934, 4056, 4057, 4179, 4180, 4302, 4303,
       4425, 4426, 4548, 4549, 4671, 4672, 4794, 4795, 4917, 4918, 5040,
       5041, 5163, 5164, 5286, 5287, 5409, 5410, 5532, 5533, 5655, 5656,
       5778, 5779, 5901, 5902, 6024, 6025, 6147, 6148, 6270, 6271, 6393,
       6394, 6516, 6517, 6639, 6640, 6762, 6763, 6885, 6886, 7008, 7009,
       7131, 7132, 7254, 7255, 7377, 7378, 7500, 7501, 7623, 7624, 7746,
       7747, 7869, 7870, 7992, 7993, 8115, 8116, 8238, 8239, 8361, 8362,
       8484, 8485, 8607, 8608, 8730, 8731], dtype=int32), array([   0,    1,   82,   83,  164,  165,  246,  247,  328,  329,  410,
        411,  492,  493,  574,  575,  656,  657,  738,  739,  820,  821,
        902,  903,  984,  985, 1066, 1067, 1148, 1149, 1230, 1231, 1312,
       1313, 1394, 1395, 1476, 1477, 1558, 1559, 1640, 1641, 1722, 1723,
       1804, 1805, 1886, 1887, 1968, 1969, 2050, 2051, 2132, 2133, 2214,
       2215, 2296, 2297, 2378, 2379, 2460, 2461, 2542, 2543, 2624, 2625,
       2706, 2707, 2788, 2789, 2870, 2871, 2952, 2953, 3034, 3035, 3116,
       3117, 3198, 3199, 3280, 3281, 3362, 3363, 3444, 3445, 3526, 3527,
       3608, 3609, 3690, 3691, 3772, 3773, 3854, 3855, 3936, 3937, 4018,
       4019, 4100, 4101, 4182, 4183, 4264, 4265, 4346, 4347, 4428, 4429,
       4510, 4511, 4592, 4593, 4674, 4675, 4756, 4757, 4838, 4839, 4920,
       4921, 5002, 5003, 5084, 5085, 5166, 5167, 5248, 5249, 5330, 5331,
       5412, 5413, 5494, 5495, 5576, 5577, 5658, 5659, 5740, 5741, 5822,
       5823, 5904, 5905, 5986, 5987, 6068, 6069, 6150, 6151, 6232, 6233,
       6314, 6315, 6396, 6397, 6478, 6479, 6560, 6561, 6642, 6643, 6724,
       6725, 6806, 6807, 6888, 6889, 6970, 6971, 7052, 7053, 7134, 7135,
       7216, 7217, 7298, 7299, 7380, 7381], dtype=int32)], FunctionSpace(Mesh(blocked element (Basix element (P, quadrilateral, 1, gll_warped, unset, False), (2,)), 6), VectorElement(FiniteElement('Q', quadrilateral, 1), dim=2))

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
Cell In[7], line 42
     40 dofs_left_u = fem.locate_dofs_topological((V.sub(0), Q), fdim, facets_left)
     41 u_D_L=np.array([0,0], dtype=ScalarType)
---> 42 bc_u_left = fem.dirichletbc(u_D_L, dofs_left_u, V.sub(0))

File ~/anaconda3/envs/fenicsx-env/lib/python3.12/site-packages/dolfinx/fem/bcs.py:177, in dirichletbc(value, dofs, V)
    175         bc = bctype(_value, dofs, V)
    176     except TypeError:
--> 177         bc = bctype(_value, dofs, V._cpp_object)
    178 else:
    179     bc = bctype(_value, dofs)

TypeError: __init__(): incompatible constructor arguments. The following argument types are supported:
    1. dolfinx.cpp.fem.DirichletBC_float64(g: numpy.ndarray[numpy.float64], dofs: numpy.ndarray[numpy.int32], V: dolfinx::fem::FunctionSpace<double>)
    2. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Constant<double>, dofs: numpy.ndarray[numpy.int32], V: dolfinx::fem::FunctionSpace<double>)
    3. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Function<double, double>, dofs: numpy.ndarray[numpy.int32])
    4. dolfinx.cpp.fem.DirichletBC_float64(g: dolfinx::fem::Function<double, double>, dofs: Annotated[List[numpy.ndarray[numpy.int32]], FixedSize(2)], V: dolfinx::fem::FunctionSpace<double>)

Invoked with: array([0., 0.]), [array([   0,    1,    2,    3,   12,   13,   24,   25,   39,   40,   57,
         58,   78,   79,  102,  103,  129,  130,  159,  160,  192,  193,
        228,  229,  267,  268,  309,  310,  354,  355,  402,  403,  453,
        454,  507,  508,  564,  565,  624,  625,  687,  688,  753,  754,
        822,  823,  894,  895,  969,  970, 1047, 1048, 1128, 1129, 1212,
       1213, 1299, 1300, 1389, 1390, 1482, 1483, 1578, 1579, 1677, 1678,
       1779, 1780, 1884, 1885, 1992, 1993, 2103, 2104, 2217, 2218, 2334,
       2335, 2454, 2455, 2577, 2578, 2703, 2704, 2826, 2827, 2949, 2950,
       3072, 3073, 3195, 3196, 3318, 3319, 3441, 3442, 3564, 3565, 3687,
       3688, 3810, 3811, 3933, 3934, 4056, 4057, 4179, 4180, 4302, 4303,
       4425, 4426, 4548, 4549, 4671, 4672, 4794, 4795, 4917, 4918, 5040,
       5041, 5163, 5164, 5286, 5287, 5409, 5410, 5532, 5533, 5655, 5656,
       5778, 5779, 5901, 5902, 6024, 6025, 6147, 6148, 6270, 6271, 6393,
       6394, 6516, 6517, 6639, 6640, 6762, 6763, 6885, 6886, 7008, 7009,
       7131, 7132, 7254, 7255, 7377, 7378, 7500, 7501, 7623, 7624, 7746,
       7747, 7869, 7870, 7992, 7993, 8115, 8116, 8238, 8239, 8361, 8362,
       8484, 8485, 8607, 8608, 8730, 8731], dtype=int32), array([   0,    1,   82,   83,  164,  165,  246,  247,  328,  329,  410,
        411,  492,  493,  574,  575,  656,  657,  738,  739,  820,  821,
        902,  903,  984,  985, 1066, 1067, 1148, 1149, 1230, 1231, 1312,
       1313, 1394, 1395, 1476, 1477, 1558, 1559, 1640, 1641, 1722, 1723,
       1804, 1805, 1886, 1887, 1968, 1969, 2050, 2051, 2132, 2133, 2214,
       2215, 2296, 2297, 2378, 2379, 2460, 2461, 2542, 2543, 2624, 2625,
       2706, 2707, 2788, 2789, 2870, 2871, 2952, 2953, 3034, 3035, 3116,
       3117, 3198, 3199, 3280, 3281, 3362, 3363, 3444, 3445, 3526, 3527,
       3608, 3609, 3690, 3691, 3772, 3773, 3854, 3855, 3936, 3937, 4018,
       4019, 4100, 4101, 4182, 4183, 4264, 4265, 4346, 4347, 4428, 4429,
       4510, 4511, 4592, 4593, 4674, 4675, 4756, 4757, 4838, 4839, 4920,
       4921, 5002, 5003, 5084, 5085, 5166, 5167, 5248, 5249, 5330, 5331,
       5412, 5413, 5494, 5495, 5576, 5577, 5658, 5659, 5740, 5741, 5822,
       5823, 5904, 5905, 5986, 5987, 6068, 6069, 6150, 6151, 6232, 6233,
       6314, 6315, 6396, 6397, 6478, 6479, 6560, 6561, 6642, 6643, 6724,
       6725, 6806, 6807, 6888, 6889, 6970, 6971, 7052, 7053, 7134, 7135,
       7216, 7217, 7298, 7299, 7380, 7381], dtype=int32)], <dolfinx.cpp.fem.FunctionSpace_float64 object at 0x7fb7e60633f0>

Seems that it doesn’t work. Could you please tell me how to fix the error?
Thanks in advance!

Hi.

The error is in the line fem.dirichletbc(u_D_L, dofs_left_u, V.sub(0)) since you are invoking with u_D_L, which is not a Function.

The following works:

import dolfinx
from dolfinx import nls
import ufl
import numpy as np
from mpi4py import MPI
from petsc4py.PETSc import ScalarType

import dolfinx.fem.petsc
import dolfinx.nls.petsc

from dolfinx import geometry
import matplotlib.pyplot as plt
from dolfinx import fem, io, mesh
import math
from ufl import (Measure, SpatialCoordinate, TestFunctions, TrialFunctions,
                 div, exp, inner)

L = 0.166  # total length
delta = 2.0  # aspect ratio
d=L *delta  # thickness
l=0.004 # mesh length in discrete model
Delta = 0.01  # displacement at the right end
phi0 = 3  # value of phi0 at both ends

# Create domain
my_domain = dolfinx.mesh.create_rectangle(MPI.COMM_WORLD, [np.array([0, 0]), np.array([L, d])], [40,90], cell_type=dolfinx.mesh.CellType.quadrilateral)

# Define mixed mesh
u_el = ufl.VectorElement('Lagrange', my_domain.ufl_cell(), degree=1, dim=2)
phi_el = ufl.FiniteElement('Lagrange', my_domain.ufl_cell(), degree=1)
mixed_el = ufl.MixedElement([u_el, phi_el]) # mixed element
V = dolfinx.fem.FunctionSpace(my_domain, mixed_el)

fdim = my_domain.topology.dim - 1
facets_left = mesh.locate_entities_boundary(my_domain, fdim, lambda x: np.isclose(x[0], 0.0))
Q, _ = V.sub(0).collapse()

#find the dofs
dofs_left_u = fem.locate_dofs_topological((V.sub(0), Q), fdim, facets_left)
u_D_L= lambda x: np.zeros((2, x.shape[1]))
uDL = fem.Function(Q)
uDL.interpolate(u_D_L)
bc_u_left = fem.dirichletbc(uDL, dofs_left_u, V.sub(0))

Cheers

Thanks! Is it because when a mixed element space is used, we need to use a Function as an argument to dirichletbc()?
By the way. If I want to impose (-1,0) at the left end instead of clamping it. How should I change the codes?

Thanks! Is it because when a mixed element space is used, we need to use a Function as an argument to dirichletbc()?

The Function input is a requirement from the API of fem.dirichletbc():

def dirichletbc(value: typing.Union[Function, Constant, np.ndarray],
                dofs: numpy.typing.NDArray[np.int32],
                V: typing.Optional[dolfinx.fem.FunctionSpaceBase] = None) -> DirichletBC:

By the way. If I want to impose (-1,0) at the left end instead of clamping it. How should I change the codes?

Just modify the definition for u_D_L

def u_D_L(x):
    values= np.zeros((2, x.shape[1]))
    values[0, :] = -1
    return values
2 Likes