Download data.py from ElBalor/AlienX-2D-Isotropic-Stencil: direct link, hf CLI and curl.
- Browser
- Download file 2.84 kB
-
https://huggingface.co/ElBalor/AlienX-2D-Isotropic-Stencil/resolve/main/data.py
- Command line
-
hf download hf://ElBalor/AlienX-2D-Isotropic-Stencil/data.py
-
curl -L -o data.py https://huggingface.co/ElBalor/AlienX-2D-Isotropic-Stencil/resolve/main/data.py
2.84 kB
| """ | |
| AlienX (ISN) - 2D Release v2: GPU Darcy Flow Data Generator | |
| ============================================================ | |
| Pull-back rotation: fields are evaluated in reference coordinates, then the | |
| gradients are pushed forward with the rotation matrix. The domain always | |
| stays within [-1, 1]^2 - no diamond stretching at 45 degrees. | |
| Analytical gradients (no finite differences) - the fix for the numerical | |
| gradient artifacts that produced the 45-degree residual in v1. | |
| Eric Yaka (Elbalor / The Digital Necromancer) | |
| """ | |
| import math | |
| import torch | |
| def generate_darcy_sample_gpu(resolution, device, angle_deg=0.0, seed=None): | |
| """ | |
| Generate a Darcy flow sample on the GPU with pull-back rotation. | |
| Args: | |
| resolution: grid size (nx = ny) | |
| device: torch device | |
| angle_deg: rotation angle of the permeability field, degrees | |
| seed: optional RNG seed for reproducibility | |
| Returns: | |
| coords: [N, 2] grid coordinates in [-1, 1]^2 | |
| k: [N] permeability field | |
| grad_k_mag: [N] magnitude of grad k (pushed forward) | |
| grad_k_vec: [N, 2] gradient vector of k (pushed forward) | |
| p: [N] pressure field (ground truth) | |
| """ | |
| if seed is not None: | |
| torch.manual_seed(seed) | |
| nx = ny = resolution | |
| x = torch.linspace(-1, 1, nx, device=device) | |
| y = torch.linspace(-1, 1, ny, device=device) | |
| X, Y = torch.meshgrid(x, y, indexing='ij') | |
| coords = torch.stack([X.flatten(), Y.flatten()], dim=-1) | |
| theta = angle_deg * math.pi / 180.0 | |
| R_inv = torch.tensor([[math.cos(-theta), -math.sin(-theta)], | |
| [math.sin(-theta), math.cos(-theta)]], device=device) | |
| coords_ref = coords @ R_inv.T | |
| X_r = coords_ref[:, 0].reshape(nx, ny) | |
| Y_r = coords_ref[:, 1].reshape(nx, ny) | |
| k = 1.0 + 0.3 * torch.sin(2*math.pi*X_r + 1.0) * torch.cos(3*math.pi*Y_r - 0.5) | |
| k += 0.2 * torch.sin(4*math.pi*X_r*Y_r) | |
| k = torch.clamp(k, 0.5, 2.0) | |
| p = torch.sin(2*math.pi*X_r) * torch.cos(2*math.pi*Y_r) + \ | |
| 0.5*torch.sin(5*math.pi*X_r + 1.3)*torch.cos(4*math.pi*Y_r - 0.7) | |
| dk_dX = (0.3 * (2*math.pi) * torch.cos(2*math.pi*X_r + 1.0) * torch.cos(3*math.pi*Y_r - 0.5) + | |
| 0.2 * (4*math.pi*Y_r) * torch.cos(4*math.pi*X_r*Y_r)) | |
| dk_dY = (-0.3 * (3*math.pi) * torch.sin(2*math.pi*X_r + 1.0) * torch.sin(3*math.pi*Y_r - 0.5) + | |
| 0.2 * (4*math.pi*X_r) * torch.cos(4*math.pi*X_r*Y_r)) | |
| grad_ref = torch.stack([dk_dX.flatten(), dk_dY.flatten()], dim=-1) | |
| R = torch.tensor([[math.cos(theta), -math.sin(theta)], | |
| [math.sin(theta), math.cos(theta)]], device=device) | |
| grad_k_vec = grad_ref @ R.T | |
| grad_k_mag = torch.sqrt((grad_k_vec**2).sum(-1)).flatten() | |
| return coords, k.flatten(), grad_k_mag, grad_k_vec, p.flatten() | |