Issue with locate_dofs_geometrical using V.sub(0).collapse

Hello,

I try to apply boundary on one direction and let the second direction free like shown in the picture one :


By symmetric, I can reduce the model to :
image

I want to apply a displacement Ux(t) but I get trouble to let free the displacement the y-direction. I find example where they put uy = 0. Otherwise, there is the other option with (ref) using V.sub(0).collapse() but I get error message with the last method.
I am using the version 0.4.1 from conda and this is a part of my script :

from dolfinx import log, io, mesh, fem, cpp, geometry
from petsc4py import PETSc
from mpi4py import MPI
import ufl
import numpy as np

log.set_log_level(log.LogLevel.OFF)

use_lumped_mass = False


#loading

t_start, t_end, nsteps = 0.0, 3., 5*800
dt = t_end/nsteps 
steps = np.linspace(t_start, t_end, nsteps)

# Geometry & Mesh

Lx, Ly = 1.0, .1 # Dimensions of the beam
ny = 10
nx = 10*ny
msh = mesh.create_rectangle(MPI.COMM_WORLD , [[0.,0.],[Lx,Ly]], [nx,ny], mesh.CellType.quadrilateral)

ndim = msh.topology.dim
fdim = ndim - 1

# Material Parameters

E, nu     = fem.Constant(msh, PETSc.ScalarType(10)), fem.Constant(msh, PETSc.ScalarType(0.3)) #[MPa]
rho       = fem.Constant(msh, PETSc.ScalarType(1.))
mu        = E / (2.0*(1.0 + nu)) # [MPa]
lmbda     = E * nu / ((1.0 + nu)* (1.0 - 2.0*nu))
K0        = lmbda+2./3.*mu

# Space function

V_element=ufl.VectorElement("CG",msh.ufl_cell(),1)
V=fem.FunctionSpace(msh,V_element)


# Facets / Geometry

def right(x):
    return np.isclose(x[0], Lx)

def left(x):
    return np.isclose(x[0], 0.0)

def point(x):
    return  np.logical_and( 0.001 < x[0], x[1] < 0.001)

facet_right   = mesh.locate_entities(msh, fdim, right)
facet_left    = mesh.locate_entities(msh, fdim, left )
point_origin  = mesh.locate_entities(msh, fdim-1,point)
                            
                            

#facet_left_dofs = fem.locate_dofs_geometrical(V,left)
#facet_right_dofs = fem.locate_dofs_topological(V, fdim, facet_right)

#facet_left_dofs = dolfinx.fem.locate_dofs_geometrical((V.sub(0), V.sub(0).collapse()), left)
facet_right_dofs = fem.locate_dofs_geometrical((V.sub(0), V.sub(0).collapse()), right)
facet_left_dofs = fem.locate_dofs_topological(V.sub(0), fdim, facet_left)
point_origin_dofs = fem.locate_dofs_geometrical(V,point)

facet_indices, facet_markers = [], []
facet_indices.append(facet_right)
facet_indices.append(facet_left)
facet_indices = np.array(np.hstack(facet_indices), dtype=np.int32)
sorted_facets = np.argsort(facet_indices)

facet_markers.append(np.full(len(facet_right ), 1))
facet_markers.append(np.full(len(facet_left ), 2))
facet_markers = np.array(np.hstack(facet_markers), dtype=np.int32)

facet_tag = mesh.meshtags(msh, fdim, facet_indices[sorted_facets], facet_markers[sorted_facets])



# BOUNDARY CONDITIONS
u_zero_xy = np.array((0. ,)*msh.geometry.dim, dtype=PETSc.ScalarType) 

# u_app = fem.Function(V.sub(0).collapse())
# with u_app.vector.localForm() as bc_local:
#     bc_local.set(0.0)

t = 0.
tc = 0.1
tr_max = 1.0

class Load():
    def __init__(self,t):
        self.t = t

    def __call__(self,x):
        values = np.zeros((ndim, x.shape[1]),dtype=PETSc.ScalarType)
        if t <= tc:
            values[0] = tr_max/tc * self.t
        else:
            values[0] = tr_max/tc
        return values
u_app_func = fem.Function(V)
u_app = Load(t)
u_app_func.interpolate(u_app)


bc_left = fem.dirichletbc(fem.Constant(msh, 0.0),facet_left_dofs, V.sub(0))
bc_point_origin = fem.dirichletbc(fem.Constant(msh, (0.0,0.0)), point_origin_dofs, V)
bc_right = fem.dirichletbc( u_app_func, facet_right_dofs)
bcu = [bc_left,bc_point_origin, bc_right]

The error message :

In [13]: facet_right_dofs = fem.locate_dofs_geometrical((V.sub(0), V.sub(0).collapse()), right)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [13], in <cell line: 1>()
----> 1 facet_right_dofs = fem.locate_dofs_geometrical((V.sub(0), V.sub(0).collapse()), right)

File ~/CODE_PROGRAMME/anaconda-2022/anaconda3_2022/envs/ipython-env/lib/python3.10/site-packages/dolfinx/fem/bcs.py:57, in locate_dofs_geometrical(V, marker)
     55         except AttributeError:
     56             _V.append(space)
---> 57     return _cpp.fem.locate_dofs_geometrical(_V, marker)
     58 else:
     59     try:

TypeError: locate_dofs_geometrical(): incompatible function arguments. The following argument types are supported:
    1. (V: List[dolfinx::fem::FunctionSpace], marker: Callable[[numpy.ndarray[numpy.float64]], numpy.ndarray[bool]]) -> List[numpy.ndarray[2]]
    2. (V: dolfinx::fem::FunctionSpace, marker: Callable[[numpy.ndarray[numpy.float64]], numpy.ndarray[bool]]) -> numpy.ndarray[numpy.int32]

Invoked with: [<dolfinx.cpp.fem.FunctionSpace object at 0x2aee0cdf1b30>, (FunctionSpace(Mesh(VectorElement(FiniteElement('Q', quadrilateral, 1), dim=2), 0), FiniteElement('Q', quadrilateral, 1)), [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552

I get the other trouble when I do fem.Function(V.sub(0).collapse())

In [1]: fem.Function(V.sub(0).collapse())
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 fem.Function(V.sub(0).collapse())

File ~/CODE_PROGRAMME/anaconda-2022/anaconda3_2022/envs/ipython-env/lib/python3.10/site-packages/dolfinx/fem/function.py:245, in Function.__init__(self, V, x, name, dtype)
    243     self._cpp_object = functiontype(dtype)(V._cpp_object, x)
    244 else:
--> 245     self._cpp_object = functiontype(dtype)(V._cpp_object)
    247 # Initialize the ufl.FunctionSpace
    248 super().__init__(V.ufl_function_space())

AttributeError: 'tuple' object has no attribute '_cpp_object'

Do you any idea how to overcome this ?

Thank you for the help !

Best regards,

Lamia

Collapse also returns the map from the sub space to the parent space, so you need to call V.sub(0).collapse()[0]