Skip to content

Commit e564260

Browse files
jorgensdmmoelter
andauthored
Typos (#186)
* Update fundamentals.md Fixed some typos and wording * Update fundamentals.md Fixed typos and wording. * Update intro.md Fixed typos. * Update nonlinpoisson.md Fixed typos. * Update membrane.md Fixed typos. * Update nonlinpoisson_code.ipynb Fixed typos and wording and "non-linear" to "nonlinear", as well as "dolfinx" to "DOLFINx". * Update complex_mode.ipynb Fixed some typos. * Use jupytext * Fix u_exact --------- Co-authored-by: Matt Moelter <mmoelter@calpoly.edu>
1 parent d601ee2 commit e564260

28 files changed

+1223
-451
lines changed

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# The DOLFINx tutorial
2+
23
[![Test, build and publish](https://github.com/jorgensd/dolfinx-tutorial/actions/workflows/build-publish.yml/badge.svg)](https://github.com/jorgensd/dolfinx-tutorial/actions/workflows/build-publish.yml)
34
[![Test release branch against DOLFINx nightly build](https://github.com/jorgensd/dolfinx-tutorial/actions/workflows/nightly.yml/badge.svg)](https://github.com/jorgensd/dolfinx-tutorial/actions/workflows/nightly.yml)
45

@@ -8,33 +9,50 @@ This is the source code for the dolfinx-tutorial [webpage](https://jorgensd.gith
89
If you have any comments, corrections or questions, please submit an issue in the issue tracker.
910

1011
## Contributing
12+
1113
If you want to contribute to this tutorial, please make a fork of the repository, make your changes, and test that the CI passes. You can do this locally by downloading [act](https://github.com/nektos/act) and call
14+
1215
```bash
1316
act -j test-nightly
1417
```
18+
1519
Any code added to the tutorial should work in parallel.
1620

1721
Alternatively, if you want to add a separate chapter, a Jupyter notebook can be added to a pull request, without integrating it into the tutorial. If so, the notebook will be reviewed and modified to be included in the tutorial.
1822

23+
Also ensure that both Python file and notebook files are updated by using jupytext, i.e.
24+
25+
```bash
26+
python3 -m jupytext --sync */*.ipynb
27+
```
28+
1929
## Dependencies
30+
2031
It is adviced to use a pre-installed version of DOLFINx, for instance through conda or docker. Remaining dependencies can be installed with
32+
2133
```bash
2234
python3 -m pip install --no-binary=h5py -e .
2335
```
2436

2537
# Docker images
26-
Docker images for this tutorial can be found in the [packages tab](https://github.com/jorgensd/dolfinx-tutorial/pkgs/container/dolfinx-tutorial)
38+
39+
Docker images for this tutorial can be found in the [packages tab](https://github.com/jorgensd/dolfinx-tutorial/pkgs/container/dolfinx-tutorial)
2740

2841
Additional requirements on top of the `dolfinx/lab:nightly` images can be found at [Dockerfile](docker/Dockerfile) and [pyproject.toml](./pyproject.toml)
2942

3043
##
44+
3145
An image building DOLFINx, Basix, UFL and FFCx from source can be built using:
46+
3247
```bash
3348
cd docker
3449
docker build -f ./docker/Dockerfile -t local_lab_env .
3550
```
51+
3652
from the root of this repository, and run
53+
3754
```bash
3855
docker run --rm -ti -v $(pwd):/root/shared -w /root/shared --init -p 8888:8888 local_lab_env
39-
```
56+
```
57+
4058
from the main directory.

chapter1/complex_mode.ipynb

Lines changed: 18 additions & 313 deletions
Large diffs are not rendered by default.

chapter1/complex_mode.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.15.2
1010
# kernelspec:
1111
# display_name: Python 3 (DOLFINx complex)
1212
# language: python
@@ -19,19 +19,19 @@
1919
#
2020
# Many PDEs, such as the [Helmholtz equation](https://docs.fenicsproject.org/dolfinx/v0.4.1/python/demos/demo_helmholtz.html) require complex-valued fields.
2121
#
22-
# For simplicity, let us consider a Poisson equation of the form:
22+
# For simplicity, let us consider a Poisson equation of the form:
2323
#
2424
# $$-\Delta u = f \text{ in } \Omega,$$
25-
# $$ f = -1 - 2j \text{ in } \Omega,$$
25+
# $$ f = -1 - 2j \text{ in } \Omega,$$
2626
# $$ u = u_{exact} \text{ on } \partial\Omega,$$
2727
# $$u_{exact}(x, y) = \frac{1}{2}x^2 + 1j\cdot y^2,$$
2828
#
2929
# As in [Solving the Poisson equation](./fundamentals) we want to express our partial differential equation as a weak formulation.
3030
#
31-
# We start by defining our discrete function space $V_h$, such that $u_h\in V_h$ and $u_h = \sum_{i=1}^N c_i \phi_i(x, y)$ where $\phi_i$ are **real valued** global basis functions of our space $V_h$, $c_i \in \mathcal{C}$ are the **complex valued** degrees of freedom.
31+
# We start by defining our discrete function space $V_h$, such that $u_h\in V_h$ and $u_h = \sum_{i=1}^N c_i \phi_i(x, y)$ where $\phi_i$ are **real valued** global basis functions of our space $V_h$, and $c_i \in \mathcal{C}$ are the **complex valued** degrees of freedom.
3232
#
33-
# Next, we choose a test function $v\in \hat V_h$ where $\hat V_h\subset V_h$ such that $v\vert_{\partial\Omega}=0$, as done in the first tutorial.
34-
# We now need to define our inner product space. We choose the $L^2$ inner product spaces, which is a *[sesquilinear](https://en.wikipedia.org/wiki/Sesquilinear_form) 2-form*, Meaning that $\langle u, v\rangle$ is a map from $V_h\times V_h\mapsto K$, and $\langle u, v \rangle = \int_\Omega u \cdot \bar v ~\mathrm{d} x$. As it is sesquilinear, we have the following properties:
33+
# Next, we choose a test function $v\in \hat V_h$ where $\hat V_h\subset V_h$ such that $v\vert_{\partial\Omega}=0$, as done in the first tutorial.
34+
# We now need to define our inner product space. We choose the $L^2$ inner product spaces, which is a _[sesquilinear](https://en.wikipedia.org/wiki/Sesquilinear_form) 2-form_, meaning that $\langle u, v\rangle$ is a map from $V_h\times V_h\mapsto K$, and $\langle u, v \rangle = \int_\Omega u \cdot \bar v ~\mathrm{d} x$. As it is sesquilinear, we have the following properties:
3535
#
3636
# $$\langle u , v \rangle = \overline{\langle v, u \rangle},$$
3737
# $$\langle u , u \rangle \geq 0.$$
@@ -41,10 +41,12 @@
4141
# $$\int_\Omega \nabla u_h \cdot \nabla \overline{v}~ \mathrm{dx} = \int_{\Omega} f \cdot \overline{v} ~\mathrm{d} s \qquad \forall v \in \hat{V}_h.$$
4242
#
4343
# ## Installation of FEniCSx with complex number support
44-
# FEniCSx supports both real and complex numbers, meaning that we can create a function spaces with real valued or complex valued coefficients.
44+
#
45+
# FEniCSx supports both real and complex numbers, so we can create a function space with real valued or complex valued coefficients.
46+
#
4547

46-
import dolfinx
4748
from mpi4py import MPI
49+
import dolfinx
4850
import numpy as np
4951
mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)
5052
V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))
@@ -55,19 +57,22 @@
5557
print(u_r.x.array.dtype)
5658
print(u_c.x.array.dtype)
5759

58-
# However, as we would like to solve linear algebra problems on the form $Ax=b$, we need to be able to use matrices and vectors that support real and complex numbers. As [PETSc](https://petsc.org/release/) is one of the most popular interfaces to linear algebra packages, we need to be able to work with their matrix and vector structures.
60+
# However, as we would like to solve linear algebra problems of the form $Ax=b$, we need to be able to use matrices and vectors that support real and complex numbers. As [PETSc](https://petsc.org/release/) is one of the most popular interfaces to linear algebra packages, we need to be able to work with their matrix and vector structures.
5961
#
6062
# Unfortunately, PETSc only supports one floating type in their matrices, thus we need to install two versions of PETSc, one that supports `float64` and one that supports `complex128`. In the [docker images](https://hub.docker.com/r/dolfinx/dolfinx) for DOLFINx, both versions are installed, and one can switch between them by calling `source dolfinx-real-mode` or `source dolfinx-complex-mode`. For the `dolfinx/lab` images, one can change the Python kernel to be either the real or complex mode, by going to `Kernel->Change Kernel...` and choose `Python3 (ipykernel)` (for real mode) or `Python3 (DOLFINx complex)` (for complex mode).
6163
#
6264
# We check that we are using the correct installation of PETSc by inspecting the scalar type.
65+
#
6366

6467
from petsc4py import PETSc
6568
from dolfinx.fem.petsc import assemble_vector
6669
print(PETSc.ScalarType)
6770
assert np.dtype(PETSc.ScalarType).kind == 'c'
6871

6972
# ## Variational problem
73+
#
7074
# We are now ready to define our variational problem
75+
#
7176

7277
import ufl
7378
u = ufl.TrialFunction(V)
@@ -78,23 +83,27 @@
7883

7984
# Note that we have used the `PETSc.ScalarType` to wrap the constant source on the right hand side. This is because we want the integration kernels to assemble into the correct floating type.
8085
#
81-
# Secondly, note that we are using `ufl.inner` to describe multiplication of $f$ and $v$, even if they are scalar values. This is because `ufl.inner` takes the conjugate of the second argument, as decribed by the $L^2$ inner product. One could alternatively write this out manually
86+
# Secondly, note that we are using `ufl.inner` to describe multiplication of $f$ and $v$, even if they are scalar values. This is because `ufl.inner` takes the conjugate of the second argument, as decribed by the $L^2$ inner product. One could alternatively write this out explicitly
8287
#
8388
# ### Inner-products and derivatives
89+
#
8490

8591
L2 = f * ufl.conj(v) * ufl.dx
8692
print(L)
8793
print(L2)
8894

89-
# Similarly, if we want to use the function $ufl.derivative$ to take derivatives of functionals, we need to take some special care. As `derivative` inserts a `ufl.TestFunction` to represent the variation, we need to take the conjugate of this to be able to use it to assemble vectors.
95+
# Similarly, if we want to use the function `ufl.derivative` to take derivatives of functionals, we need to take some special care. As `derivative` inserts a `ufl.TestFunction` to represent the variation, we need to take the conjugate of this to in order to assemble vectors.
96+
#
9097

9198
J = u_c**2 * ufl.dx
9299
F = ufl.derivative(J, u_c, ufl.conj(v))
93100
residual = assemble_vector(dolfinx.fem.form(F))
94101
print(residual.array)
95102

96103
# We define our Dirichlet condition and setup and solve the variational problem.
104+
#
97105
# ## Solve variational problem
106+
#
98107

99108
mesh.topology.create_connectivity(mesh.topology.dim-1, mesh.topology.dim)
100109
boundary_facets = dolfinx.mesh.exterior_facet_indices(mesh.topology)
@@ -103,8 +112,10 @@
103112
problem = dolfinx.fem.petsc.LinearProblem(a, L, bcs=[bc])
104113
uh = problem.solve()
105114

106-
# We compute the $L^2$ error and the max error
115+
# We compute the $L^2$ error and the max error.
116+
#
107117
# ## Error computation
118+
#
108119

109120
x = ufl.SpatialCoordinate(mesh)
110121
u_ex = 0.5 * x[0]**2 + 1j*x[1]**2
@@ -115,7 +126,9 @@
115126
print(global_error, max_error)
116127

117128
# ## Plotting
118-
# Finally, we plot the real and imaginary solution
129+
#
130+
# Finally, we plot the real and imaginary solutions.
131+
#
119132

120133
import pyvista
121134
pyvista.start_xvfb()

chapter1/fundamentals_code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.16.1
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python

chapter1/membrane_code.ipynb

Lines changed: 549 additions & 35 deletions
Large diffs are not rendered by default.

chapter1/membrane_code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.16.1
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python

chapter1/nitsche.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.16.1
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python

chapter2/diffusion_code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.16.1
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python

chapter2/heat_code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.16.1
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python

chapter2/hyperelasticity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.16.1
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python

chapter2/linearelasticity_code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: light
88
# format_version: '1.5'
9-
# jupytext_version: 1.14.7
9+
# jupytext_version: 1.16.1
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python

chapter2/nonlinpoisson_code.ipynb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"Author: Jørgen S. Dokken\n",
1010
"\n",
1111
"## Test problem\n",
12-
"To solve a test problem, we need to choose the right hand side $f$ and the coefficient $q(u)$ and the boundary $u_D$. Previously, we have worked with manufactured solutions that can be reproduced without approximation errors. This is more difficult in non-linear porblems, and the algebra is more tedious. Howeve, we will utilize UFLs differentiation capabilities to obtain a manufactured solution.\n",
12+
"To solve a test problem, we need to choose the right hand side $f$, the coefficient $q(u)$, and the boundary $u_D$. Previously, we have worked with manufactured solutions that can be reproduced without approximation errors. This is more difficult in nonlinear problems, and the algebra is more tedious. However, we will utilize the UFL differentiation capabilities to obtain a manufactured solution.\n",
1313
"\n",
1414
"For this problem, we will choose $q(u) = 1 + u^2$ and define a two dimensional manufactured solution that is linear in $x$ and $y$:"
1515
]
@@ -44,10 +44,10 @@
4444
"cell_type": "markdown",
4545
"metadata": {},
4646
"source": [
47-
"Note that since `x` is a 2D vector, the first component (index 0) resemble $x$, while the second component (index 1) resemble $y$. The resulting function `f` can be directly used in variational formulations in DOLFINx.\n",
47+
"Note that since `x` is a 2D vector, the first component (index 0) represents $x$, while the second component (index 1) represents $y$. The resulting function `f` can be directly used in variational formulations in DOLFINx.\n",
4848
"\n",
49-
"As we now have defined our source term and exact solution, we can create the appropriate function space and boundary conditions.\n",
50-
"Note that as we have already defined the exact solution, we only have to convert it to a python function that can be evaluated in the interpolation function. We do this by employing the Python `eval` and `lambda`-functions."
49+
"As we now have defined our source term and an exact solution, we can create the appropriate function space and boundary conditions.\n",
50+
"Note that as we have already defined the exact solution, we only have to convert it to a Python function that can be evaluated in the interpolation function. We do this by employing the Python `eval` and `lambda`-functions."
5151
]
5252
},
5353
{
@@ -77,7 +77,7 @@
7777
"cell_type": "markdown",
7878
"metadata": {},
7979
"source": [
80-
"We are now ready to define the variational formulation. Note that as the problem is non-linear, we have replace the `TrialFunction` with a `Function`, which serves as the unknown of our problem."
80+
"We are now ready to define the variational formulation. Note that as the problem is nonlinear, we have to replace the `TrialFunction` with a `Function`, which serves as the unknown of our problem."
8181
]
8282
},
8383
{
@@ -114,7 +114,7 @@
114114
"cell_type": "markdown",
115115
"metadata": {},
116116
"source": [
117-
"Next, we use the dolfinx Newton solver. We can set the convergence criterions for the solver by changing the absolute tolerance (`atol`), relative tolerance (`rtol`) or the convergence criterion (`residual` or `incremental`)."
117+
"Next, we use the DOLFINx Newton solver. We can set the convergence criteria for the solver by changing the absolute tolerance (`atol`), relative tolerance (`rtol`) or the convergence criterion (`residual` or `incremental`)."
118118
]
119119
},
120120
{
@@ -213,7 +213,7 @@
213213
"metadata": {},
214214
"source": [
215215
"We observe that the solver converges after $8$ iterations.\n",
216-
"If we think of the problem in terms of finite differences on a uniform mesh, $\\mathcal{P}_1$ elements mimic standard second-order finite differences, which compute the derivative of a linear or quadratic funtion exactly. Here $\\nabla u$ is a constant vector, which is multiplied by $1+u^2$, which is a second order polynomial in $x$ and $y$, which the finite difference operator would compute exactly. We can therefore, even with $\\mathcal{P}_1$ elements, expect the manufactured solution to be reproduced by the numerical method. However, if we had chosen a nonlinearity, such as $1+u^4$, this would not be the case, and we would need to verify convergence rates."
216+
"If we think of the problem in terms of finite differences on a uniform mesh, $\\mathcal{P}_1$ elements mimic standard second-order finite differences, which compute the derivative of a linear or quadratic funtion exactly. Here $\\nabla u$ is a constant vector, which is multiplied by $1+u^2$, giving a second order polynomial in $x$ and $y$, which the finite difference operator would compute exactly. We can therefore, even with $\\mathcal{P}_1$ elements, expect the manufactured solution to be reproduced by the numerical method. However, if we had chosen a nonlinearity, such as $1+u^4$, this would not be the case, and we would need to verify convergence rates."
217217
]
218218
},
219219
{

0 commit comments

Comments
 (0)