Time-dependent BC

I would like to define time-dependent BC on a scalar FEM space. Here is a MWE:

from mpi4py import MPI
import numpy as np
import ufl
from basix.ufl import element
from dolfinx.fem import (Function, dirichletbc, functionspace, locate_dofs_topological, locate_dofs_geometrical,)
from dolfinx.mesh import *

# mesh, spaces, functions
msh = create_unit_square(MPI.COMM_WORLD, 10,10)
P1 = element("Lagrange", "triangle", 1) 
XV = functionspace(msh, P1)
x = ufl.SpatialCoordinate(msh)

# BC
def Gamma(x):
    return np.isclose(x[0], 0.)

class time_dep_func:
    def __init__(self):
        self.t = 0.0

    def eval(self, x):
        return np.sin(self.t)

BC_obj = time_dep_func()
BC_obj.t = 0.
bc_fun = Function(XV) 
bc_fun.interpolate(BC_obj.eval)

dofs = locate_dofs_geometrical(XV, Gamma) 
bcu = dirichletbc(bc_fun, dofs, XV)

I get an error message like this:

Traceback (most recent call last):
  File "/home/renoldner/miniconda3/envs/fenicsx/lib/python3.11/site-packages/dolfinx/fem/function.py", line 397, in interpolate
    _interpolate(u, cells)
  File "/home/renoldner/miniconda3/envs/fenicsx/lib/python3.11/functools.py", line 909, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/renoldner/miniconda3/envs/fenicsx/lib/python3.11/site-packages/dolfinx/fem/function.py", line 373, in _interpolate
    self._cpp_object.interpolate(u, cells, nmm_interpolation_data)
TypeError: interpolate(): incompatible function arguments. The following argument types are supported:
    1. (self: dolfinx.cpp.fem.Function_float64, f: numpy.ndarray[numpy.float64], cells: numpy.ndarray[numpy.int32]) -> None
    2. (self: dolfinx.cpp.fem.Function_float64, u: dolfinx.cpp.fem.Function_float64, cells: numpy.ndarray[numpy.int32], nmm_interpolation_data: Tuple[List[int], List[int], List[float], List[int]]) -> None
    3. (self: dolfinx.cpp.fem.Function_float64, expr: dolfinx::fem::Expression<double, double>, cells: numpy.ndarray[numpy.int32]) -> None

Invoked with: <dolfinx.cpp.fem.Function_float64 object at 0x7f6542b703f0>, <bound method time_dep_func.eval of <__main__.time_dep_func object at 0x7f6546dd34d0>>, array([  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
        13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
        26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
        39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
        52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
        65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,
        78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
        91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103,
       104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
       117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
       130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
       143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
       156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
       169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
       182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
       195, 196, 197, 198, 199], dtype=int32), ((), (), (), ())

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ [...] / test.py", line 34, in <module>
    bc_fun.interpolate(BC_obj.eval)
  File "/home/renoldner/miniconda3/envs/fenicsx/lib/python3.11/site-packages/dolfinx/fem/function.py", line 402, in interpolate
    self._cpp_object.interpolate(np.asarray(u(x), dtype=self.dtype), cells)
IndexError: invalid axis: 0 (ndim = 0)

I can not explain this, as in THIS DISCOURSE POST, the method seems to work (however, there, a Vector-valued FEM space is used).

Using
dofs = locate_dofs_topological(XV, 1, Gamma)

does not fix the error.

Hello there,

My best guess after rapidly reading your code is that there’s something wrong in the definition of eval and, consequently, in the line bc_fun.interpolate(BC_obj.eval).

If you make eval actually depend on x (like, for instance, by returning x[0]**2*np.sin(self.t)) it should pass the interpolation line with no error. Then it could complain for the locate_dofs_geometrical args but I’m not sure because I didn’t run your code.

All the best,
Giorgia

1 Like

Thank you for your answer. I tried the following:

class time_dep_func:
    def __init__(self):
        self.t = 0.0

    def eval(self, x):
        return x[0]**2*np.sin(self.t)

with “locate_dofs_geometricl” and get

python3 test.py 
Traceback (most recent call last):
  File "/home/renoldner/miniconda3/envs/fenicsx/lib/python3.11/site-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: Annotated[List[numpy.ndarray[numpy.int32]], FixedSize(2)], V: dolfinx::fem::FunctionSpace<double>)

Invoked with: <dolfinx.cpp.fem.Function_float64 object at 0x7f154cbcabf0>, array([ 64,  66,  76,  85,  93, 100, 106, 111, 115, 118, 120], dtype=int32), FunctionSpace(Mesh(blocked element (Basix element (P, triangle, 1, gll_warped, unset, False), (2,)), 0), Basix element (P, triangle, 1, gll_warped, unset, False))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ [...] / test.py", line 34, in <module>
    bcu = dirichletbc(bc_fun, dofs, XV)     
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/renoldner/miniconda3/envs/fenicsx/lib/python3.11/site-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: Annotated[List[numpy.ndarray[numpy.int32]], FixedSize(2)], V: dolfinx::fem::FunctionSpace<double>)

Invoked with: <dolfinx.cpp.fem.Function_float64 object at 0x7f154cbcabf0>, array([ 64,  66,  76,  85,  93, 100, 106, 111, 115, 118, 120], dtype=int32), <dolfinx.cpp.fem.FunctionSpace_float64 object at 0x7f1548988f70>

The arguments of locate_dofs_geometrical look correct to me, i have successfully used them like this in other scripts.

It’s actually complaining when calling dirichletbc, locate_dofs_geometrical is working correctly. Try to take a look at the error here:

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: <dolfinx.cpp.fem.Function_float64 object at 0x7f154cbcabf0>, array([ 64,  66,  76,  85,  93, 100, 106, 111, 115, 118, 120], dtype=int32), FunctionSpace(Mesh(blocked element (Basix element (P, triangle, 1, gll_warped, unset, False), (2,)), 0), Basix element (P, triangle, 1, gll_warped, unset, False))
1 Like

In addition to the previous change by @gpase, you should also be changing the very final line ot

bcu = dirichletbc(bc_fun, dofs)

The third argument is only needed when the first input argument is a constant (or when the FE space is a mixed one). In this case, bc_fun is a function, so dirichletbc already knows from that that XV is the FE space to be used when extracting DOFs.

Thank you for your answer!