Skip to content

Commit

Permalink
Merge pull request #10 from jorgensd/dokken/bump_version
Browse files Browse the repository at this point in the history
Update to v0.8
  • Loading branch information
jorgensd committed Jun 5, 2024
2 parents 5161167 + e3979a7 commit c3134f2
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 336 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/build_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ env:
# Directory that will be published on github pages
PUBLISH_DIR: ./_build/html
DEB_PYTHON_INSTALL_LAYOUT: deb_system
PYVISTA_TRAME_SERVER_PROXY_PREFIX: "/proxy/"
PYVISTA_TRAME_SERVER_PROXY_ENABLED: "True"
PYVISTA_OFF_SCREEN: false
PYVISTA_JUPYTER_BACKEND: "html"

jobs:
build-docs:
env:
PYTHONPATH: /usr/local/lib/python3/dist-packages:/usr/local/lib:/usr/local/dolfinx-real/lib/python3.10/dist-packages
DEB_PYTHON_INSTALL_LAYOUT: deb_system
PYVISTA_JUPYTER_BACKEND: "html"
runs-on: ubuntu-22.04
container: dolfinx/dolfinx:v0.7.2

runs-on: ubuntu-24.04
container: ghcr.io/fenics/dolfinx/dolfinx:stable
steps:
# This action sets the current path to the root of your github repo
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Github Pages

on:
push:
branches: [main]
branches: [release]

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
Expand Down
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ sphinx:
- "sphinx.ext.viewcode"

config:
html_last_updated_fmt: "%b %d, %Y"
html_theme_options:
navigation_with_keys: false
nb_custom_formats:
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ requires = ["setuptools>=64.4.0", "wheel", "pip>=22.3"]

[project]
name = "FEniCS23"
version = "0.7.0"
version = "0.8.0"
description = "Tutorial for FENiCS 2023"
authors = [{ name = "Jørgen S. Dokken", email = "dokken@simula.no" }]
license = { file = "LICENSE" }
readme = "README.md"
dependencies = [
"fenics-dolfinx>=0.7.0",
"fenics-dolfinx>=0.8.0",
"pygraphviz",
"pyvista[all]>=0.43.0",
"ipyparallel",
Expand Down
21 changes: 13 additions & 8 deletions src/approximations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# the left hand side is constant. Thus, it would make sense to only assemble the matrix once.
# Following this, we create a general projector class

import dolfinx.fem.function
import pyvista
import numpy as np
import dolfinx
Expand Down Expand Up @@ -118,7 +119,7 @@ def assemble_rhs(self, h: ufl.core.expr.Expr):
self._b.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT_VALUES,
mode=PETSc.ScatterMode.FORWARD)

def project(self, h: ufl.core.expr.Expr):
def project(self, h: ufl.core.expr.Expr) -> dolfinx.fem.Function:
"""
Compute projection using a PETSc KSP solver
Expand All @@ -128,6 +129,10 @@ def project(self, h: ufl.core.expr.Expr):
self.assemble_rhs(h)
self._ksp.solve(self._b.vector, self._x.vector)
return self._x

def __del__(self):
self._A.destroy()
self._ksp.destroy()

# With this class, we can send in any expression written in the unified form language to the projector,
# and then generate code for the right hand side assembly, and then solve the linear system.
Expand Down Expand Up @@ -165,7 +170,7 @@ def h(mesh: dolfinx.mesh.Mesh):

# We can also interpolate functions from an expression into any suitable function space by calling

V = dolfinx.fem.FunctionSpace(mesh, ("Discontinuous Lagrange", 2))
V = dolfinx.fem.functionspace(mesh, ("Discontinuous Lagrange", 2))
compiled_h_for_V = dolfinx.fem.Expression(
h(mesh), V.element.interpolation_points())

Expand All @@ -174,7 +179,7 @@ def h(mesh: dolfinx.mesh.Mesh):
# Let us now test the code for a first order Lagrange space

mesh = dolfinx.mesh.create_unit_interval(MPI.COMM_WORLD, 20)
V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))
V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))


V_projector = Projector(
Expand Down Expand Up @@ -203,7 +208,7 @@ def plot_1D_scalar_function(u: dolfinx.fem.Function, title: str):

# We can now repeat the study for a DG-1 function

W = dolfinx.fem.FunctionSpace(mesh, ("DG", 1))
W = dolfinx.fem.functionspace(mesh, ("DG", 1))


W_projector = Projector(
Expand All @@ -219,8 +224,8 @@ def plot_1D_scalar_function(u: dolfinx.fem.Function, title: str):

for N in [50, 100, 200]:
mesh = dolfinx.mesh.create_unit_interval(MPI.COMM_WORLD, N)
V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))
W = dolfinx.fem.FunctionSpace(mesh, ("DG", 1))
V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))
W = dolfinx.fem.functionspace(mesh, ("DG", 1))
V_projector = Projector(
V, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
uh = V_projector.project(h(V.mesh))
Expand All @@ -245,8 +250,8 @@ def h_aligned(mesh: dolfinx.mesh.Mesh):

for N in [20, 40, 80]:
mesh = dolfinx.mesh.create_unit_interval(MPI.COMM_WORLD, N)
V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))
W = dolfinx.fem.FunctionSpace(mesh, ("DG", 1))
V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))
W = dolfinx.fem.functionspace(mesh, ("DG", 1))
V_projector = Projector(
V, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
uh = V_projector.project(h_aligned(V.mesh))
Expand Down
2 changes: 1 addition & 1 deletion src/code_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
# We can look at the assembly code for the local matrix. We start by inspecting the signature of the `tabulate_tensor` function,
# that computes the local element matrix

os.system("head -336 ufl_formulation.c | tail +283")
os.system("head -344 ufl_formulation.c | tail +272")
2 changes: 1 addition & 1 deletion src/form_compilation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

# + tags=["hide-output"]
mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 30, 30)
V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))
V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))
# -

# Let us consider a simple heat equation,
Expand Down
43 changes: 17 additions & 26 deletions src/introduction.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,67 +17,58 @@
# To solve this problem, we have to choose an appropriate finite element space to represent the function $k$ and $u$.
# There is a large variety of finite elements, for instance the [Lagrange elements](https://defelement.com/elements/lagrange.html).
# The basis function for a first order Lagrange element is shown below
# <figure>
#
#<center>
# <img src="https://defelement.com/img/element-Lagrange-variant-equispaced-triangle-1-0-large.png" width="150" height="150" />
# <img src="https://defelement.com/img/element-Lagrange-variant-equispaced-triangle-1-1-large.png" width="150" height="150" />
# <img src="https://defelement.com/img/element-Lagrange-variant-equispaced-triangle-1-2-large.png" width="150" height="150" />
# <figcaption> First order Lagrange basis functions <figcaption\>
# <figure\>
# <img src="https://defelement.com/img/element-Lagrange-variant-equispaced-triangle-1-2-large.png" width="150" height="150" /><br>
# First order Lagrange basis functions<br><br>
# </center>

#
# To symbolically represent this element, we use `ufl.FiniteElement`
# To symbolically represent this element, we use `basix.ufl.element`, that creates a UFL-compatible element using Basix.

# + slideshow={"slide_type": ""}
import numpy as np
import basix.ufl
import ufl

element = ufl.FiniteElement("Lagrange", ufl.triangle, 1)
element = basix.ufl.element("Lagrange", "triangle", 1)

# -
# We note that we send in the finite element family, what cells we will use to represent the domain,
# and the degree of the function space.
# As this element is just a symbolic representation, it does not contain the information required to tabulate (evaluate)
# basis functions at an abitrary point. UFL is written in this way, so that it can be used as a symbolic representation
# basis functions at an arbitrary point. UFL is written in this way, so that it can be used as a symbolic representation
# for a large range of finite element software, not just FENiCS.
#
# In FENiCSx, we use [Basix](https://github.com/FEniCS/basix/) to tabulate finite elements.
# Basix can convert any `ufl`-element into a basix finite element, which we in turn can evaluate.

basix_element = basix.ufl.convert_ufl_element(element)

# Lets next tabulate the basis functions of our element at a given point `p=(0, 0.5)` in the reference element.
# the `basix.finite_element.FiniteElement.tabulate` function takes in two arguments, how many derivatives we want to compute,
# and at what points in the reference element we want to compute them.

points = np.array([[0., 0.5], [1, 0]], dtype=np.float64)
print(basix_element.tabulate(0, points))
print(element.tabulate(0, points))

# We can also compute the derivatives at any points in the reference element

print(basix_element.tabulate(1, points))
print(element.tabulate(1, points))

# Observe that the output we get from this command also includes the 0th order derivatives.
# Thus we note that the output has the shape `(num_spatial_derivatives+1, num_points, num_basis_functions)`
#
# Not every function we want to represent is scalar valued. For instance, in fluid flow problems, the Taylor-Hood finite element
# pair is often used to represent the fluid velocity and pressure, where each component of the fluid velocity is in a Lagrange space.
# We represent this by using a `ufl.VectorElement`, which you can give the number of components as an input argument.

vector_element = ufl.VectorElement("Lagrange", ufl.triangle, 2, dim=2)

# We can also use basix for this
# We represent this by adding a `shape` argument to the `basix.ufl.element` constructor.

el = basix.ufl.element("Lagrange", "triangle", 2)
v_el = basix.ufl.blocked_element(el, shape=(2,))
vector_element = basix.ufl.element("Lagrange", "triangle", 2, shape=(2, ))

# Both these definitions of elements are compatible with DOLFINx. The reason for having both of them is that basix offers more tweaking of the finite
# elements that the UFL definition does. For more information regarding this see:
# Basix allows for a large variety of extra options to tweak your finite elements, see for instance
# [Variants of Lagrange elements](https://docs.fenicsproject.org/dolfinx/v0.7.2/python/demos/demo_lagrange_variants.html)
# for how to choose the node spacing in a Lagrange element.

# To create the Taylor-Hood finite element pair, we use the `ufl.MixedElement`/`basix.ufl.mixed_element` syntax
# To create the Taylor-Hood finite element pair, we use the `basix.ufl.mixed_element`

m_el = ufl.MixedElement([vector_element, element])
m_el_basix = basix.ufl.mixed_element([v_el, basix_element])
m_el = basix.ufl.mixed_element([vector_element, element])

# There is a wide range of finite elements that are supported by ufl and basix.
# See for instance: [Supported elements in basix/ufl](https://defelement.com/lists/implementations/basix.ufl.html).
3 changes: 1 addition & 2 deletions src/lifting.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
tdim = mesh.topology.dim

# + tags=["hide-output"]
el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
V = dolfinx.fem.FunctionSpace(mesh, el)
V = dolfinx.fem.functionspace(mesh, ("Lagrange", 2, (mesh.geometry.dim, )))
# -

# # Define boundaries
Expand Down
7 changes: 4 additions & 3 deletions src/mesh_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import ipyparallel as ipp
import dolfinx
import basix.ufl
import numpy as np
import ufl
from mpi4py import MPI
Expand All @@ -25,7 +26,7 @@
nodes = np.array([[1., 0.], [2., 0.], [3., 2.], [1, 3]], dtype=np.float64)
connectivity = np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int64)

c_el = ufl.Mesh(ufl.VectorElement("Lagrange", ufl.triangle, 1))
c_el = ufl.Mesh(basix.ufl.element("Lagrange", "triangle", 1, shape=(nodes.shape[1],)))
domain = dolfinx.mesh.create_mesh(MPI.COMM_SELF, connectivity, nodes, c_el)

# We start by creating a simple plotter by interfacing with Pyvista
Expand All @@ -38,7 +39,7 @@ def plot_mesh(mesh: dolfinx.mesh.Mesh):
"""
plotter = pyvista.Plotter()
ugrid = pyvista.UnstructuredGrid(*dolfinx.plot.vtk_mesh(mesh))
if mesh.geometry.cmaps[0].degree > 1:
if mesh.geometry.cmap.degree > 1:
plotter.add_mesh(ugrid, style="points", color="b", point_size=10)
ugrid = ugrid.tessellate()
show_edges = False
Expand All @@ -62,7 +63,7 @@ def plot_mesh(mesh: dolfinx.mesh.Mesh):
[2.9, 1.3], [1.5, 1.5], [1.5, -0.2]], dtype=np.float64)
connectivity = np.array([[0, 1, 2, 3, 4, 5]], dtype=np.int64)

c_el = ufl.Mesh(ufl.VectorElement("Lagrange", ufl.triangle, 2))
c_el = ufl.Mesh(basix.ufl.element("Lagrange", "triangle", 2, shape=(nodes.shape[1],)))
domain = dolfinx.mesh.create_mesh(MPI.COMM_SELF, connectivity, nodes, c_el)
plot_mesh(domain)

Expand Down
6 changes: 3 additions & 3 deletions src/problem_specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
import numpy as np

mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)
V = dolfinx.fem.FunctionSpace(mesh, ("Discontinuous Lagrange", 3))
V = dolfinx.fem.functionspace(mesh, ("Discontinuous Lagrange", 3))
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
a = u * v * ufl.dx

F = dolfinx.fem.FunctionSpace(mesh, ("Discontinuous Lagrange", 2))
F = dolfinx.fem.functionspace(mesh, ("Discontinuous Lagrange", 2))
f = dolfinx.fem.Function(F)
G = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 2))
G = dolfinx.fem.functionspace(mesh, ("Lagrange", 2))
g = dolfinx.fem.Function(G)

L = f / g * v * ufl.dx
Expand Down
Loading

0 comments on commit c3134f2

Please sign in to comment.