Applying constant vector for dirichletBC in dolfinx

Hi,

In old FEniCS, we could apply DirichletBC using constant vector as folllows.

from dolfin import *

mesh = UnitSquareMesh(20, 20)
# Build function space
P2 = VectorElement("CG", mesh.ufl_cell(), 2)
P1 = FiniteElement("CG", mesh.ufl_cell(), 1)
TH = P2 * P1
VQ = FunctionSpace(mesh, TH)
bc = DirichletBC(VQ.sub(0), Expression(("1", "0"), degree=0), "std::abs(x[1])>1-1e-12 && on_boundary")

I would like to do the same thing in dolfinx, but I could only find an example of using either scalar or function in the tutorial.

How could I apply constant vector that has different value (x-component is 1 and y-component is 0) using dolfinx?

Not sure if this is completely correct, but it may give you some useful hints on how to solve the problem:

import numpy as np
from dolfinx import mesh
from dolfinx.fem import Constant, Function
from dolfinx.fem import FunctionSpace, dirichletbc
from dolfinx.fem locate_dofs_topological
from dolfinx.mesh import locate_entities_boundary
from mpi4py import MPI
from petsc4py import PETSc
from ufl import FiniteElement, MixedElement, VectorElement

domain = mesh.create_unit_square(
    MPI.COMM_WORLD, 20, 20, mesh.CellType.quadrilateral)

P2 = VectorElement("CG", domain.ufl_cell(), 2)
P2_space = FunctionSpace(domain, P2)

P1 = FiniteElement("CG", domain.ufl_cell(), 1)
TH = FunctionSpace(domain, MixedElement([P2, P1]))

def on_boundary(x):
    return np.full(x.shape[1], True)

def bc_function(x):
    return np.logical_and(on_boundary, np.abs(x[1]) > 1-1e-12)

boundary_facets = locate_entities_boundary(
    domain, domain.topology.dim-1, bc_function)

boundary_dofs = locate_dofs_topological(
    P2_space, domain.topology.dim-1, boundary_facets)

f = Constant(domain, PETSc.ScalarType((0.0, 1.0)))
bc = dirichletbc(f, boundary_dofs, P2_space)

1 Like

What you are doing here is actually not applying a Constant in the meaning you are thinking. The expression has to be interpolated into the space (CG-2). So even if you are sending in a constant value, it computes this as a function under the hood.

Other than that, it is worth noting that there are only certain sub-spaces that support constant valued bcs.
Under the hood of DOLFINx, there is only a minor memory increase (size of a vector) when using functions instead of a constant. It does not affect the actual assembly time.
To use a function you could:

V, _ = VQ.sub(0).collapse(0)
u_bc = dolfinx.fem.Function(V)
def c(x):
    vals = np.zeros((2, x.shape[1]))
    vals[0] = 1
    return vals
u_bc.interpolate(c)
1 Like

You can also use Expression in DOLFINx for this purpose:

u_bc = dolfinx.fem.Function(V)
bc_val = dolfinx.fem.Constant(mesh, PETSc.ScalarType([1,0]))
bc_expr = dolfinx.fem.Expression(bc_val, V.element.interpolation_points())
u_bc.interpolate(bc_expr)
1 Like