Skip to content

Commit 9b80577

Browse files
Github action: auto-update.
1 parent fbf823a commit 9b80577

File tree

437 files changed

+295403
-12287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

437 files changed

+295403
-12287
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"\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"
69+
]
70+
},
71+
{
72+
"cell_type": "code",
73+
"execution_count": null,
74+
"metadata": {
75+
"collapsed": false
76+
},
77+
"outputs": [],
78+
"source": [
79+
"# Spectral Differentiation table\nprint(\"-\" * 55)\nprint(f\"{'Resolution':<12} {'Original':<15} {'Noisy':<15} {'Projected':<15}\")\nprint(\"-\" * 55)\n\nfor i, res in enumerate(resolutions):\n print(f\"{res:<12} {errors_original_spectral[i]:<15.2e} {errors_noisy_spectral[i]:<15.2e} {errors_prog_spectral[i]:<15.2e}\")\n\n\n# Spectral Differentiation plot\nplt.figure(figsize=(10, 6))\nplt.semilogy(resolutions, errors_original_spectral, 'o-', label='Original', color='black', linewidth=2.5, markersize=6)\nplt.semilogy(resolutions, errors_noisy_spectral, 'o-', label='Noisy', color='green', linewidth=2.5, markersize=6)\nplt.semilogy(resolutions, errors_prog_spectral, 'o-', label='Projected', color='blue', linewidth=2.5, markersize=6)\nplt.xlabel('Resolution', fontsize=16)\nplt.ylabel('Divergence Error (L2 norm)', fontsize=16)\nplt.title('Spectral Divergence Errors', fontsize=18)\nplt.legend(fontsize=14)\nplt.grid(True, alpha=0.3)\nplt.xticks(fontsize=14)\nplt.yticks(fontsize=14)\nplt.tight_layout()\nplt.show()"
80+
]
81+
},
82+
{
83+
"cell_type": "markdown",
84+
"metadata": {},
85+
"source": [
86+
".. 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"
87+
]
88+
},
89+
{
90+
"cell_type": "code",
91+
"execution_count": null,
92+
"metadata": {
93+
"collapsed": false
94+
},
95+
"outputs": [],
96+
"source": [
97+
"# Finite differences table\nprint(\"-\" * 55)\nprint(f\"{'Resolution':<12} {'Original':<15} {'Noisy':<15} {'Projected':<15}\")\nprint(\"-\" * 55)\n\nfor i, res in enumerate(resolutions):\n print(f\"{res:<12} {errors_original_finite[i]:<15.2e} {errors_noisy_finite[i]:<15.2e} {errors_prog_finite[i]:<15.2e}\")\n\n\n# Finite differences plot\nplt.figure(figsize=(10, 6))\nplt.semilogy(resolutions, errors_original_finite, 'o-', label='Original', color='black', linewidth=2.5, markersize=6)\nplt.semilogy(resolutions, errors_noisy_finite, 'o-', label='Noisy', color='green', linewidth=2.5, markersize=6)\nplt.semilogy(resolutions, errors_prog_finite, 'o-', label='Projected', color='blue', linewidth=2.5, markersize=6)\nplt.xlabel('Resolution', fontsize=16)\nplt.ylabel('Divergence Error (L2 norm)', fontsize=16)\nplt.title('Finite Difference Divergence Errors', fontsize=18)\nplt.legend(fontsize=14)\nplt.grid(True, alpha=0.3)\nplt.xticks(fontsize=14)\nplt.yticks(fontsize=14)\nplt.tight_layout()\nplt.show()"
98+
]
99+
}
100+
],
101+
"metadata": {
102+
"kernelspec": {
103+
"display_name": "Python 3",
104+
"language": "python",
105+
"name": "python3"
106+
},
107+
"language_info": {
108+
"codemirror_mode": {
109+
"name": "ipython",
110+
"version": 3
111+
},
112+
"file_extension": ".py",
113+
"mimetype": "text/x-python",
114+
"name": "python",
115+
"nbconvert_exporter": "python",
116+
"pygments_lexer": "ipython3",
117+
"version": "3.13.7"
118+
}
119+
},
120+
"nbformat": 4,
121+
"nbformat_minor": 0
122+
}
Binary file not shown.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"\n\n# A simple finite-difference solver for the diffusion-advection equation\nAn intro to our loss module's finite difference utility demonstrating\nits use to create a simple numerical solver for the diffusion-advection equation.\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\nimport matplotlib.animation as animation\n\nfrom neuralop.losses.differentiation import FiniteDiff \n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
26+
]
27+
},
28+
{
29+
"cell_type": "markdown",
30+
"metadata": {},
31+
"source": [
32+
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Defining our problem\nWe aim to solve the 2D diffusion advection equation:\n\n\\begin{align}\\frac{\\partial u}{\\partial t} + c_x \\frac{\\partial u}{\\partial x} + c_y \\frac{\\partial u}{\\partial y} = \\nu \\left(\\frac{\\partial^2 u}{\\partial x^2} + \\frac{\\partial^2 u}{\\partial y^2}\\right) + f(x,y,t)\\end{align}\n\nWhere $f(x,y,t)$ is a source term and $c_x$ and $c_y$ are advection speeds in x and y.\nWe set simulation parameters below:\n\n"
33+
]
34+
},
35+
{
36+
"cell_type": "code",
37+
"execution_count": null,
38+
"metadata": {
39+
"collapsed": false
40+
},
41+
"outputs": [],
42+
"source": [
43+
"## Simulation parameters\nLx, Ly = 2.0, 2.0 # Domain lengths\nnx, ny = 64, 64 # Grid resolution\nT = 1.6 # Total simulation time\ndt = 0.001 # Time step\nnu = 0.02 # diffusion coefficient\ncx, cy = 1.0, 0.6 # advection speeds\n\n## Create grid\nX = torch.linspace(0, Lx, nx, device=device).repeat(ny, 1).T \nY = torch.linspace(0, Ly, ny, device=device).repeat(nx, 1) \ndx = Lx / (nx - 1)\ndy = Ly / (ny - 1)\nnt = int(T / dt)\n\n## Initialize finite difference operator\nfd = FiniteDiff(dim=2, h=(dx, dy))\n\n\n## Initial condition and source term\nu = (-torch.sin(2 * np.pi * Y) * torch.cos(2 * np.pi * X)\n + 0.3 * torch.exp(-((X - 0.75)**2 + (Y - 0.5)**2) / 0.02)\n - 0.3 * torch.exp(-((X - 1.25)**2 + (Y - 1.5)**2) / 0.02)).to(device)\n\ndef source_term(X, Y, t):\n return 0.2 * torch.sin(3 * np.pi * X) * torch.cos(3 * np.pi * Y) * torch.cos(4 * np.pi * t)"
44+
]
45+
},
46+
{
47+
"cell_type": "markdown",
48+
"metadata": {},
49+
"source": [
50+
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Simulate evolution using numerical solver\n\n"
51+
]
52+
},
53+
{
54+
"cell_type": "code",
55+
"execution_count": null,
56+
"metadata": {
57+
"collapsed": false
58+
},
59+
"outputs": [],
60+
"source": [
61+
"u_evolution = [u.clone()]\n\nt = torch.tensor(0.0)\nfor _ in range(nt):\n \n # Compute derivatives\n u_x = fd.dx(u)\n u_y = fd.dy(u)\n u_xx = fd.dx(u_x)\n u_yy = fd.dy(u_y)\n\n # Evolve one step in time using Euler's method\n u = u + dt * (-cx * u_x - cy * u_y + nu * (u_xx + u_yy) + source_term(X, Y, t))\n t += dt\n u_evolution.append(u.clone())\n\nu_evolution = torch.stack(u_evolution).cpu().numpy()"
62+
]
63+
},
64+
{
65+
"cell_type": "markdown",
66+
"metadata": {},
67+
"source": [
68+
".. raw:: html\n\n <div style=\"margin-top: 3em;\"></div>\n\n## Animate our solution\n\n"
69+
]
70+
},
71+
{
72+
"cell_type": "code",
73+
"execution_count": null,
74+
"metadata": {
75+
"collapsed": false
76+
},
77+
"outputs": [],
78+
"source": [
79+
"num_frames = 100\nframe_indices = torch.linspace(0, len(u_evolution) - 1, num_frames, dtype=torch.int).cpu().numpy()\nu_frames = u_evolution[frame_indices]\n\nfig, ax = plt.subplots(figsize=(6, 6))\ncmap_u = ax.imshow(u_frames[0], extent=[0, Lx, 0, Ly], origin=\"lower\", cmap=\"plasma\")\nax.set_title(\"Advection-Diffusion: u\")\nplt.colorbar(cmap_u, ax=ax, shrink=0.75)\n\ndef update(frame):\n cmap_u.set_data(u_frames[frame])\n ax.set_title(f\"Time: {frame_indices[frame] * dt:.3f}\")\n ax.set_xticks([])\n ax.set_yticks([])\n return cmap_u,\n\nani = animation.FuncAnimation(fig, update, frames=len(u_frames), interval=50, blit=False)"
80+
]
81+
}
82+
],
83+
"metadata": {
84+
"kernelspec": {
85+
"display_name": "Python 3",
86+
"language": "python",
87+
"name": "python3"
88+
},
89+
"language_info": {
90+
"codemirror_mode": {
91+
"name": "ipython",
92+
"version": 3
93+
},
94+
"file_extension": ".py",
95+
"mimetype": "text/x-python",
96+
"name": "python",
97+
"nbconvert_exporter": "python",
98+
"pygments_lexer": "ipython3",
99+
"version": "3.13.7"
100+
}
101+
},
102+
"nbformat": 4,
103+
"nbformat_minor": 0
104+
}
Binary file not shown.

0 commit comments

Comments
 (0)