DirichletBC depending on both time and another function

Hi all!

I was wondering what is the best strategy for Dirichlet boundary conditions that are dependent on time, space and another function.

Say for example I want to impose the condition:
u_D = (100 \ t + x) + 2 \ T

I am currently doing the following:

import dolfinx
from mpi4py import MPI


from petsc4py.PETSc import ScalarType
import numpy as np


class SpaceTimeExpression:
    def __init__(self, t=0):
        self.t = t
        self.values = None

    def __call__(self, x):
        if self.values is None:
            self.values = np.zeros(x.shape[1], dtype=ScalarType)

        self.values = np.full(x.shape[1], 100 * self.t + x[0])
        return self.values


mesh = dolfinx.mesh.create_unit_cube(MPI.COMM_WORLD, 2, 2, 2)
V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))
u_D = dolfinx.fem.Function(V)
T = dolfinx.fem.Function(V)  # or dolfinx.fem.Constant(mesh, 2.0)

expr = SpaceTimeExpression(t=0)
sub_expr = dolfinx.fem.Function(V)
sub_expr.interpolate(expr.__call__)

u_D_expr = dolfinx.fem.Expression(sub_expr + 2 * T, V.element.interpolation_points())

u_D.interpolate(u_D_expr)
bc = dolfinx.fem.dirichletbc(
    u_D, dolfinx.fem.locate_dofs_topological(V, 2, [0, 1, 2, 3, 4, 5])
)

for t in range(10):
    expr.t = t

    sub_expr.interpolate(expr.__call__)

    u_D.interpolate(u_D_expr)

    print(u_D.vector.array[0])

In the code above I an kind of splitting the u_D expression into two.
But there may be cases where this is trickier, for instance:

u_D = (1 + t \cdot T) \cdot t + 2 \ T \ x

Is there a way to achieve this in a more straightforward way?

Thanks in advance!!

Rem

What about using constants and a single DOLFINx Expression, i.e. something along the lines of

x = dolfinx.fem.Function(V)
t = dolfinx.fem.Constant(mesh, np.float64(0.0))
T = dolfinx.fem.Constant(mesh, np.float64(10))
u_d = (1 + t * T) * t + 2 * T * x
ud_expr = dolfinx.fem.Expression(u_d, V.element.interpolation_points())
u_D = dolfinx.fem.Function(V)
u_D.interpolate(ud_expr)
t.value += dt
u_D.interpolate(ud_expr)
1 Like

I think this can work!

Would it work for cases where we have:

u_D = 100 \ x if t < 100
u_D = 0 otherwise

I would then use ufl.conditional for this.

1 Like