Milestone 1: The curl of a vector field
In the first milestone, you will implement the curl of a vector field using a Fourier spectral method. The goal is to
- …understand how to compute the curl with Fourier-spectral methods.
Curl
In your project you will implement a pseudospectral solver for the Navier-Stokes equations. We will guide you step-by-step through creating this code. This initial milestone explains how to compute the curl, that is a nessary operation for computing the Navier-Stokes equation in the rotational form that we will use for the project.
The curl is a differential operation on a vector field. Given vector field $\vec{u}(\vec{r})$, which for the Navier-Stokes equation will be a velocity field, the curl is defined as
\[\text{curl}\,\vec{u}=\nabla\times\vec{u}=\begin{pmatrix}\partial_y u_z - \partial_z u_y\\\partial_z u_x - \partial_x u_z\\\partial_x u_y - \partial_y u_x\end{pmatrix}.\]Using the curl, we can define the vorticity field
\[\vec{\omega}=\frac{1}{2}\nabla\times\vec{u}.\]Note that some authors define $\vec{\omega}=\nabla\times\vec{u}$ without the factor of $1/2$. With our definition, $\omega$ becomes the angular velocity of a velocity field that corresponds to pure rotation, as can be easily checked by computing the vorticity of $\vec{u}(\vec{r})=\vec{\omega}\times\vec{r}$.
Task 1: Fourier-representation of the curl
Given a Fourier-series of the vector-field $\vec{u}(\vec{r})$, i.e.
\[\vec{u}(\vec{r})=\sum_{\vec{q}} \tilde{\vec{u}}(\vec{q}) e^{i \vec{q}\cdot\vec{r}}\]with Fourier coefficients \(\tilde{\vec{u}}(\vec{q})\), derive the expression for the curl in the Fourier representation.
Task 2: Implement a function computing the curl in real-space
Implement a function
nb_grid_pts = (32, 32, 2)
fft = FFT(nb_grid_pts, engine='pocketfft')
def curl(u_cxyz):
"""Computes the curl of a vector field in real space."""
fft...
...
that uses the Fourier-representation of the curl derived above to compute the curl of a real-space field. Use µFFT for the computation of the Fourier-transform.
Task 3: Test that a constant field has vanishing curl
As the first simplest test, check that a constant field leads to vanishing curl:
u_cxyz = np.ones([3, *fft.nb_subdomain_grid_pts])
curlu_cxyz = curl(u_cxyz)
np.testing.assert_allclose(curlu_cxyz, 0)
Task 4: Test nonvanishing curl
Compute the curl for the vector field generated by
norm = np.array([0, 0, 1])
u_cxyz = np.cross(norm, fft.coords - 0.5, axis=0)
Plot vector field and curl of the vector field. Which value of the curl would you expect? What do you see?