Exponax Integration¶
Dataset generation using Exponax spectral PDE solvers.
Exponax provides pseudo-spectral solvers for a range of PDEs on periodic domains. FlowPDE wraps these to generate training data for flow-based models.
All generators subclass ExponaxDatasetGenerator, which provides shared observation
augmentation, JAX→torch conversion, statistics, and dataset wrapping. Every dataset
emits {'input': condition, 'target': solution}.
Base Generator¶
ExponaxDatasetGenerator
¶
Base class for concise Exponax problem generators.
Source code in flowpde/datasets/exponax/generator.py
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | |
apply_observation_augmentation(data, *, observation_key, problem, n, seed)
¶
Add observation noise and/or spatial masking, in place.
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
A dict to forward to |
Dict[str, Any]
|
(pass as |
Dict[str, Any]
|
|
Source code in flowpde/datasets/exponax/generator.py
Poisson Generator¶
Source → solution pairs for the Poisson equation \(\nabla^2 u = f\) (1D/2D/3D).
PoissonGenerator
¶
Bases: ExponaxDatasetGenerator
Generate Poisson equation datasets using Exponax.
Workflow
- Create simple smooth sine/cosine source terms f
- Solve \(\nabla^2 u = f\) via 'exponax.poisson.Poisson'
- Convert JAX arrays -> PyTorch tensors
- Wrap in a 'PDEDataset'
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Optional[GenerationConfig]
|
A 'PoissonConfig' instance. All keyword arguments are forwarded to 'PoissonConfig' if config is None. |
None
|
Source code in flowpde/datasets/exponax/poisson.py
generate(num_samples=None, seed=None, problem='forward')
¶
Generate a Poisson dataset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_samples
|
Optional[int]
|
Override 'config.num_samples'. |
None
|
seed
|
Optional[int]
|
Override 'config.seed'. |
None
|
problem
|
Literal['forward', 'inverse']
|
'forward' (data->solution) or 'inverse' (solution->data). |
'forward'
|
Returns:
| Type | Description |
|---|---|
PDEDataset
|
A |
Source code in flowpde/datasets/exponax/poisson.py
PoissonConfig
dataclass
¶
Bases: GenerationConfig
Configuration specific to the Poisson equation.
Attributes:
| Name | Type | Description |
|---|---|---|
order |
int
|
Order of the Poisson operator (default 2 -> Laplacian). |
source_num_terms |
int
|
Number of sine/cosine terms per source field. |
source_max_mode |
int
|
Largest integer wavenumber sampled per dimension. |
Source code in flowpde/datasets/exponax/poisson.py
Burgers Generator¶
Initial-condition → final-state pairs (optionally full trajectories) for the Burgers equation \(\partial_t u + u \cdot \nabla u = \nu \nabla^2 u\) (1D/2D).
BurgersGenerator
¶
Bases: ExponaxDatasetGenerator
Generate Burgers equation datasets using Exponax.
Workflow
- Create simple smooth sine/cosine initial conditions
- Step forward using
exponax.stepper.Burgers(optionally viaexponax.rolloutfor trajectories) - Convert JAX arrays → PyTorch tensors
- Wrap in a
PDEDataset
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Optional[GenerationConfig]
|
A |
None
|
Source code in flowpde/datasets/exponax/burgers.py
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
generate(num_samples=None, seed=None, problem='forward')
¶
Generate a Burgers dataset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_samples
|
Optional[int]
|
Override |
None
|
seed
|
Optional[int]
|
Override |
None
|
problem
|
Literal['forward', 'inverse']
|
|
'forward'
|
Returns:
| Type | Description |
|---|---|
PDEDataset
|
A |
PDEDataset
|
(and optionally |
Source code in flowpde/datasets/exponax/burgers.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
BurgersConfig
dataclass
¶
Bases: GenerationConfig
Configuration specific to the Burgers equation.
Attributes:
| Name | Type | Description |
|---|---|---|
dt |
float
|
Time-step size for the ETDRK stepper. |
num_steps |
int
|
Number of time steps to advance. |
diffusivity_min |
float
|
Lower bound of the log-uniform per-sample viscosity ν. Each sample gets an independently drawn ν from LogUniform(diffusivity_min, diffusivity_max), so the dataset spans multiple physical regimes (smooth ↔ shock-dominated). |
diffusivity_max |
float
|
Upper bound of the log-uniform per-sample viscosity. |
convection_scale |
float
|
Scaling of the nonlinear convection term. |
single_channel |
bool
|
If True, use a single-channel formulation (scalar Burgers) regardless of spatial dimension. |
ic_num_terms |
int
|
Number of sine/cosine terms per initial condition. |
ic_max_mode |
int
|
Largest integer wavenumber sampled per dimension. |
store_trajectory |
bool
|
If True, keep the full rollout trajectory
in the dataset (key |
Source code in flowpde/datasets/exponax/burgers.py
Darcy Generator¶
\((\kappa, f) \rightarrow u\) for variable-coefficient Poisson
\(-\nabla \cdot (\kappa \nabla u) = f\). generate() accepts inverse_mode in
{'both', 'coefficient', 'source'}.
DarcyGenerator
¶
Bases: ExponaxDatasetGenerator
Generate Darcy-flow / variable-coefficient Poisson datasets.
Workflow:
1. Draw per-sample log-normal $\kappa$ fields from a GRF.
2. Draw per-sample smooth Fourier source fields.
3. Solve $-\nabla\cdot(\kappa\,\nabla u)=f$ via FD + fixed-step CG for each sample.
4. Optionally apply additive noise and/or spatial masking to the
solution field (for inverse-problem datasets).
5. Convert to PyTorch tensors and return a `DarcyDataset`.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Optional[GenerationConfig]
|
A |
None
|
Example
gen = DarcyGenerator(num_points=64)
train = gen.generate(num_samples=1000, seed=0)
test = gen.generate(num_samples=200, seed=1)
Source code in flowpde/datasets/exponax/darcy.py
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 | |
generate(num_samples=None, seed=None, problem='forward', inverse_mode='both')
¶
Generate a Darcy-flow dataset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_samples
|
Optional[int]
|
Override |
None
|
seed
|
Optional[int]
|
Override |
None
|
problem
|
Literal['forward', 'inverse']
|
|
'forward'
|
inverse_mode
|
Literal['both', 'coefficient', 'source']
|
Inverse mapping to use:
|
'both'
|
Returns:
| Type | Description |
|---|---|
DarcyDataset
|
A |
Source code in flowpde/datasets/exponax/darcy.py
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 | |
DarcyConfig
dataclass
¶
Bases: GenerationConfig
Configuration for the Darcy-flow / variable-coefficient Poisson generator.
Inherits all base fields from GenerationConfig (num_points,
num_samples, seed, torch_device, obs_noise_std,
obs_mask_fraction).
Attributes:
| Name | Type | Description |
|---|---|---|
num_spatial_dims |
int
|
Spatial dimension (1 or 2). Default 2. |
domain_extent |
float
|
Side length of the square/interval domain. Default 1.0 ([0,1]^d), which is the standard Darcy benchmark domain. |
kappa_alpha |
float
|
Spectral exponent \(\alpha\) for the \(\kappa\) GRF power spectrum \(S(\lvert k\rvert) \propto (\tau^2 + \lvert k\rvert^2)^{-\alpha}\). Higher → smoother permeability. \(\alpha = 2.0\) matches the original FNO Darcy benchmark. |
kappa_tau |
float
|
GRF inverse correlation length \(\tau\). Higher → more oscillatory \(\kappa\) with smaller features. |
kappa_scale |
float
|
Standard deviation of \(\log\kappa\) before exponentiation. Scale 1.0 gives \(\kappa \in [e^{-2}, e^{2}] \approx [0.14,\, 7.4]\) roughly. Increase for higher contrast between high- and low-permeability regions. |
kappa_min |
float
|
Hard lower bound on \(\kappa\) (positivity / ellipticity floor). |
f_cutoff |
int
|
Fourier cutoff for the random source term. |
f_amplitude_min |
float
|
Minimum per-sample amplitude scaling for f. |
f_amplitude_max |
float
|
Maximum per-sample amplitude scaling for f. |
cg_steps |
int
|
Fixed number of conjugate-gradient iterations used to solve
the linear system. The solver is unpreconditioned, so the count
needed grows with the grid and with the contrast in κ. Measured
on a 64×64 grid at the default κ: 100 steps leaves a relative
residual of 2e-1 (the "solutions" are 20 % wrong), 500 leaves
8e-4, and 2000 converges to machine precision. Do not lower this
for speed without checking |
cg_tolerance |
Optional[float]
|
Largest acceptable CG relative residual, checked over
every generated sample. |
Source code in flowpde/datasets/exponax/darcy.py
Datasets¶
PDEDataset
¶
Bases: Dataset
PyTorch Dataset wrapping Exponax-generated PDE data.
Returns samples as {'input': ..., 'target': ...} where the semantics of input and target depend on the PDE type and the chosen problem direction:
- Poisson (static): input=source, target=solution (forward) or input=solution, target=source (inverse).
- Burgers (time-dependent): input=initial condition, target=final state (forward) or vice-versa (inverse).
When partial observations are enabled (obs_mask_fraction < 1.0),
__getitem__ appends the observation mask to the conditioning input
and additionally returns 'obs_mask': a float tensor of shape
(1, *spatial) with 1 at observed locations and 0 elsewhere.
The dataset also stores normalization statistics and generation config for reference.
Source code in flowpde/datasets/exponax/base.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
input_fields
property
¶
Raw field names composing sample['input'], in channel order.
The mask is appended to the input as an extra channel, so it has to
appear here too or the names no longer line up with the channels --
which is exactly what denormalize_channels splits on. It has no
statistics, so it passes through denormalization unchanged.
target_fields
property
¶
Raw field names composing sample['target'], in channel order.
__init__(data, problem='forward', metadata=None, normalizer=None)
¶
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Dict[str, Tensor]
|
Dictionary with at least two tensor entries whose keys identify the PDE fields (e.g. 'source' / 'solution' for Poisson, 'initial' / 'final' for Burgers). |
required |
problem
|
Literal['forward', 'inverse']
|
'forward' maps natural data -> solution; 'inverse' reverses the mapping. |
'forward'
|
metadata
|
Optional[Dict[str, Any]]
|
Optional dict with 'stats', 'config', etc. |
None
|
normalizer
|
Optional[FieldNormalizer]
|
Optional |
None
|
Source code in flowpde/datasets/exponax/base.py
set_normalizer(normalizer)
¶
Attach (or clear) a field normalizer applied on every access.
Pass the training split's normalizer to validation and test splits so all data is standardized with the same statistics.
Returns:
| Type | Description |
|---|---|
PDEDataset
|
|
Source code in flowpde/datasets/exponax/base.py
get_stats()
¶
get_config()
¶
GenerationConfig
dataclass
¶
Configuration for PDE data generation via Exponax.
Attributes:
| Name | Type | Description |
|---|---|---|
num_spatial_dims |
int
|
Number of spatial dimensions (1, 2, or 3) |
num_points |
int
|
Number of grid points per spatial dimension |
domain_extent |
float
|
Physical size of the periodic domain |
num_samples |
int
|
Number of samples to generate |
seed |
int
|
Random seed for reproducibility |
torch_device |
str
|
Target PyTorch device for converted tensors |
obs_noise_std |
float
|
Optional additive Gaussian noise applied to the inverse-problem observation field. Set to 0.0 to disable. |
obs_mask_fraction |
float
|
Fraction of spatial grid points that are observed
in inverse-problem datasets. Each sample independently draws a
random Bernoulli mask with this probability; unobserved locations
are zeroed out in the observation field. The binary mask
(1 = observed, 0 = unobserved) is stored as |
Source code in flowpde/datasets/exponax/base.py
Utilities¶
utilities
¶
Exponax Dataset Utilities¶
Utility helpers for Exponax-backed datasets, including JAX↔PyTorch conversions and normalization stats.
jax_to_torch(jax_array, device='cpu', dtype=torch.float32)
¶
Convert a JAX array to a PyTorch tensor.
Uses NumPy as an intermediate format for maximum compatibility across different JAX/PyTorch device configurations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
jax_array
|
Any
|
JAX array to convert |
required |
device
|
DeviceType
|
Target PyTorch device ('cpu', 'cuda', etc.) |
'cpu'
|
dtype
|
Optional[dtype]
|
Target PyTorch dtype (default: torch.float32) |
float32
|
Returns:
| Type | Description |
|---|---|
Tensor
|
PyTorch tensor on the specified device |
Source code in flowpde/datasets/exponax/utilities.py
compute_normalization_stats(tensor)
¶
Compute normalization statistics for a tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
Tensor
|
Input tensor of any shape |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary with 'mean', 'std', 'min', and 'max' values. |
Source code in flowpde/datasets/exponax/utilities.py
sample_sine_fields(key, *, n, num_spatial_dims, num_points, domain_extent, num_terms, max_mode)
¶
Generate simple smooth sine fields with random modes, weights, and phases.