Skip to content

Fix typos #185

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ If you want to contribute to this tutorial, please make a fork of the repository
```bash
act -j test-nightly
```
Any code added to the tutorial should work in parallel.
Any code added to the tutorial should work in parallel. If any changes are made to `ipynb` files, please ensure that these changes are reflected in the corresponding `py` files by using [`jupytext`](https://jupytext.readthedocs.io/en/latest/faq.html#can-i-use-jupytext-with-jupyterhub-binder-nteract-colab-saturn-or-azure):
```bash
jupytext --sync notebook.ipynb
```

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.

Expand Down
540 changes: 532 additions & 8 deletions chapter1/complex_mode.ipynb

Large diffs are not rendered by default.

31 changes: 22 additions & 9 deletions chapter1/complex_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# extension: .py
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.14.7
# jupytext_version: 1.16.1
# kernelspec:
# display_name: Python 3 (DOLFINx complex)
# language: python
Expand All @@ -19,19 +19,19 @@
#
# Many PDEs, such as the [Helmholtz equation](https://docs.fenicsproject.org/dolfinx/v0.4.1/python/demos/demo_helmholtz.html) require complex-valued fields.
#
# For simplicity, let us consider a Poisson equation of the form:
# For simplicity, let us consider a Poisson equation of the form:
#
# $$-\Delta u = f \text{ in } \Omega,$$
# $$ f = -1 - 2j \text{ in } \Omega,$$
# $$ f = -1 - 2j \text{ in } \Omega,$$
# $$ u = u_{exact} \text{ on } \partial\Omega,$$
# $$u_{exact}(x, y) = \frac{1}{2}x^2 + 1j\cdot y^2,$$
#
# As in [Solving the Poisson equation](./fundamentals) we want to express our partial differential equation as a weak formulation.
#
# 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.
#
# 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.
# 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:
# 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.
# 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:
#
# $$\langle u , v \rangle = \overline{\langle v, u \rangle},$$
# $$\langle u , u \rangle \geq 0.$$
Expand All @@ -41,7 +41,9 @@
# $$\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.$$
#
# ## Installation of FEniCSx with complex number support
# FEniCSx supports both real and complex numbers, meaning that we can create a function spaces with real valued or complex valued coefficients.
#
# FEniCSx supports both real and complex numbers, meaning that we can create function spaces with real valued or complex valued coefficients.
#

import dolfinx
from mpi4py import MPI
Expand All @@ -55,19 +57,22 @@
print(u_r.x.array.dtype)
print(u_c.x.array.dtype)

# 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.
# 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.
#
# 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).
# 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 choosing `Python3 (ipykernel)` (for real mode) or `Python3 (DOLFINx complex)` (for complex mode).
#
# We check that we are using the correct installation of PETSc by inspecting the scalar type.
#

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

# ## Variational problem
#
# We are now ready to define our variational problem
#

import ufl
u = ufl.TrialFunction(V)
Expand All @@ -81,20 +86,24 @@
# 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
#
# ### Inner-products and derivatives
#

L2 = f * ufl.conj(v) * ufl.dx
print(L)
print(L2)

# 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.
# Similarly, if we want to use the function `ufl.derivative` to take derivatives of functionals, we need to take some special care. As `ufl.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.
#

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

# We define our Dirichlet condition and setup and solve the variational problem.
#
# ## Solve variational problem
#

mesh.topology.create_connectivity(mesh.topology.dim-1, mesh.topology.dim)
boundary_facets = dolfinx.mesh.exterior_facet_indices(mesh.topology)
Expand All @@ -104,7 +113,9 @@
uh = problem.solve()

# We compute the $L^2$ error and the max error
#
# ## Error computation
#

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

# ## Plotting
#
# Finally, we plot the real and imaginary solution
#

import pyvista
pyvista.start_xvfb()
Expand Down
2 changes: 1 addition & 1 deletion chapter1/fundamentals_code.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"\n",
"Inserting $u_e$ in the original boundary problem, we find that \n",
"\\begin{align}\n",
" f(x,y)= -6,\\qquad u_d(x,y)=u_e(x,y)=1+x^2+2y^2,\n",
" f(x,y)= -6,\\qquad u_D(x,y)=u_e(x,y)=1+x^2+2y^2,\n",
"\\end{align}\n",
"regardless of the shape of the domain as long as we prescribe \n",
"$u_e$ on the boundary.\n",
Expand Down
4 changes: 2 additions & 2 deletions chapter1/fundamentals_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# extension: .py
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.14.7
# jupytext_version: 1.16.1
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
Expand Down Expand Up @@ -43,7 +43,7 @@
#
# Inserting $u_e$ in the original boundary problem, we find that
# \begin{align}
# f(x,y)= -6,\qquad u_d(x,y)=u_e(x,y)=1+x^2+2y^2,
# f(x,y)= -6,\qquad u_D(x,y)=u_e(x,y)=1+x^2+2y^2,
# \end{align}
# regardless of the shape of the domain as long as we prescribe
# $u_e$ on the boundary.
Expand Down
4 changes: 2 additions & 2 deletions chapter1/membrane.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ In this section, we will turn our attentition to a physically more relevant prob

We would like to compute the deflection $D(x,y)$ of a two-dimensional, circular membrane of radius $R$, subject to a load $p$ over the membrane. The appropriate PDE model is
\begin{align}
-T \nabla^2D&=p \quad\text{in }\quad \Omega=\{(x,y)\vert x^2+y^2\leq R \}.
-T \nabla^2D&=p \quad\text{in }\quad \Omega=\{(x,y)\vert x^2+y^2\leq R^2 \}.
\end{align}
Here, $T$ is the tension in the membrane (constant), and $p$ is the external pressure load. The boundary of the membrane has no deflection. This implies that $D=0$ is the boundary condition. We model a localized load as a Gaussian function:
\begin{align}
Expand Down Expand Up @@ -36,7 +36,7 @@ With $D_e=\frac{AR^2}{8\pi\sigma T}$ and dropping the bars we obtain the scaled
\begin{align}
-\nabla^2 w = 4e^{-\beta^2(x^2+(y-R_0)^2)}
\end{align}
to be solved over the unit disc with $w=0$ on the boundary. Now there are only two parameters which vary the dimensionless extent of the pressure, $\beta$, and the location of the pressure peak, $R_0\in[0,1]$. As $\beta\to 0$, the solution will approach the special case $w=1-x^2-y^2$. Given a computed scaed solution $w$, the physical deflection can be computed by
to be solved over the unit disc with $w=0$ on the boundary. Now there are only two parameters which vary the dimensionless extent of the pressure, $\beta$, and the location of the pressure peak, $R_0\in[0,1]$. As $\beta\to 0$, the solution will approach the special case $w=1-x^2-y^2$. Given a computed scaled solution $w$, the physical deflection can be computed by
\begin{align}
D=\frac{AR^2}{8\pi\sigma T}w.
\end{align}
Loading