I am trying to follow the approach suggested in this dolfinx tutorial, to set multiple Dirichlet and Neumann Boundary conditions.
I do fail to see how to apply a zero Neumann condition. I would have thought that having a null function as
u_ex
in the above demo would do the trick, but I get an error
after the line
f = -div(grad(u_ex(x)))
with the error message
Cannot determine geometric dimension from expression.
ERROR:UFL:Cannot determine geometric dimension from expression.
What is the problem with a zero function?
This is a minimum working example, I am using dolfinx 0.6.0
from petsc4py import PETSc default_scalar_type = PETSc.ScalarType from dolfinx.fem import (Constant, Function, FunctionSpace, assemble_scalar, dirichletbc, form, locate_dofs_topological) from dolfinx.fem.petsc import LinearProblem from dolfinx.io import XDMFFile from dolfinx.mesh import create_unit_square, locate_entities, meshtags from dolfinx.plot import create_vtk_mesh from mpi4py import MPI from ufl import (FacetNormal, Measure, SpatialCoordinate, TestFunction, TrialFunction, div, dot, dx, grad, inner, lhs, rhs) import numpy as np import pyvista mesh = create_unit_square(MPI.COMM_WORLD, 10, 10) u_ex = lambda x: 0.0 + 0.0*x[0]**2 + 0.0*x[1]**2 x = SpatialCoordinate(mesh) # Define physical parameters and boundary condtions s = u_ex(x) f = -div(grad(u_ex(x))) n = FacetNormal(mesh) g = -dot(n, grad(u_ex(x))) kappa = Constant(mesh, default_scalar_type(1)) r = Constant(mesh, default_scalar_type(1000)) # Define function space and standard part of variational form V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = TrialFunction(V), TestFunction(V) F = kappa * inner(grad(u), grad(v)) * dx - inner(f, v) * dx boundaries = [(1, lambda x: np.isclose(x[0], 0)), (2, lambda x: np.isclose(x[0], 1)), (3, lambda x: np.isclose(x[1], 0)), (4, lambda x: np.isclose(x[1], 1))] facet_indices, facet_markers = [], [] fdim = mesh.topology.dim - 1 for (marker, locator) in boundaries: facets = locate_entities(mesh, fdim, locator) facet_indices.append(facets) facet_markers.append(np.full_like(facets, marker)) facet_indices = np.hstack(facet_indices).astype(np.int32) facet_markers = np.hstack(facet_markers).astype(np.int32) sorted_facets = np.argsort(facet_indices) facet_tag = meshtags(mesh, fdim, facet_indices[sorted_facets], facet_markers[sorted_facets]) ds = Measure("ds", domain=mesh, subdomain_data=facet_tag) class BoundaryCondition(): def __init__(self, type, marker, values): self._type = type if type == "Dirichlet": u_D = Function(V) u_D.interpolate(values) facets = facet_tag.find(marker) dofs = locate_dofs_topological(V, fdim, facets) self._bc = dirichletbc(u_D, dofs) elif type == "Neumann": self._bc = inner(values, v) * ds(marker) elif type == "Robin": self._bc = values[0] * inner(u-values[1], v)* ds(marker) else: raise TypeError("Unknown boundary condition: {0:s}".format(type)) @property def bc(self): return self._bc @property def type(self): return self._type # Define the Dirichlet condition boundary_conditions = [BoundaryCondition("Dirichlet", 1, u_ex), BoundaryCondition("Dirichlet", 2, u_ex), BoundaryCondition("Robin", 3, (r, s)), BoundaryCondition("Neumann", 4, g)]