You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"\n\n# Divergence-Free Spectral Projection\nAn example demonstrating spectral projection to enforce divergence-free constraints\nin 2D velocity fields\n"
8
+
]
9
+
},
10
+
{
11
+
"cell_type": "markdown",
12
+
"metadata": {},
13
+
"source": [
14
+
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Import the library\nWe first import our `neuralop` library and required dependencies.\n\n"
15
+
]
16
+
},
17
+
{
18
+
"cell_type": "code",
19
+
"execution_count": null,
20
+
"metadata": {
21
+
"collapsed": false
22
+
},
23
+
"outputs": [],
24
+
"source": [
25
+
"import torch\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom neuralop.layers.spectral_projection import spectral_projection_divergence_free\nfrom neuralop.losses.differentiation import FourierDiff, FiniteDiff\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"Using device: {device}\")"
26
+
]
27
+
},
28
+
{
29
+
"cell_type": "markdown",
30
+
"metadata": {},
31
+
"source": [
32
+
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Divergence error computation functions\nWe define two functions to compute the divergence error \nusing spectral differentiation and finite differences.\n\n"
33
+
]
34
+
},
35
+
{
36
+
"cell_type": "code",
37
+
"execution_count": null,
38
+
"metadata": {
39
+
"collapsed": false
40
+
},
41
+
"outputs": [],
42
+
"source": [
43
+
"def div_error_fourier(u, L):\n\"\"\"Compute divergence error using spectral differentiation.\"\"\"\n fourier_diff_2d = FourierDiff(dim=2, L=(L, L), use_fc=False)\n div = fourier_diff_2d.divergence(u)\n error_val = torch.linalg.norm(div, dim=(1, 2)) * (L**2 / (div.shape[-1] * div.shape[-2]))**(0.5)\n return error_val.mean().item()\n\n\ndef div_error_finite_diff(u, L):\n\"\"\"Compute divergence error using FiniteDiff.\"\"\"\n dx = L / u.shape[-1]\n dy = L / u.shape[-2]\n finite_diff_2d = FiniteDiff(dim=2, h=(dx, dy), periodic_in_x=True, periodic_in_y=True)\n div = finite_diff_2d.divergence(u)\n error_val = torch.linalg.norm(div, dim=(1, 2)) * (L**2 / (div.shape[-1] * div.shape[-2]))**(0.5)\n return error_val.mean().item()"
44
+
]
45
+
},
46
+
{
47
+
"cell_type": "markdown",
48
+
"metadata": {},
49
+
"source": [
50
+
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Setting considered\nWe start from a divergence-free velocity field on [0, 2*pi] x [0, 2*pi] \nconstructed from the stream function \u03c8(x,y) = sin(x) * cos(6*y) \n\nVelocity components: \n u_x = \u2202\u03c8/\u2202y = -6 * sin(x) * sin(6*y) \n\n u_y = -\u2202\u03c8/\u2202x = - cos(x) * cos(6*y) \n\n-------------------------------------------------------\n\nMathematical verification of divergence-free property: \n\n \u2207\u00b7u = \u2202u_x/\u2202x + \u2202u_y/\u2202y \n\n = \u2202/\u2202x[-6*sin(x) * sin(6*y)] + \u2202/\u2202y[-cos(x) * cos(6*y)] \n\n = -6*cos(x) * sin(6*y) + 6*cos(x) * sin(6*y) \n\n = 0 \u2713 \n\n-------------------------------------------------------\n\n\nWe then add 10% noise to break the divergence-free property. \n\nWe then apply the spectral projection to restore the divergence-free property. \n\nWe then compute the divergence error for the original, noisy, and projected fields. \n\nWe repeat this at various resolutions, [256, 512, 1024, 2048, 4096, 8192].\n\n"
51
+
]
52
+
},
53
+
{
54
+
"cell_type": "code",
55
+
"execution_count": null,
56
+
"metadata": {
57
+
"collapsed": false
58
+
},
59
+
"outputs": [],
60
+
"source": [
61
+
"L = 2 * np.pi\nnoise_level = 0.1\nresolutions = [256, 512, 1024, 2048, 4096, 8192]\n\n\nerrors_original_spectral = []\nerrors_original_finite = []\nerrors_noisy_spectral = []\nerrors_noisy_finite = []\nerrors_prog_spectral = []\nerrors_prog_finite = []\n\nfor target_resolution in resolutions:\n \n # Create coordinate grids for this resolution\n xs = torch.arange(target_resolution, device=device, dtype=torch.float64) * (L / target_resolution)\n ys = torch.arange(target_resolution, device=device, dtype=torch.float64) * (L / target_resolution)\n X, Y = torch.meshgrid(xs, ys, indexing='ij')\n \n # Create divergence-free field using the stream function defined earlier\n u_x = -6.0 * torch.sin(X) * torch.sin(6.0 * Y)\n u_y = -torch.cos(X) * torch.cos(6.0 * Y)\n u = torch.stack([u_x, u_y], dim=0).unsqueeze(0).to(device=device, dtype=torch.float64)\n \n # Add noise to break divergence-free property\n mean_magnitude = torch.mean(torch.sqrt(u[:, 0]**2 + u[:, 1]**2))\n noise = torch.randn_like(u, dtype=torch.float64) * noise_level * mean_magnitude\n u_noisy = u + noise\n \n # Apply spectral projection to restore divergence-free property\n u_proj = spectral_projection_divergence_free(u_noisy, L, constraint_modes=(64, 64))\n \n # Compute divergence errors for all three fields\n errors_original_spectral.append(div_error_fourier(u, L))\n errors_original_finite.append(div_error_finite_diff(u, L))\n errors_noisy_spectral.append(div_error_fourier(u_noisy, L))\n errors_noisy_finite.append(div_error_finite_diff(u_noisy, L))\n errors_prog_spectral.append(div_error_fourier(u_proj, L))\n errors_prog_finite.append(div_error_finite_diff(u_proj, L))"
62
+
]
63
+
},
64
+
{
65
+
"cell_type": "markdown",
66
+
"metadata": {},
67
+
"source": [
68
+
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Divergence Errors using Spectral Differentiation \nThe Fourier differentiation method computes derivatives in the spectral domain \nby transforming the field to Fourier space, applying the appropriate wavenumber \noperators, and transforming back. \n\nWe display the divergence error for the original, noisy, and projected fields \nat the different resolutions. \n\nNote that at lower resolutions, finite differences are not accurate enough \nto properly compute the divergence error, which is why the errors appear higher \ninitially but improve at higher resolutions. This is a limitation of \nfinite differences for computing derivatives, not an issue with the \nspectral projection itself. Spectral differentiation provides more accurate \nderivative calculations at lower resolutions.\n\n"
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Divergence Errors using Finite Differences\nThe finite difference method approximates derivatives using central differences. \n\nWe display the divergence error for the original, noisy, and projected fields \nat the different resolutions.\n\n"
0 commit comments