How to impose spatially varying dirichletbc boundary conditions for one direction in a linear elasticity problem?

I want to impose spatially varing displacement boundary condition on all facets of the unit cube in x-direction. Here is the displacement function f\left( x,y,z \right) =\frac{1}{8}\left[ 1+\left( \frac{2}{l}x-1 \right) \right] \left[ 1-\left( \frac{2}{l}y-1 \right) \right] \left[ 1+\left( \frac{2}{l}z-1 \right) \right].
And my code is as follw:

import dolfinx
from mpi4py import MPI
import numpy as np
import ufl
from functools import partial
from dolfinx import default_scalar_type

def box_like_domain(l, w, h, nx, ny, nz, cell_type) -> dolfinx.mesh:
"""
Create a box-like mesh domain.
Args:
l (float): the length of the box-like domain.
w (float): the width of the box-like domain.
h (float): the height of the box-like domain.
nx (int): the number of grids in the x-axis.
ny (int): the number of grids in the y-axis.
nz (int): the number of grids in the z-axis.
cell_type (str):  Mesh cell type, like "tetrahedron", "pyramid", "prism", "hexahedron"

Returns:
mesh
"""
cell_type_attr = getattr(dolfinx.mesh.CellType,
cell_type)  # get the attribute named as cell_type of dolfinx.mesh.CellType
mesh = dolfinx.mesh.create_box(comm=MPI.COMM_WORLD, points=[[0, 0, 0], [l, w, h]], n=[nx, ny, nz],
cell_type=cell_type_attr)
return mesh

def disp_bc(x, l, node_i):
"""
Boundary condition function
Args:
node_i (int): node number
x (np.ndarray): node coordinates array
l (float): side length

Returns:

"""
nodes = [(0, 0, 0), (l, 0, 0), (l, l, 0), (0, l, 0),
(0, 0, l), (l, 0, l), (l, l, l), (0, l, l)]
disp = (1 + (2 * nodes[node_i][0] / l - 1) * (2 * x[0] / l - 1)) * (
1 + (2 * nodes[node_i][1] / l - 1) * (2 * x[1] / l - 1)) * (
1 + (2 * nodes[node_i][2] / l - 1) * (2 * x[2] / l - 1)) / 8
return disp

# create mesh
cubic_mesh = box_like_domain(l=1, w=1, h=1, nx=10, ny=10, nz=10, cell_type="hexahedron")
# define the parameters
mu = 1  # lame‘s elasticity parameter
beta = 1.25
lambda_ = beta  # lame‘s elasticity parameter
rho = 1     # density
# create funtion space on cubic mesh
element = ufl.VectorElement("Lagrange", cubic_mesh.ufl_cell(), 1)   # create element
V = dolfinx.fem.functionspace(mesh=cubic_mesh, element=element) # create function space
# Define the boundary condition
fdim = cubic_mesh.topology.dim - 1  # facet dimension
left_f = dolfinx.mesh.locate_entities_boundary(mesh=cubic_mesh, dim=fdim, marker=lambda x: np.isclose(x[0],
0)) # left facet
right_f = dolfinx.mesh.locate_entities_boundary(mesh=cubic_mesh, dim=fdim, marker=lambda x: np.isclose(x[0],
1)) # right facet
front_f = dolfinx.mesh.locate_entities_boundary(mesh=cubic_mesh, dim=fdim, marker=lambda x: np.isclose(x[1],
0)) # front facet
rear_f = dolfinx.mesh.locate_entities_boundary(mesh=cubic_mesh, dim=fdim, marker=lambda x: np.isclose(x[1],
1)) # rear facet
lower_f = dolfinx.mesh.locate_entities_boundary(mesh=cubic_mesh, dim=fdim, marker=lambda x: np.isclose(x[2],
0))
top_f = dolfinx.mesh.locate_entities_boundary(mesh=cubic_mesh, dim=fdim, marker=lambda x: np.isclose(x[2],
1))  # top facet
all_fs = np.hstack((left_f, right_f, front_f, rear_f, lower_f, top_f))
y_bc = dolfinx.fem.dirichletbc(value=default_scalar_type(0),
dofs=dolfinx.fem.locate_dofs_topological(V.sub(1), fdim, all_fs), V=V.sub(1))
z_bc = dolfinx.fem.dirichletbc(value=default_scalar_type(0),
dofs=dolfinx.fem.locate_dofs_topological(V.sub(2), fdim, all_fs), V=V.sub(2))

x = ufl.SpatialCoordinate(cubic_mesh)
# u_bc = dolfinx.fem.Function(V)
disp_bc_partial = partial(disp_bc, node_i=5, l=1)
# u_bc.sub(0).interpolate(disp_bc_partial)
u_bc = disp_bc_partial(x)
x_bc = dolfinx.fem.dirichletbc(value=u_bc.sub(0),
dofs=dolfinx.fem.locate_dofs_topological(V, fdim, all_fs), V=V.sub(0))


The output message is:

Traceback (most recent call last):
File "/mnt/d/BaiduNetdiskWorkspace/MultiscaleDynamicTOP/code/FEniCSBasedProject/3D_test/test.py", line 100, in <module>
x_bc = dolfinx.fem.dirichletbc(value=u_bc.sub(0),
AttributeError: 'Division' object has no attribute 'sub'


When I remove sub(0), he gets the following error:

Traceback (most recent call last):
File "/usr/lib/petsc/lib/python3/dist-packages/dolfinx/fem/bcs.py", line 150, in dirichletbc
dtype = value.dtype
AttributeError: 'Division' object has no attribute 'dtype'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/mnt/d/BaiduNetdiskWorkspace/MultiscaleDynamicTOP/code/FEniCSBasedProject/3D_test/test.py", line 100, in <module>
x_bc = dolfinx.fem.dirichletbc(value=u_bc,
File "/usr/lib/petsc/lib/python3/dist-packages/dolfinx/fem/bcs.py", line 162, in dirichletbc
raise AttributeError("Boundary condition value must have a dtype attribute.")
AttributeError: Boundary condition value must have a dtype attribute.


See in
https://bleyerj.github.io/comet-fenicsx/intro/linear_elasticity/linear_elasticity.html#changing-boundary-conditions
Just interpolate your expression into the uD_y function defined on the collapsed subspace.

Thank you for your suggestion!I haven’t tried the method you gave, but solved the problem by doing the following:

u_bc = dolfinx.fem.Function(V)
disp_bc_partial = partial(disp_bc, node_i=5, l=1)
u_bc.sub(0).interpolate(disp_bc_partial) # This is my function expression of BC
x_bc = dolfinx.fem.dirichletbc(value=u_bc.sub(0),
dofs=dolfinx.fem.locate_dofs_topological(V.sub(0), fdim, all_fs))


It works well. But I still have some confussion that when I add the Parameter V of dolfinx.fem.dirichletbc. Like：

u_bc = dolfinx.fem.Function(V)
disp_bc_partial = partial(disp_bc, node_i=5, l=1)
u_bc.sub(0).interpolate(disp_bc_partial) # This is my function expression of BC
x_bc = dolfinx.fem.dirichletbc(value=u_bc.sub(0),
dofs=dolfinx.fem.locate_dofs_topological(V.sub(0), fdim, all_fs), V=V.sub(0))


It will output errors like:

Traceback (most recent call last):
File "/usr/lib/petsc/lib/python3/dist-packages/dolfinx/fem/bcs.py", line 175, in dirichletbc
bc = bctype(_value, dofs, V)
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: List[numpy.ndarray[numpy.int32][2]], V: dolfinx::fem::FunctionSpace<double>)

Invoked with: <dolfinx.cpp.fem.Function_float64 object at 0x7fc0f120c030>, array([   0,    3,    6,    9,   12,   15,   18,   24,   27,   30,   36,
39,   42,   48,   51,   54,   60,   63,   66,   72,   78,   84,
87,   90,   96,  102,  105,  108,  114,  117,  120,  126,  132,
138,  147,  153,  156,  159,  165,  171,  177,  180,  183,  189,
192,  195,  201,  207,  213,  222,  228,  240,  246,  249,  252,
258,  264,  270,  276,  279,  282,  288,  291,  294,  300,  306,
312,  321,  327,  339,  345,  360,  366,  369,  372,  378,  384,
390,  396,  402,  405,  408,  414,  417,  420,  426,  432,  438,
447,  453,  465,  471,  486,  492,  510,  516,  519,  522,  528,
534,  540,  546,  552,  558,  561,  564,  570,  573,  576,  582,
588,  594,  603,  609,  621,  627,  642,  648,  666,  672,  693,
699,  702,  705,  711,  717,  723,  729,  735,  741,  747,  750,
753,  759,  762,  765,  771,  777,  783,  792,  798,  810,  816,
831,  837,  855,  861,  882,  888,  912,  918,  921,  924,  930,
936,  942,  948,  954,  960,  966,  972,  975,  978,  984,  987,
990,  993,  996, 1002, 1008, 1017, 1023, 1035, 1041, 1056, 1062,
1080, 1086, 1107, 1113, 1137, 1143, 1170, 1176, 1179, 1182, 1185,
1188, 1194, 1200, 1206, 1212, 1218, 1224, 1230, 1236, 1239, 1242,
1245, 1248, 1251, 1254, 1257, 1260, 1269, 1275, 1287, 1293, 1308,
1314, 1332, 1338, 1359, 1365, 1389, 1395, 1422, 1428, 1431, 1458,
1461, 1464, 1467, 1470, 1476, 1482, 1488, 1494, 1500, 1506, 1512,
1515, 1518, 1521, 1524, 1527, 1530, 1533, 1545, 1551, 1566, 1572,
1590, 1596, 1617, 1623, 1647, 1653, 1680, 1686, 1689, 1716, 1719,
1722, 1746, 1749, 1752, 1755, 1761, 1767, 1773, 1779, 1785, 1791,
1794, 1797, 1800, 1803, 1806, 1809, 1812, 1815, 1830, 1836, 1854,
1860, 1881, 1887, 1911, 1917, 1944, 1950, 1953, 1980, 1983, 1986,
2010, 2013, 2034, 2037, 2040, 2043, 2049, 2055, 2061, 2067, 2073,
2076, 2079, 2082, 2085, 2088, 2091, 2094, 2097, 2100, 2118, 2124,
2145, 2151, 2175, 2181, 2208, 2214, 2217, 2244, 2247, 2250, 2274,
2277, 2298, 2301, 2319, 2322, 2325, 2328, 2334, 2340, 2346, 2352,
2355, 2358, 2361, 2364, 2367, 2370, 2373, 2376, 2379, 2382, 2403,
2409, 2433, 2439, 2466, 2472, 2475, 2502, 2505, 2508, 2532, 2535,
2556, 2559, 2577, 2580, 2595, 2598, 2601, 2604, 2610, 2616, 2622,
2625, 2628, 2631, 2634, 2637, 2640, 2643, 2646, 2649, 2652, 2655,
2679, 2685, 2712, 2718, 2721, 2748, 2751, 2754, 2778, 2781, 2802,
2805, 2823, 2826, 2841, 2844, 2856, 2859, 2862, 2865, 2871, 2877,
2880, 2883, 2886, 2889, 2892, 2895, 2898, 2901, 2904, 2907, 2910,
2913, 2940, 2946, 2949, 2976, 2979, 2982, 3006, 3009, 3030, 3033,
3051, 3054, 3069, 3072, 3084, 3087, 3096, 3099, 3102, 3105, 3111,
3114, 3117, 3120, 3123, 3126, 3129, 3132, 3135, 3138, 3141, 3144,
3147, 3150, 3153, 3180, 3183, 3186, 3210, 3213, 3234, 3237, 3255,
3258, 3273, 3276, 3288, 3291, 3300, 3303, 3309, 3312, 3315, 3318,
3321, 3324, 3327, 3330, 3333, 3336, 3339, 3342, 3345, 3348, 3351,
3354, 3357, 3360, 3384, 3387, 3408, 3411, 3429, 3432, 3447, 3450,
3462, 3465, 3474, 3477, 3483, 3486, 3489, 3492, 3495, 3498, 3501,
3504, 3507, 3510, 3513, 3516, 3519, 3522, 3525, 3546, 3549, 3567,
3570, 3585, 3588, 3600, 3603, 3612, 3615, 3621, 3624, 3627, 3630,
3633, 3636, 3639, 3642, 3645, 3648, 3651, 3654, 3657, 3675, 3678,
3693, 3696, 3708, 3711, 3720, 3723, 3729, 3732, 3735, 3738, 3741,
3744, 3747, 3750, 3753, 3756, 3759, 3762, 3777, 3780, 3792, 3795,
3804, 3807, 3813, 3816, 3819, 3822, 3825, 3828, 3831, 3834, 3837,
3840, 3843, 3855, 3858, 3867, 3870, 3876, 3879, 3882, 3885, 3888,
3891, 3894, 3897, 3900, 3903, 3912, 3915, 3921, 3924, 3927, 3930,
3933, 3936, 3939, 3942, 3945, 3951, 3954, 3957, 3960, 3963, 3966,
3969, 3972, 3975, 3978, 3981, 3984, 3987, 3990], dtype=int32), FunctionSpace(Mesh(blocked element (Basix element (P, hexahedron, 1, gll_warped, unset, False), (3,)), 0), FiniteElement('Q', hexahedron, 1))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/mnt/d/BaiduNetdiskWorkspace/MultiscaleDynamicTOP/code/FEniCSBasedProject/3D_test/Unit_cubic.py", line 119, in <module>
main()
File "/mnt/d/BaiduNetdiskWorkspace/MultiscaleDynamicTOP/code/FEniCSBasedProject/3D_test/Unit_cubic.py", line 99, in main
x_bc = dolfinx.fem.dirichletbc(value=u_bc.sub(0),
File "/usr/lib/petsc/lib/python3/dist-packages/dolfinx/fem/bcs.py", line 177, in dirichletbc
bc = bctype(_value, dofs, V._cpp_object)
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: List[numpy.ndarray[numpy.int32][2]], V: dolfinx::fem::FunctionSpace<double>)

Invoked with: <dolfinx.cpp.fem.Function_float64 object at 0x7fc0f120c030>, array([   0,    3,    6,    9,   12,   15,   18,   24,   27,   30,   36,
39,   42,   48,   51,   54,   60,   63,   66,   72,   78,   84,
87,   90,   96,  102,  105,  108,  114,  117,  120,  126,  132,
138,  147,  153,  156,  159,  165,  171,  177,  180,  183,  189,
192,  195,  201,  207,  213,  222,  228,  240,  246,  249,  252,
258,  264,  270,  276,  279,  282,  288,  291,  294,  300,  306,
312,  321,  327,  339,  345,  360,  366,  369,  372,  378,  384,
390,  396,  402,  405,  408,  414,  417,  420,  426,  432,  438,
447,  453,  465,  471,  486,  492,  510,  516,  519,  522,  528,
534,  540,  546,  552,  558,  561,  564,  570,  573,  576,  582,
588,  594,  603,  609,  621,  627,  642,  648,  666,  672,  693,
699,  702,  705,  711,  717,  723,  729,  735,  741,  747,  750,
753,  759,  762,  765,  771,  777,  783,  792,  798,  810,  816,
831,  837,  855,  861,  882,  888,  912,  918,  921,  924,  930,
936,  942,  948,  954,  960,  966,  972,  975,  978,  984,  987,
990,  993,  996, 1002, 1008, 1017, 1023, 1035, 1041, 1056, 1062,
1080, 1086, 1107, 1113, 1137, 1143, 1170, 1176, 1179, 1182, 1185,
1188, 1194, 1200, 1206, 1212, 1218, 1224, 1230, 1236, 1239, 1242,
1245, 1248, 1251, 1254, 1257, 1260, 1269, 1275, 1287, 1293, 1308,
1314, 1332, 1338, 1359, 1365, 1389, 1395, 1422, 1428, 1431, 1458,
1461, 1464, 1467, 1470, 1476, 1482, 1488, 1494, 1500, 1506, 1512,
1515, 1518, 1521, 1524, 1527, 1530, 1533, 1545, 1551, 1566, 1572,
1590, 1596, 1617, 1623, 1647, 1653, 1680, 1686, 1689, 1716, 1719,
1722, 1746, 1749, 1752, 1755, 1761, 1767, 1773, 1779, 1785, 1791,
1794, 1797, 1800, 1803, 1806, 1809, 1812, 1815, 1830, 1836, 1854,
1860, 1881, 1887, 1911, 1917, 1944, 1950, 1953, 1980, 1983, 1986,
2010, 2013, 2034, 2037, 2040, 2043, 2049, 2055, 2061, 2067, 2073,
2076, 2079, 2082, 2085, 2088, 2091, 2094, 2097, 2100, 2118, 2124,
2145, 2151, 2175, 2181, 2208, 2214, 2217, 2244, 2247, 2250, 2274,
2277, 2298, 2301, 2319, 2322, 2325, 2328, 2334, 2340, 2346, 2352,
2355, 2358, 2361, 2364, 2367, 2370, 2373, 2376, 2379, 2382, 2403,
2409, 2433, 2439, 2466, 2472, 2475, 2502, 2505, 2508, 2532, 2535,
2556, 2559, 2577, 2580, 2595, 2598, 2601, 2604, 2610, 2616, 2622,
2625, 2628, 2631, 2634, 2637, 2640, 2643, 2646, 2649, 2652, 2655,
2679, 2685, 2712, 2718, 2721, 2748, 2751, 2754, 2778, 2781, 2802,
2805, 2823, 2826, 2841, 2844, 2856, 2859, 2862, 2865, 2871, 2877,
2880, 2883, 2886, 2889, 2892, 2895, 2898, 2901, 2904, 2907, 2910,
2913, 2940, 2946, 2949, 2976, 2979, 2982, 3006, 3009, 3030, 3033,
3051, 3054, 3069, 3072, 3084, 3087, 3096, 3099, 3102, 3105, 3111,
3114, 3117, 3120, 3123, 3126, 3129, 3132, 3135, 3138, 3141, 3144,
3147, 3150, 3153, 3180, 3183, 3186, 3210, 3213, 3234, 3237, 3255,
3258, 3273, 3276, 3288, 3291, 3300, 3303, 3309, 3312, 3315, 3318,
3321, 3324, 3327, 3330, 3333, 3336, 3339, 3342, 3345, 3348, 3351,
3354, 3357, 3360, 3384, 3387, 3408, 3411, 3429, 3432, 3447, 3450,
3462, 3465, 3474, 3477, 3483, 3486, 3489, 3492, 3495, 3498, 3501,
3504, 3507, 3510, 3513, 3516, 3519, 3522, 3525, 3546, 3549, 3567,
3570, 3585, 3588, 3600, 3603, 3612, 3615, 3621, 3624, 3627, 3630,
3633, 3636, 3639, 3642, 3645, 3648, 3651, 3654, 3657, 3675, 3678,
3693, 3696, 3708, 3711, 3720, 3723, 3729, 3732, 3735, 3738, 3741,
3744, 3747, 3750, 3753, 3756, 3759, 3762, 3777, 3780, 3792, 3795,
3804, 3807, 3813, 3816, 3819, 3822, 3825, 3828, 3831, 3834, 3837,
3840, 3843, 3855, 3858, 3867, 3870, 3876, 3879, 3882, 3885, 3888,
3891, 3894, 3897, 3900, 3903, 3912, 3915, 3921, 3924, 3927, 3930,
3933, 3936, 3939, 3942, 3945, 3951, 3954, 3957, 3960, 3963, 3966,
3969, 3972, 3975, 3978, 3981, 3984, 3987, 3990], dtype=int32), <dolfinx.cpp.fem.FunctionSpace_float64 object at 0x7fc0a4b27a30>


This is because the last keyword argument V is only used when you collapse a function into a sub space. Then you send in two arguments in locate_dofs_topological, then uncollapsed and collapsed subspace. This returns you two arrays of degrees of freedom in each of these spaces.

Since the collapsed function has no direct relationship to its parent object, one supplied the subspace to ensure that the BCs are imposed on the correct part of the variational form

Thank you very much, Mr. Dokken! But I didn’t quite understand what you meant especially about the use of methods dolfinx.fem.locate_dofs_topological. May I ask you to elaborate a bit more?

And I still have another question that‘s why the follwing codes work:

y_bc = dolfinx.fem.dirichletbc(value=default_scalar_type(0),
dofs=dolfinx.fem.locate_dofs_topological(V.sub(1), fdim, all_fs), V=V.sub(1))
z_bc = dolfinx.fem.dirichletbc(value=default_scalar_type(0),
dofs=dolfinx.fem.locate_dofs_topological(V.sub(2), fdim, all_fs), V=V.sub(2))


But the code on x-direction doesn’t work.

x_bc = dolfinx.fem.dirichletbc(value=u_bc.sub(0),
dofs=dolfinx.fem.locate_dofs_topological(V.sub(0), fdim, all_fs), V=V.sub(0))


Finally thank you very much for your patience!

Thank you so much Mr. dokken! Previously it was because of my own lack of understanding of the functions dolfinx.fem.dirichletbc and dolfinx.fem.locate_dofs_topological themselves, which caused me to wonder. Now I have understood what you mean.