Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
80d08db
Improve workflow handling (#118)
jorgensd Mar 22, 2023
da48de6
Merge branch 'main' into release
jorgensd Mar 22, 2023
625293c
Merge branch 'main' into release
jorgensd Mar 22, 2023
6b2db88
Dokken/update fspace and wmtgs (#127)
jorgensd Apr 19, 2023
8bcf5f9
Update petsc arches
jorgensd Jun 21, 2023
10a4939
Fix bounding boxes and more (#135)
jorgensd Jul 4, 2023
8eb2770
PETSc python API update (#137)
jorgensd Jul 5, 2023
dd30b8a
Make sure all notebooks run. Change to pathlib in some examples
jorgensd Aug 12, 2023
9e30cab
Api changes related to: https://github.com/FEniCS/dolfinx/pull/2763 (…
jorgensd Sep 23, 2023
662b8b2
Bump version numbers
jorgensd Oct 12, 2023
fb8e738
Bump version numbers (#149)
jorgensd Oct 12, 2023
d9a02c0
Merge branch 'main' into release
jorgensd Oct 12, 2023
b9c7990
Fix petsc arch
jorgensd Oct 12, 2023
8db8b94
Merge branch 'dokken/prepare-v0.7.0' into release
jorgensd Oct 12, 2023
ffe997e
Merge branch 'main' into release
jorgensd Oct 28, 2023
ecd6994
Prepare v0.7.1 (#154)
jorgensd Oct 28, 2023
26ad6bf
Merge branch 'main' into release
jorgensd Oct 28, 2023
69bf939
Updates compatible with nightly branch of DOLFINx (#156)
jorgensd Dec 7, 2023
1a885f2
Fix wrong link
jorgensd Jan 28, 2024
a36ae80
Fix typo in changelog
jorgensd Jan 28, 2024
b4c4a0c
Merge main into release (#189)
jorgensd Apr 30, 2024
f2775eb
Merge branch 'main' into release
jorgensd May 5, 2024
e32797a
add missing checkout (#191)
jorgensd May 5, 2024
45ea6bf
Remove unused import
jorgensd May 5, 2024
fb40ada
Update text to resolve #194 (#195)
jorgensd May 13, 2024
6a67d30
Dokken/update nonlin options (#203)
jorgensd Aug 12, 2024
50b0aad
Update python file as well
jorgensd Aug 12, 2024
4d19c14
Update config ptr (#207)
jorgensd Sep 26, 2024
bf06975
Pressure correction equation fix (#196)
jorgensd Sep 26, 2024
4706eef
Update fundamentals.md (#199)
rossbm1 Sep 26, 2024
1f872e5
Change from vector to petsc_vec (#206)
jorgensd Sep 26, 2024
adf0314
dolfinx.fem.Form changed to dolfinx.fem.form (#213)
MPenaR Oct 2, 2024
aa4ef09
Merge branch 'main' into release
jorgensd Oct 14, 2024
1fcb776
Update book_stable.yml
jorgensd Oct 14, 2024
336a89a
Update test_stable.yml
jorgensd Oct 14, 2024
94447f3
Fix python path in test
jorgensd Oct 14, 2024
ea69c78
Merge branch 'release'
jorgensd Oct 15, 2024
7b2ccb0
Merge branch 'main' into release
jorgensd Oct 15, 2024
0b3745e
Merge branch 'main' into release
jorgensd Oct 15, 2024
3138242
Fix CI (#227)
jorgensd Nov 19, 2024
3fd4b03
Update test_stable.yml (#235)
jorgensd Jan 6, 2025
260fa82
Add libgl flag to ci (#238)
jorgensd Jan 6, 2025
ce168fa
Dokken/bump release (#249)
jorgensd Feb 4, 2025
096fc96
Update linearelasticity_code.ipynb (#246)
mleoni-pf Feb 5, 2025
f084a1f
Update linearelasticity_code.ipynb (#245)
mleoni-pf Feb 5, 2025
3bd537c
Update linearelasticity_code.ipynb (#244)
mleoni-pf Feb 5, 2025
4e9bac0
Update linearelasticity_code.ipynb (#243)
mleoni-pf Feb 5, 2025
389d43a
Update ns_code2.ipynb (#241)
mleoni-pf Feb 5, 2025
de967cc
Add files via upload (#250)
bayswiss Feb 5, 2025
63c5cde
Remove dead link
jorgensd Apr 22, 2025
9d52627
Add fix from https://github.com/jorgensd/dolfinx-tutorial/pull/253 + …
jorgensd Aug 9, 2025
4b5b2bb
Add propsoed solution to #205 (#257)
jorgensd Aug 9, 2025
7fdf1fb
Add singular Poisson demo. Resolves: https://github.com/jorgensd/dolf…
jorgensd Aug 9, 2025
acf248e
Add extra note on conversion from new python files (#265)
jorgensd Aug 12, 2025
3c38876
Adaptive mesh refinement with NetGen (#266)
jorgensd Aug 18, 2025
4856900
Add netgen to stable book build (#267)
jorgensd Aug 18, 2025
1e66dc1
Update text to reflect that there is a docker image (#268)
jorgensd Aug 18, 2025
27f9c84
Strip output and adapt eta definition, ref comment from Jack Hale (#269)
jorgensd Aug 18, 2025
3c87f94
Finish trailing sentence (#270)
jorgensd Aug 18, 2025
c04e742
Try removing xvfb for most tutorials (#278)
jorgensd Oct 5, 2025
19867b7
INstall osmesa
jorgensd Oct 5, 2025
5d01c81
Remove -W
jorgensd Oct 5, 2025
579af78
Add offscreen false to jupyter build
jorgensd Oct 5, 2025
c87b5c2
Remove some more xvfb and move new variables
jorgensd Oct 5, 2025
3147119
Lower bound on vtk
jorgensd Oct 5, 2025
6cd86be
Change tag on release branch
jorgensd Oct 5, 2025
b439d6c
Another rename
jorgensd Oct 5, 2025
36d9d5c
Merge remote-tracking branch 'origin/main' into release
jorgensd Oct 20, 2025
97c61e9
Update pctools paper
jorgensd Oct 23, 2025
ae67b2e
Update em.ipynb
mleoni-pf Nov 21, 2025
fbdd2e1
Sync py file
jorgensd Dec 29, 2025
c846d6f
Update action.yml
jorgensd Dec 29, 2025
6e95de7
Merge branch 'main' into dokken/mleoni-patch
jorgensd Dec 29, 2025
5f812a7
Merge branch 'main' into dokken/mleoni-patch
jorgensd Jan 5, 2026
d332ab0
Turn off compression with meshio
jorgensd Jan 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/install-dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ runs:
- name: Install apt dependencies and upgrade pip
shell: bash -el {0}
run: |
apt-get update && apt-get install -y libxrender1 libgl1-mesa-dev mesa-utils
apt-get update && apt-get install -y libxrender1 libgl1-mesa-dev mesa-utils gzip
2 changes: 1 addition & 1 deletion chapter3/em.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"\n",
"which holds for an isotropic linear magnetic medium.\n",
"Here, $\\mu$ is the magnetic permability of the material.\n",
"Now, since $B$ is solenodial (divergence free) accoording to Maxwell's equations, we known that $B$ must be the curl of some vector field $A$. This field is called the magnetic vector potential. Since the problem is static and thus $\\frac{\\partial D}{\\partial t}=0$, it follows that\n",
"Now, since $B$ is solenodial (divergence free) according to Maxwell's equations, we known that $B$ must be the curl of some vector field $A$. This field is called the magnetic vector potential. Since the problem is static and thus $\\frac{\\partial D}{\\partial t}=0$, it follows that\n",
"\n",
"$$\n",
"J = \\nabla \\times H = \\nabla \\times(\\mu^{-1} B)=\\nabla \\times (\\mu^{-1}\\nabla \\times A ) = -\\nabla \\cdot (\\mu^{-1}\\nabla A).\n",
Expand Down
2 changes: 1 addition & 1 deletion chapter3/em.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
#
# which holds for an isotropic linear magnetic medium.
# Here, $\mu$ is the magnetic permability of the material.
# Now, since $B$ is solenodial (divergence free) accoording to Maxwell's equations, we known that $B$ must be the curl of some vector field $A$. This field is called the magnetic vector potential. Since the problem is static and thus $\frac{\partial D}{\partial t}=0$, it follows that
# Now, since $B$ is solenodial (divergence free) according to Maxwell's equations, we known that $B$ must be the curl of some vector field $A$. This field is called the magnetic vector potential. Since the problem is static and thus $\frac{\partial D}{\partial t}=0$, it follows that
#
# $$
# J = \nabla \times H = \nabla \times(\mu^{-1} B)=\nabla \times (\mu^{-1}\nabla \times A ) = -\nabla \cdot (\mu^{-1}\nabla A).
Expand Down
48 changes: 29 additions & 19 deletions chapter3/subdomains.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
"metadata": {},
"source": [
"# Defining subdomains for different materials\n",
"\n",
"Author: Jørgen S. Dokken\n",
"\n",
"Solving PDEs in domains made up of different materials is a frequently encountered task. In FEniCSx, we handle these problems by defining a Discontinous cell-wise constant function.\n",
"Such a function can be created over any mesh in the following way\n",
"## Subdomains on built-in meshes"
"\n",
"## Subdomains on built-in meshes\n"
]
},
{
Expand Down Expand Up @@ -56,7 +58,7 @@
},
"source": [
"We will use a simple example with two materials in two dimensions to demonstrate the idea. The whole domain will be $\\Omega=[0,1]\\times[0,1]$, which consists of two subdomains\n",
"$\\Omega_0=[0,1]\\times [0,1/2]$ and $\\Omega_1=[0,1]\\times[1/2, 1]$. We start by creating two python functions, where each returns `True` if the input coordinate is inside its domain."
"$\\Omega_0=[0,1]\\times [0,1/2]$ and $\\Omega_1=[0,1]\\times[1/2, 1]$. We start by creating two python functions, where each returns `True` if the input coordinate is inside its domain.\n"
]
},
{
Expand Down Expand Up @@ -84,14 +86,16 @@
"$$\n",
"-\\nabla \\cdot [\\kappa (x,y)\\nabla u(x, y)]= 1 \\qquad \\text{in } \\Omega,\n",
"$$\n",
"\n",
"$$\n",
"u=u_D=1 \\qquad \\text{on } \\partial\\Omega_D=[0,y], y\\in[0,1]\n",
"$$\n",
"\n",
"$$\n",
"-\\frac{\\partial u}{\\partial n}=0 \\qquad \\text{on } \\partial\\Omega\\setminus \\partial\\Omega_D\n",
"$$\n",
"\n",
"Our next step is to define $\\kappa$"
"Our next step is to define $\\kappa$\n"
]
},
{
Expand All @@ -112,7 +116,7 @@
"In the previous code block, we found which cells (triangular elements) satisfy the condition for being in $\\Omega_0, \\Omega_1$. As the $DG-0$ function contains only one degree of freedom per cell, there is a one to one mapping between the cell indicies and the degrees of freedom. We let $\\kappa=\\begin{cases}\n",
"1 &\\text{if } x\\in\\Omega_0\\\\\n",
"0.1& \\text{if } x\\in\\Omega_1\\\\\n",
"\\end{cases}$"
"\\end{cases}$\n"
]
},
{
Expand All @@ -129,7 +133,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We are now ready to define our variational formulation and Dirichlet boundary condition after using integration by parts"
"We are now ready to define our variational formulation and Dirichlet boundary condition after using integration by parts\n"
]
},
{
Expand All @@ -151,7 +155,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now solve and visualize the solution of the problem"
"We can now solve and visualize the solution of the problem\n"
]
},
{
Expand Down Expand Up @@ -217,7 +221,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We clearly observe different behavior in the two regions, which both have the same Dirichlet boundary condition on the left side, where $x=0$."
"We clearly observe different behavior in the two regions, which both have the same Dirichlet boundary condition on the left side, where $x=0$.\n"
]
},
{
Expand All @@ -227,7 +231,8 @@
},
"source": [
"## Interpolation with Python-function\n",
"As we saw in the first approach, in many cases, we can use the geometrical coordinates to determine which coefficient we should use. Using the unstructured mesh from the previous example, we illustrate an alternative approach using interpolation:"
"\n",
"As we saw in the first approach, in many cases, we can use the geometrical coordinates to determine which coefficient we should use. Using the unstructured mesh from the previous example, we illustrate an alternative approach using interpolation:\n"
]
},
{
Expand Down Expand Up @@ -261,7 +266,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We verify this by assembling the error between this new function and the old one"
"We verify this by assembling the error between this new function and the old one\n"
]
},
{
Expand All @@ -280,7 +285,8 @@
"metadata": {},
"source": [
"## Subdomains defined from external mesh data\n",
"Let us now consider the same problem, but using GMSH to generate the mesh and subdomains. We will then in turn show how to use this data to generate discontinuous functions in DOLFINx."
"\n",
"Let us now consider the same problem, but using GMSH to generate the mesh and subdomains. We will then in turn show how to use this data to generate discontinuous functions in DOLFINx.\n"
]
},
{
Expand Down Expand Up @@ -329,7 +335,8 @@
"metadata": {},
"source": [
"## Read in MSH files with DOLFINx\n",
"You can read in MSH files with DOLFINx, which will read them in on a single process, and then distribute them over the available ranks in the MPI communicator."
"\n",
"You can read in MSH files with DOLFINx, which will read them in on a single process, and then distribute them over the available ranks in the MPI communicator.\n"
]
},
{
Expand All @@ -353,14 +360,17 @@
},
"source": [
"## Convert msh-files to XDMF using meshio\n",
"\n",
"We will use `meshio` to read in the `msh` file, and convert it to a more suitable IO format. Meshio requires `h5py`, and can be installed on linux with the following commands:\n",
"\n",
"```{code}\n",
"export HDF5_MPI=\"ON\"\n",
"export CC=mpicc\n",
"export HDF5_DIR=\"/usr/lib/x86_64-linux-gnu/hdf5/mpich/\"\n",
"pip3 install --no-cache-dir --no-binary=h5py h5py meshio\n",
"```\n",
"We start by creating a convenience function for extracting data for a single cell type, and creating a new `meshio.Mesh`."
"\n",
"We start by creating a convenience function for extracting data for a single cell type, and creating a new `meshio.Mesh`.\n"
]
},
{
Expand All @@ -385,7 +395,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"This function returns a meshio mesh, including physical markers for the given type. The `prune_z` argument is for cases where we want to use two dimensional meshes. The last coordinate in the mesh (as it is generated in a 3D space) has to be removed for DOLFINx to consider this as a two dimensional geometry."
"This function returns a meshio mesh, including physical markers for the given type. The `prune_z` argument is for cases where we want to use two dimensional meshes. The last coordinate in the mesh (as it is generated in a 3D space) has to be removed for DOLFINx to consider this as a two dimensional geometry.\n"
]
},
{
Expand All @@ -401,8 +411,8 @@
" # Create and save one file for the mesh, and one file for the facets\n",
" triangle_mesh = create_mesh(msh, \"triangle\", prune_z=True)\n",
" line_mesh = create_mesh(msh, \"line\", prune_z=True)\n",
" meshio.write(\"mesh.xdmf\", triangle_mesh)\n",
" meshio.write(\"mt.xdmf\", line_mesh)\n",
" meshio.write(\"mesh.xdmf\", triangle_mesh, compression=None)\n",
" meshio.write(\"mt.xdmf\", line_mesh, compression=None)\n",
"MPI.COMM_WORLD.barrier()"
]
},
Expand All @@ -412,7 +422,7 @@
"source": [
"We have now written the mesh and the cell markers to one file, and the facet markers in a separate file. We can now read this data in DOLFINx using `XDMFFile.read_mesh` and `XDMFFile.read_meshtags`. The `dolfinx.MeshTags` stores the index of the entity, along with the value of the marker in two one dimensional arrays.\n",
"\n",
"Note that we have generated and written the mesh on only one processor. However, the `xdmf`-format supports parallel IO, and we can thus read the mesh in parallel."
"Note that we have generated and written the mesh on only one processor. However, the `xdmf`-format supports parallel IO, and we can thus read the mesh in parallel.\n"
]
},
{
Expand All @@ -433,7 +443,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We have now read in the mesh and corresponding cell and facet data. We can now create our discontinuous function `kappa` as follows"
"We have now read in the mesh and corresponding cell and facet data. We can now create our discontinuous function `kappa` as follows\n"
]
},
{
Expand All @@ -454,7 +464,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also efficiently use the facet data `ft` to create the Dirichlet boundary condition"
"We can also efficiently use the facet data `ft` to create the Dirichlet boundary condition\n"
]
},
{
Expand All @@ -475,7 +485,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now solve the problem in a similar fashion as above"
"We can now solve the problem in a similar fashion as above\n"
]
},
{
Expand Down
33 changes: 30 additions & 3 deletions chapter3/subdomains.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
# ---

# # Defining subdomains for different materials
#
# Author: Jørgen S. Dokken
#
# Solving PDEs in domains made up of different materials is a frequently encountered task. In FEniCSx, we handle these problems by defining a Discontinous cell-wise constant function.
# Such a function can be created over any mesh in the following way
#
# ## Subdomains on built-in meshes
#

# +
from dolfinx import default_scalar_type
Expand Down Expand Up @@ -54,6 +57,7 @@

# We will use a simple example with two materials in two dimensions to demonstrate the idea. The whole domain will be $\Omega=[0,1]\times[0,1]$, which consists of two subdomains
# $\Omega_0=[0,1]\times [0,1/2]$ and $\Omega_1=[0,1]\times[1/2, 1]$. We start by creating two python functions, where each returns `True` if the input coordinate is inside its domain.
#


# +
Expand All @@ -74,14 +78,17 @@ def Omega_1(x):
# $$
# -\nabla \cdot [\kappa (x,y)\nabla u(x, y)]= 1 \qquad \text{in } \Omega,
# $$
#
# $$
# u=u_D=1 \qquad \text{on } \partial\Omega_D=[0,y], y\in[0,1]
# $$
#
# $$
# -\frac{\partial u}{\partial n}=0 \qquad \text{on } \partial\Omega\setminus \partial\Omega_D
# $$
#
# Our next step is to define $\kappa$
#

kappa = Function(Q)
cells_0 = locate_entities(mesh, mesh.topology.dim, Omega_0)
Expand All @@ -91,11 +98,13 @@ def Omega_1(x):
# 1 &\text{if } x\in\Omega_0\\
# 0.1& \text{if } x\in\Omega_1\\
# \end{cases}$
#

kappa.x.array[cells_0] = np.full_like(cells_0, 1, dtype=default_scalar_type)
kappa.x.array[cells_1] = np.full_like(cells_1, 0.1, dtype=default_scalar_type)

# We are now ready to define our variational formulation and Dirichlet boundary condition after using integration by parts
# We are now ready to define our variational formulation and Dirichlet boundary condition after using integration by parts
#

V = functionspace(mesh, ("Lagrange", 1))
u, v = TrialFunction(V), TestFunction(V)
Expand All @@ -106,6 +115,7 @@ def Omega_1(x):
bcs = [dirichletbc(default_scalar_type(1), dofs, V)]

# We can now solve and visualize the solution of the problem
#

# +
problem = LinearProblem(
Expand Down Expand Up @@ -152,9 +162,12 @@ def Omega_1(x):


# We clearly observe different behavior in the two regions, which both have the same Dirichlet boundary condition on the left side, where $x=0$.
#

# ## Interpolation with Python-function
#
# As we saw in the first approach, in many cases, we can use the geometrical coordinates to determine which coefficient we should use. Using the unstructured mesh from the previous example, we illustrate an alternative approach using interpolation:
#


def eval_kappa(x):
Expand All @@ -172,13 +185,16 @@ def eval_kappa(x):
kappa2.interpolate(eval_kappa)

# We verify this by assembling the error between this new function and the old one
#

# Difference in kappa's
error = mesh.comm.allreduce(assemble_scalar(form((kappa - kappa2) ** 2 * dx)))
print(error)

# ## Subdomains defined from external mesh data
#
# Let us now consider the same problem, but using GMSH to generate the mesh and subdomains. We will then in turn show how to use this data to generate discontinuous functions in DOLFINx.
#

gmsh.initialize()
proc = MPI.COMM_WORLD.rank
Expand Down Expand Up @@ -215,7 +231,9 @@ def eval_kappa(x):
gmsh.finalize()

# ## Read in MSH files with DOLFINx
#
# You can read in MSH files with DOLFINx, which will read them in on a single process, and then distribute them over the available ranks in the MPI communicator.
#

mesh_data = gmshio.read_from_msh("mesh.msh", MPI.COMM_WORLD, gdim=2)
mesh = mesh_data.mesh
Expand All @@ -225,14 +243,18 @@ def eval_kappa(x):
facet_markers = mesh_data.facet_tags

# ## Convert msh-files to XDMF using meshio
#
# We will use `meshio` to read in the `msh` file, and convert it to a more suitable IO format. Meshio requires `h5py`, and can be installed on linux with the following commands:
#
# ```{code}
# export HDF5_MPI="ON"
# export CC=mpicc
# export HDF5_DIR="/usr/lib/x86_64-linux-gnu/hdf5/mpich/"
# pip3 install --no-cache-dir --no-binary=h5py h5py meshio
# ```
#
# We start by creating a convenience function for extracting data for a single cell type, and creating a new `meshio.Mesh`.
#


def create_mesh(mesh, cell_type, prune_z=False):
Expand All @@ -248,6 +270,7 @@ def create_mesh(mesh, cell_type, prune_z=False):


# This function returns a meshio mesh, including physical markers for the given type. The `prune_z` argument is for cases where we want to use two dimensional meshes. The last coordinate in the mesh (as it is generated in a 3D space) has to be removed for DOLFINx to consider this as a two dimensional geometry.
#

if proc == 0:
# Read in mesh
Expand All @@ -256,13 +279,14 @@ def create_mesh(mesh, cell_type, prune_z=False):
# Create and save one file for the mesh, and one file for the facets
triangle_mesh = create_mesh(msh, "triangle", prune_z=True)
line_mesh = create_mesh(msh, "line", prune_z=True)
meshio.write("mesh.xdmf", triangle_mesh)
meshio.write("mt.xdmf", line_mesh)
meshio.write("mesh.xdmf", triangle_mesh, compression=None)
meshio.write("mt.xdmf", line_mesh, compression=None)
MPI.COMM_WORLD.barrier()

# We have now written the mesh and the cell markers to one file, and the facet markers in a separate file. We can now read this data in DOLFINx using `XDMFFile.read_mesh` and `XDMFFile.read_meshtags`. The `dolfinx.MeshTags` stores the index of the entity, along with the value of the marker in two one dimensional arrays.
#
# Note that we have generated and written the mesh on only one processor. However, the `xdmf`-format supports parallel IO, and we can thus read the mesh in parallel.
#

with XDMFFile(MPI.COMM_WORLD, "mesh.xdmf", "r") as xdmf:
mesh = xdmf.read_mesh(name="Grid")
Expand All @@ -272,6 +296,7 @@ def create_mesh(mesh, cell_type, prune_z=False):
ft = xdmf.read_meshtags(mesh, name="Grid")

# We have now read in the mesh and corresponding cell and facet data. We can now create our discontinuous function `kappa` as follows
#

Q = functionspace(mesh, ("DG", 0))
kappa = Function(Q)
Expand All @@ -281,6 +306,7 @@ def create_mesh(mesh, cell_type, prune_z=False):
kappa.x.array[top_cells] = np.full_like(top_cells, 0.1, dtype=default_scalar_type)

# We can also efficiently use the facet data `ft` to create the Dirichlet boundary condition
#

V = functionspace(mesh, ("Lagrange", 1))
u_bc = Function(V)
Expand All @@ -290,6 +316,7 @@ def create_mesh(mesh, cell_type, prune_z=False):
bcs = [dirichletbc(default_scalar_type(1), left_dofs, V)]

# We can now solve the problem in a similar fashion as above
#

# +
u, v = TrialFunction(V), TestFunction(V)
Expand Down