Initial conditions#

Perturbations#

When performing a numerical simulation studying the onset of instabilities in a time-dependent problem, it is typical to set for the initial conditions

\[u(\textbf{x}, t=0) = u_0(\textbf{x})=b(\textbf{x}) + \mathcal{N}(\textbf{x})\]
\[\min_{\textbf{x}}\mathcal{N}(\textbf{x}) = \varepsilon^-\]
\[\max_{\textbf{x}}\mathcal{N}(\textbf{x}) = \varepsilon^+\]

When adding some numerical noise \(\mathcal{N}(\textbf{x})\) to the base state \(b(\textbf{x})\), it is desirable to have control of both its amplitude and ‘coarseness’ or frequency.

import numpy as np
from dolfinx.fem import FunctionSpace
from lucifex.mesh import rectangle_mesh, interval_mesh
from lucifex.utils import SpatialPerturbation, DofsPerturbation, sinusoid_noise, cubic_noise, cross_section
from lucifex.viz import plot_line, plot_colormap

Examples: \(d=1\) interval#

\[\Omega = [0, L_x]\]
\[b(x)= 1 - x\]

sinusoid noise with specified frequency and subject to periodic boundary conditions

\[\mathcal{N}(x)=\mathcal{N}_{\text{sinu}}(x;n_{\text{waves}})\]
\[ \mathcal{N}_{\text{sinu}}(x=0)=\mathcal{N}_{\text{sinu}}(x=L_x)=0\]

prescribed noise function

\[\mathcal{N}(x;\lambda_0, \lambda_1)=\cos(2\pi x/\lambda_0)\sin(2\pi x/\lambda_1)\]
Lx = 2.0
mesh = interval_mesh(Lx, 200)
fs = FunctionSpace(mesh, ('P', 1))

n_waves = 10
sinu_noise = sinusoid_noise('periodic', Lx, n_waves, 0)

lmbda = (Lx, 0.2 * Lx)
sincos_noise = lambda x: np.cos(2* np.pi * x[0] / lmbda[0]) * np.sin(2 * np.pi * x[0] / lmbda[1])

for noise in (sinu_noise, sincos_noise):
    eps = 0.2
    perturbation = SpatialPerturbation(
        lambda x: 1 - x[0],
        noise,
        [Lx],
        eps,
    )    
    u0 = perturbation.combine_base_noise(fs)
    uBase = perturbation.base(fs)
    uNoise = perturbation.noise(fs)
    plot_line([u0, uBase], x_label='$x$', legend_labels=['$u_0=b+\mathcal{N}$', '$b$'])
    fig, ax = plot_line(uNoise, x_label='$x$', y_label='$\mathcal{N}(x)$')
    ax.hlines((0, eps), 0, Lx, colors='black', linestyles='dotted', linewidths=0.75)
../../_images/70e1c6ddcbc06bad158acb2552ec847f6e8007cd7b17ecb133c026ab25539db3.png ../../_images/0c253d31f718ce57faa6a0926e9f709e2a4e63f5b769c1cc85df9a28fcbe743a.png ../../_images/3e3eccb7c2a92fe452a33eee554a064064bf6bb1e9de1e1ba9bbd2eda919c81d.png ../../_images/5de65c6e5f0af797c7e08728bc9a0e91a3e51f741d22f1a996e14062fc9028e5.png

Examples: \(d=2\) rectangle#

\[\Omega = [0, L_x]\times[0, L_y]\]
\[b(x, y)= \tfrac{1}{2}xy\]

cubic interpolation noise with specified frequency and subject to Neumann/Dirichlet boundary conditions

\[\mathcal{N}(x)=\mathcal{N}_{\text{cubi}}(x;n_{\text{freq}})\]
\[\frac{\partial\mathcal{N}_{\text{cubi}}}{\partial x}(x=0,y)=\frac{\partial\mathcal{N}_{\text{cubic}}}{\partial x}(x=L_x,y)=\mathcal{N}_{\text{cubi}}(x,y=0)=\mathcal{N}_{\text{cubic}}(x,y=L_y)=0\]

degrees-of-freedom vector noise

\[\textbf{u}_0 = \textbf{b} + \textbf{N}\quad\text{where}\quad u_0(\textbf{x})=\sum_ju_{0,j}\xi_j(\textbf{x})\]
Lx = 2.0
Ly = 1.0
mesh = rectangle_mesh(Lx, Ly, 100, 100)
fs = FunctionSpace(mesh, ('P', 1))

base =  lambda x: 0.5 * x[0] * x[1]

eps = (-0.25, 0.5) 
freq = (5, 10)
seed = (11, 22)
noise_perturbation = SpatialPerturbation(
    base,
    cubic_noise(['neumann', 'dirichlet'], [Lx, Ly], freq, seed, (0, 1)),
    [Lx, Ly],
    eps,
)
dofs_perturbation = DofsPerturbation(
    base,
    123,
    eps,
)
for perturbation in (noise_perturbation, dofs_perturbation):
    u0 = perturbation.combine_base_noise(fs)
    uBase = perturbation.base(fs)
    uNoise = perturbation.noise(fs)

    print(f'min(N) = {min(uNoise.x.array)}')
    print(f'max(N) = {max(uNoise.x.array)}')

    plot_colormap(u0, title='$u_0$')
    plot_colormap(uNoise, title='$\mathcal{N}$')

    x_axis, uNoise_x, y_value = cross_section(uNoise, 'y', 0.5)
    fig, ax = plot_line((x_axis, uNoise_x), x_label='$x$', y_label=f'$\mathcal{{N}}(y={y_value:.2f})$')
    ax.hlines(eps, 0, Lx, colors='black', linestyles='dotted', linewidths=0.75)

    y_axis, uNoise_y, x_value = cross_section(uNoise, 'x', 0.5)
    fig, ax = plot_line((y_axis, uNoise_y), x_label='$y$', y_label=f'$\mathcal{{N}}(x={y_value:.2f})$')
    ax.hlines(eps, 0, Lx, colors='black', linestyles='dotted', linewidths=0.75)
min(N) = -0.25
max(N) = 0.4994233082812214
min(N) = -0.2499879345102143
max(N) = 0.49996212192760614
../../_images/886733f8ceb72b736740504ff2325f82aa02c8c11a92c71dcd41b15e659b8638.png ../../_images/5f83b6fc80c3440eb25cb3f8bd330302119e7a971412f10d722b575ccea73ba7.png ../../_images/0e09d66deefdd8670ef6889f397f75372dbd4d9dbe8b9df5ced30dacfdcbaef3.png ../../_images/ded853ccc2c0c5dbaedf2066e237a8da319f7ab5d07bf0826368c98eb5124c16.png ../../_images/6e9db9d21dd9782accdfab025f2e921bdbbbffec5b36a4836a7d742bb560d522.png ../../_images/ea3e738cc52c611a1a47877435933148a90a53f6a81595b82db99dd900b87775.png ../../_images/977eb48bb6132bcc0da798f76fea6af2c09939da2712d0f107eb54332c3e13a9.png ../../_images/3c9064ac9b1a527272797e8b36ff9f56e5a7cda7dd77073e5645180b28dc38cb.png
The Kernel crashed while executing code in the current cell or a previous cell. 

Please review the code in the cell(s) to identify a possible cause of the failure. 

Click <a href='https://aka.ms/vscodeJupyterKernelCrash'>here</a> for more info. 

View Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details.