Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:30:10 +08:00
commit f0bd18fb4e
824 changed files with 331919 additions and 0 deletions

343
skills/fluidsim/SKILL.md Normal file
View File

@@ -0,0 +1,343 @@
---
name: fluidsim
description: Framework for computational fluid dynamics simulations using Python. Use when running fluid dynamics simulations including Navier-Stokes equations (2D/3D), shallow water equations, stratified flows, or when analyzing turbulence, vortex dynamics, or geophysical flows. Provides pseudospectral methods with FFT, HPC support, and comprehensive output analysis.
---
# FluidSim
## Overview
FluidSim is an object-oriented Python framework for high-performance computational fluid dynamics (CFD) simulations. It provides solvers for periodic-domain equations using pseudospectral methods with FFT, delivering performance comparable to Fortran/C++ while maintaining Python's ease of use.
**Key strengths**:
- Multiple solvers: 2D/3D Navier-Stokes, shallow water, stratified flows
- High performance: Pythran/Transonic compilation, MPI parallelization
- Complete workflow: Parameter configuration, simulation execution, output analysis
- Interactive analysis: Python-based post-processing and visualization
## Core Capabilities
### 1. Installation and Setup
Install fluidsim using uv with appropriate feature flags:
```bash
# Basic installation
uv uv pip install fluidsim
# With FFT support (required for most solvers)
uv uv pip install "fluidsim[fft]"
# With MPI for parallel computing
uv uv pip install "fluidsim[fft,mpi]"
```
Set environment variables for output directories (optional):
```bash
export FLUIDSIM_PATH=/path/to/simulation/outputs
export FLUIDDYN_PATH_SCRATCH=/path/to/working/directory
```
No API keys or authentication required.
See `references/installation.md` for complete installation instructions and environment configuration.
### 2. Running Simulations
Standard workflow consists of five steps:
**Step 1**: Import solver
```python
from fluidsim.solvers.ns2d.solver import Simul
```
**Step 2**: Create and configure parameters
```python
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = 256
params.oper.Lx = params.oper.Ly = 2 * 3.14159
params.nu_2 = 1e-3
params.time_stepping.t_end = 10.0
params.init_fields.type = "noise"
```
**Step 3**: Instantiate simulation
```python
sim = Simul(params)
```
**Step 4**: Execute
```python
sim.time_stepping.start()
```
**Step 5**: Analyze results
```python
sim.output.phys_fields.plot("vorticity")
sim.output.spatial_means.plot()
```
See `references/simulation_workflow.md` for complete examples, restarting simulations, and cluster deployment.
### 3. Available Solvers
Choose solver based on physical problem:
**2D Navier-Stokes** (`ns2d`): 2D turbulence, vortex dynamics
```python
from fluidsim.solvers.ns2d.solver import Simul
```
**3D Navier-Stokes** (`ns3d`): 3D turbulence, realistic flows
```python
from fluidsim.solvers.ns3d.solver import Simul
```
**Stratified flows** (`ns2d.strat`, `ns3d.strat`): Oceanic/atmospheric flows
```python
from fluidsim.solvers.ns2d.strat.solver import Simul
params.N = 1.0 # Brunt-Väisälä frequency
```
**Shallow water** (`sw1l`): Geophysical flows, rotating systems
```python
from fluidsim.solvers.sw1l.solver import Simul
params.f = 1.0 # Coriolis parameter
```
See `references/solvers.md` for complete solver list and selection guidance.
### 4. Parameter Configuration
Parameters are organized hierarchically and accessed via dot notation:
**Domain and resolution**:
```python
params.oper.nx = 256 # grid points
params.oper.Lx = 2 * pi # domain size
```
**Physical parameters**:
```python
params.nu_2 = 1e-3 # viscosity
params.nu_4 = 0 # hyperviscosity (optional)
```
**Time stepping**:
```python
params.time_stepping.t_end = 10.0
params.time_stepping.USE_CFL = True # adaptive time step
params.time_stepping.CFL = 0.5
```
**Initial conditions**:
```python
params.init_fields.type = "noise" # or "dipole", "vortex", "from_file", "in_script"
```
**Output settings**:
```python
params.output.periods_save.phys_fields = 1.0 # save every 1.0 time units
params.output.periods_save.spectra = 0.5
params.output.periods_save.spatial_means = 0.1
```
The Parameters object raises `AttributeError` for typos, preventing silent configuration errors.
See `references/parameters.md` for comprehensive parameter documentation.
### 5. Output and Analysis
FluidSim produces multiple output types automatically saved during simulation:
**Physical fields**: Velocity, vorticity in HDF5 format
```python
sim.output.phys_fields.plot("vorticity")
sim.output.phys_fields.plot("vx")
```
**Spatial means**: Time series of volume-averaged quantities
```python
sim.output.spatial_means.plot()
```
**Spectra**: Energy and enstrophy spectra
```python
sim.output.spectra.plot1d()
sim.output.spectra.plot2d()
```
**Load previous simulations**:
```python
from fluidsim import load_sim_for_plot
sim = load_sim_for_plot("simulation_dir")
sim.output.phys_fields.plot()
```
**Advanced visualization**: Open `.h5` files in ParaView or VisIt for 3D visualization.
See `references/output_analysis.md` for detailed analysis workflows, parametric study analysis, and data export.
### 6. Advanced Features
**Custom forcing**: Maintain turbulence or drive specific dynamics
```python
params.forcing.enable = True
params.forcing.type = "tcrandom" # time-correlated random forcing
params.forcing.forcing_rate = 1.0
```
**Custom initial conditions**: Define fields in script
```python
params.init_fields.type = "in_script"
sim = Simul(params)
X, Y = sim.oper.get_XY_loc()
vx = sim.state.state_phys.get_var("vx")
vx[:] = sin(X) * cos(Y)
sim.time_stepping.start()
```
**MPI parallelization**: Run on multiple processors
```bash
mpirun -np 8 python simulation_script.py
```
**Parametric studies**: Run multiple simulations with different parameters
```python
for nu in [1e-3, 5e-4, 1e-4]:
params = Simul.create_default_params()
params.nu_2 = nu
params.output.sub_directory = f"nu{nu}"
sim = Simul(params)
sim.time_stepping.start()
```
See `references/advanced_features.md` for forcing types, custom solvers, cluster submission, and performance optimization.
## Common Use Cases
### 2D Turbulence Study
```python
from fluidsim.solvers.ns2d.solver import Simul
from math import pi
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = 512
params.oper.Lx = params.oper.Ly = 2 * pi
params.nu_2 = 1e-4
params.time_stepping.t_end = 50.0
params.time_stepping.USE_CFL = True
params.init_fields.type = "noise"
params.output.periods_save.phys_fields = 5.0
params.output.periods_save.spectra = 1.0
sim = Simul(params)
sim.time_stepping.start()
# Analyze energy cascade
sim.output.spectra.plot1d(tmin=30.0, tmax=50.0)
```
### Stratified Flow Simulation
```python
from fluidsim.solvers.ns2d.strat.solver import Simul
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = 256
params.N = 2.0 # stratification strength
params.nu_2 = 5e-4
params.time_stepping.t_end = 20.0
# Initialize with dense layer
params.init_fields.type = "in_script"
sim = Simul(params)
X, Y = sim.oper.get_XY_loc()
b = sim.state.state_phys.get_var("b")
b[:] = exp(-((X - 3.14)**2 + (Y - 3.14)**2) / 0.5)
sim.state.statephys_from_statespect()
sim.time_stepping.start()
sim.output.phys_fields.plot("b")
```
### High-Resolution 3D Simulation with MPI
```python
from fluidsim.solvers.ns3d.solver import Simul
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = params.oper.nz = 512
params.nu_2 = 1e-5
params.time_stepping.t_end = 10.0
params.init_fields.type = "noise"
sim = Simul(params)
sim.time_stepping.start()
```
Run with:
```bash
mpirun -np 64 python script.py
```
### Taylor-Green Vortex Validation
```python
from fluidsim.solvers.ns2d.solver import Simul
import numpy as np
from math import pi
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = 128
params.oper.Lx = params.oper.Ly = 2 * pi
params.nu_2 = 1e-3
params.time_stepping.t_end = 10.0
params.init_fields.type = "in_script"
sim = Simul(params)
X, Y = sim.oper.get_XY_loc()
vx = sim.state.state_phys.get_var("vx")
vy = sim.state.state_phys.get_var("vy")
vx[:] = np.sin(X) * np.cos(Y)
vy[:] = -np.cos(X) * np.sin(Y)
sim.state.statephys_from_statespect()
sim.time_stepping.start()
# Validate energy decay
df = sim.output.spatial_means.load()
# Compare with analytical solution
```
## Quick Reference
**Import solver**: `from fluidsim.solvers.ns2d.solver import Simul`
**Create parameters**: `params = Simul.create_default_params()`
**Set resolution**: `params.oper.nx = params.oper.ny = 256`
**Set viscosity**: `params.nu_2 = 1e-3`
**Set end time**: `params.time_stepping.t_end = 10.0`
**Run simulation**: `sim = Simul(params); sim.time_stepping.start()`
**Plot results**: `sim.output.phys_fields.plot("vorticity")`
**Load simulation**: `sim = load_sim_for_plot("path/to/sim")`
## Resources
**Documentation**: https://fluidsim.readthedocs.io/
**Reference files**:
- `references/installation.md`: Complete installation instructions
- `references/solvers.md`: Available solvers and selection guide
- `references/simulation_workflow.md`: Detailed workflow examples
- `references/parameters.md`: Comprehensive parameter documentation
- `references/output_analysis.md`: Output types and analysis methods
- `references/advanced_features.md`: Forcing, MPI, parametric studies, custom solvers

View File

@@ -0,0 +1,398 @@
# Advanced Features
## Custom Forcing
### Forcing Types
FluidSim supports several forcing mechanisms to maintain turbulence or drive specific dynamics.
#### Time-Correlated Random Forcing
Most common for sustained turbulence:
```python
params.forcing.enable = True
params.forcing.type = "tcrandom"
params.forcing.nkmin_forcing = 2 # minimum forced wavenumber
params.forcing.nkmax_forcing = 5 # maximum forced wavenumber
params.forcing.forcing_rate = 1.0 # energy injection rate
params.forcing.tcrandom_time_correlation = 1.0 # correlation time
```
#### Proportional Forcing
Maintains a specific energy distribution:
```python
params.forcing.type = "proportional"
params.forcing.forcing_rate = 1.0
```
#### Custom Forcing in Script
Define forcing directly in the launch script:
```python
params.forcing.enable = True
params.forcing.type = "in_script"
sim = Simul(params)
# Define custom forcing function
def compute_forcing_fft(sim):
"""Compute forcing in Fourier space"""
forcing_vx_fft = sim.oper.create_arrayK(value=0.)
forcing_vy_fft = sim.oper.create_arrayK(value=0.)
# Add custom forcing logic
# Example: force specific modes
forcing_vx_fft[10, 10] = 1.0 + 0.5j
return forcing_vx_fft, forcing_vy_fft
# Override forcing method
sim.forcing.forcing_maker.compute_forcing_fft = lambda: compute_forcing_fft(sim)
# Run simulation
sim.time_stepping.start()
```
## Custom Initial Conditions
### In-Script Initialization
Full control over initial fields:
```python
from math import pi
import numpy as np
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = 256
params.oper.Lx = params.oper.Ly = 2 * pi
params.init_fields.type = "in_script"
sim = Simul(params)
# Get coordinate arrays
X, Y = sim.oper.get_XY_loc()
# Define velocity fields
vx = sim.state.state_phys.get_var("vx")
vy = sim.state.state_phys.get_var("vy")
# Taylor-Green vortex
vx[:] = np.sin(X) * np.cos(Y)
vy[:] = -np.cos(X) * np.sin(Y)
# Initialize state in Fourier space
sim.state.statephys_from_statespect()
# Run simulation
sim.time_stepping.start()
```
### Layer Initialization (Stratified Flows)
Set up density layers:
```python
from fluidsim.solvers.ns2d.strat.solver import Simul
params = Simul.create_default_params()
params.N = 1.0 # stratification
params.init_fields.type = "in_script"
sim = Simul(params)
# Define dense layer
X, Y = sim.oper.get_XY_loc()
b = sim.state.state_phys.get_var("b") # buoyancy field
# Gaussian density anomaly
x0, y0 = pi, pi
sigma = 0.5
b[:] = np.exp(-((X - x0)**2 + (Y - y0)**2) / (2 * sigma**2))
sim.state.statephys_from_statespect()
sim.time_stepping.start()
```
## Parallel Computing with MPI
### Running MPI Simulations
Install with MPI support:
```bash
uv pip install "fluidsim[fft,mpi]"
```
Run with MPI:
```bash
mpirun -np 8 python simulation_script.py
```
FluidSim automatically detects MPI and distributes computation.
### MPI-Specific Parameters
```python
# No special parameters needed
# FluidSim handles domain decomposition automatically
# For very large 3D simulations
params.oper.nx = 512
params.oper.ny = 512
params.oper.nz = 512
# Run with: mpirun -np 64 python script.py
```
### Output with MPI
Output files are written from rank 0 processor. Analysis scripts work identically for serial and MPI runs.
## Parametric Studies
### Running Multiple Simulations
Script to generate and run multiple parameter combinations:
```python
from fluidsim.solvers.ns2d.solver import Simul
import numpy as np
# Parameter ranges
viscosities = [1e-3, 5e-4, 1e-4, 5e-5]
resolutions = [128, 256, 512]
for nu in viscosities:
for nx in resolutions:
params = Simul.create_default_params()
# Configure simulation
params.oper.nx = params.oper.ny = nx
params.nu_2 = nu
params.time_stepping.t_end = 10.0
# Unique output directory
params.output.sub_directory = f"nu{nu}_nx{nx}"
# Run simulation
sim = Simul(params)
sim.time_stepping.start()
```
### Cluster Submission
Submit multiple jobs to a cluster:
```python
from fluiddyn.clusters.legi import Calcul8 as Cluster
cluster = Cluster()
for nu in viscosities:
for nx in resolutions:
script_content = f"""
from fluidsim.solvers.ns2d.solver import Simul
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = {nx}
params.nu_2 = {nu}
params.time_stepping.t_end = 10.0
params.output.sub_directory = "nu{nu}_nx{nx}"
sim = Simul(params)
sim.time_stepping.start()
"""
with open(f"job_nu{nu}_nx{nx}.py", "w") as f:
f.write(script_content)
cluster.submit_script(
f"job_nu{nu}_nx{nx}.py",
name_run=f"sim_nu{nu}_nx{nx}",
nb_nodes=1,
nb_cores_per_node=24,
walltime="12:00:00"
)
```
### Analyzing Parametric Studies
```python
import os
import pandas as pd
from fluidsim import load_sim_for_plot
import matplotlib.pyplot as plt
results = []
# Collect data from all simulations
for sim_dir in os.listdir("simulations"):
sim_path = f"simulations/{sim_dir}"
if not os.path.isdir(sim_path):
continue
try:
sim = load_sim_for_plot(sim_path)
# Extract parameters
nu = sim.params.nu_2
nx = sim.params.oper.nx
# Extract results
df = sim.output.spatial_means.load()
final_energy = df["E"].iloc[-1]
mean_energy = df["E"].mean()
results.append({
"nu": nu,
"nx": nx,
"final_energy": final_energy,
"mean_energy": mean_energy
})
except Exception as e:
print(f"Error loading {sim_dir}: {e}")
# Analyze results
results_df = pd.DataFrame(results)
# Plot results
plt.figure(figsize=(10, 6))
for nx in results_df["nx"].unique():
subset = results_df[results_df["nx"] == nx]
plt.plot(subset["nu"], subset["mean_energy"],
marker="o", label=f"nx={nx}")
plt.xlabel("Viscosity")
plt.ylabel("Mean Energy")
plt.xscale("log")
plt.legend()
plt.savefig("parametric_study_results.png")
```
## Custom Solvers
### Extending Existing Solvers
Create a new solver by inheriting from an existing one:
```python
from fluidsim.solvers.ns2d.solver import Simul as SimulNS2D
from fluidsim.base.setofvariables import SetOfVariables
class SimulCustom(SimulNS2D):
"""Custom solver with additional physics"""
@staticmethod
def _complete_params_with_default(params):
"""Add custom parameters"""
SimulNS2D._complete_params_with_default(params)
params._set_child("custom", {"param1": 0.0})
def __init__(self, params):
super().__init__(params)
# Custom initialization
def tendencies_nonlin(self, state_spect=None):
"""Override to add custom tendencies"""
tendencies = super().tendencies_nonlin(state_spect)
# Add custom terms
# tendencies.vx_fft += custom_term_vx
# tendencies.vy_fft += custom_term_vy
return tendencies
```
Use the custom solver:
```python
params = SimulCustom.create_default_params()
# Configure params...
sim = SimulCustom(params)
sim.time_stepping.start()
```
## Online Visualization
Display fields during simulation:
```python
params.output.ONLINE_PLOT_OK = True
params.output.periods_plot.phys_fields = 1.0 # plot every 1.0 time units
params.output.phys_fields.field_to_plot = "vorticity"
sim = Simul(params)
sim.time_stepping.start()
```
Plots appear in real-time during execution.
## Checkpoint and Restart
### Automatic Checkpointing
```python
params.output.periods_save.phys_fields = 1.0 # save every 1.0 time units
```
Fields are saved automatically during simulation.
### Manual Checkpointing
```python
# During simulation
sim.output.phys_fields.save()
```
### Restarting from Checkpoint
```python
params = Simul.create_default_params()
params.init_fields.type = "from_file"
params.init_fields.from_file.path = "simulation_dir/state_phys_t5.000.h5"
params.time_stepping.t_end = 20.0 # extend simulation
sim = Simul(params)
sim.time_stepping.start()
```
## Memory and Performance Optimization
### Reduce Memory Usage
```python
# Disable unnecessary outputs
params.output.periods_save.spectra = 0 # disable spectra saving
params.output.periods_save.spect_energy_budg = 0 # disable energy budget
# Reduce spatial field saves
params.output.periods_save.phys_fields = 10.0 # save less frequently
```
### Optimize FFT Performance
```python
import os
# Select FFT library
os.environ["FLUIDSIM_TYPE_FFT2D"] = "fft2d.with_fftw"
os.environ["FLUIDSIM_TYPE_FFT3D"] = "fft3d.with_fftw"
# Or use MKL if available
# os.environ["FLUIDSIM_TYPE_FFT2D"] = "fft2d.with_mkl"
```
### Time Step Optimization
```python
# Use adaptive time stepping
params.time_stepping.USE_CFL = True
params.time_stepping.CFL = 0.8 # slightly larger CFL for faster runs
# Use efficient time scheme
params.time_stepping.type_time_scheme = "RK4" # 4th order Runge-Kutta
```

View File

@@ -0,0 +1,68 @@
# FluidSim Installation
## Requirements
- Python >= 3.9
- Virtual environment recommended
## Installation Methods
### Basic Installation
Install fluidsim using uv:
```bash
uv pip install fluidsim
```
### With FFT Support (Required for Pseudospectral Solvers)
Most fluidsim solvers use Fourier-based methods and require FFT libraries:
```bash
uv pip install "fluidsim[fft]"
```
This installs fluidfft and pyfftw dependencies.
### With MPI and FFT (For Parallel Simulations)
For high-performance parallel computing:
```bash
uv pip install "fluidsim[fft,mpi]"
```
Note: This triggers local compilation of mpi4py.
## Environment Configuration
### Output Directories
Set environment variables to control where simulation data is stored:
```bash
export FLUIDSIM_PATH=/path/to/simulation/outputs
export FLUIDDYN_PATH_SCRATCH=/path/to/working/directory
```
### FFT Method Selection
Specify FFT implementation (optional):
```bash
export FLUIDSIM_TYPE_FFT2D=fft2d.with_fftw
export FLUIDSIM_TYPE_FFT3D=fft3d.with_fftw
```
## Verification
Test the installation:
```bash
pytest --pyargs fluidsim
```
## No Authentication Required
FluidSim does not require API keys or authentication tokens.

View File

@@ -0,0 +1,283 @@
# Output and Analysis
## Output Types
FluidSim automatically saves several types of output during simulations.
### Physical Fields
**File format**: HDF5 (`.h5`)
**Location**: `simulation_dir/state_phys_t*.h5`
**Contents**: Velocity, vorticity, and other physical space fields at specific times
**Access**:
```python
sim.output.phys_fields.plot()
sim.output.phys_fields.plot("vorticity")
sim.output.phys_fields.plot("vx")
sim.output.phys_fields.plot("div") # check divergence
# Save manually
sim.output.phys_fields.save()
# Get data
vorticity = sim.state.state_phys.get_var("rot")
```
### Spatial Means
**File format**: Text file (`.txt`)
**Location**: `simulation_dir/spatial_means.txt`
**Contents**: Volume-averaged quantities vs time (energy, enstrophy, etc.)
**Access**:
```python
sim.output.spatial_means.plot()
# Load from file
from fluidsim import load_sim_for_plot
sim = load_sim_for_plot("simulation_dir")
sim.output.spatial_means.load()
spatial_means_data = sim.output.spatial_means
```
### Spectra
**File format**: HDF5 (`.h5`)
**Location**: `simulation_dir/spectra_*.h5`
**Contents**: Energy and enstrophy spectra vs wavenumber
**Access**:
```python
sim.output.spectra.plot1d() # 1D spectrum
sim.output.spectra.plot2d() # 2D spectrum
# Load spectra data
spectra = sim.output.spectra.load2d_mean()
```
### Spectral Energy Budget
**File format**: HDF5 (`.h5`)
**Location**: `simulation_dir/spect_energy_budg_*.h5`
**Contents**: Energy transfer between scales
**Access**:
```python
sim.output.spect_energy_budg.plot()
```
## Post-Processing
### Loading Simulations for Analysis
#### Fast Loading (Read-Only)
```python
from fluidsim import load_sim_for_plot
sim = load_sim_for_plot("simulation_dir")
# Access all output types
sim.output.phys_fields.plot()
sim.output.spatial_means.plot()
sim.output.spectra.plot1d()
```
Use this for quick visualization and analysis. Does not initialize full simulation state.
#### Full State Loading
```python
from fluidsim import load_state_phys_file
sim = load_state_phys_file("simulation_dir/state_phys_t10.000.h5")
# Can continue simulation
sim.time_stepping.start()
```
### Visualization Tools
#### Built-in Plotting
FluidSim provides basic plotting through matplotlib:
```python
# Physical fields
sim.output.phys_fields.plot("vorticity")
sim.output.phys_fields.animate("vorticity")
# Time series
sim.output.spatial_means.plot()
# Spectra
sim.output.spectra.plot1d()
```
#### Advanced Visualization
For publication-quality or 3D visualization:
**ParaView**: Open `.h5` files directly
```bash
paraview simulation_dir/state_phys_t*.h5
```
**VisIt**: Similar to ParaView for large datasets
**Custom Python**:
```python
import h5py
import matplotlib.pyplot as plt
# Load field manually
with h5py.File("state_phys_t10.000.h5", "r") as f:
vx = f["state_phys"]["vx"][:]
vy = f["state_phys"]["vy"][:]
# Custom plotting
plt.contourf(vx)
plt.show()
```
## Analysis Examples
### Energy Evolution
```python
from fluidsim import load_sim_for_plot
import matplotlib.pyplot as plt
sim = load_sim_for_plot("simulation_dir")
df = sim.output.spatial_means.load()
plt.figure()
plt.plot(df["t"], df["E"], label="Kinetic Energy")
plt.xlabel("Time")
plt.ylabel("Energy")
plt.legend()
plt.show()
```
### Spectral Analysis
```python
sim = load_sim_for_plot("simulation_dir")
# Plot energy spectrum
sim.output.spectra.plot1d(tmin=5.0, tmax=10.0) # average over time range
# Get spectral data
k, E_k = sim.output.spectra.load1d_mean(tmin=5.0, tmax=10.0)
# Check for power law
import numpy as np
log_k = np.log(k)
log_E = np.log(E_k)
# fit power law in inertial range
```
### Parametric Study Analysis
When running multiple simulations with different parameters:
```python
import os
import pandas as pd
from fluidsim import load_sim_for_plot
# Collect results from multiple simulations
results = []
for sim_dir in os.listdir("simulations"):
if not os.path.isdir(f"simulations/{sim_dir}"):
continue
sim = load_sim_for_plot(f"simulations/{sim_dir}")
# Extract key metrics
df = sim.output.spatial_means.load()
final_energy = df["E"].iloc[-1]
# Get parameters
nu = sim.params.nu_2
results.append({
"nu": nu,
"final_energy": final_energy,
"sim_dir": sim_dir
})
# Analyze results
results_df = pd.DataFrame(results)
results_df.plot(x="nu", y="final_energy", logx=True)
```
### Field Manipulation
```python
sim = load_sim_for_plot("simulation_dir")
# Load specific time
sim.output.phys_fields.set_of_phys_files.update_times()
times = sim.output.phys_fields.set_of_phys_files.times
# Load field at specific time
field_file = sim.output.phys_fields.get_field_to_plot(time=5.0)
vorticity = field_file.get_var("rot")
# Compute derived quantities
import numpy as np
vorticity_rms = np.sqrt(np.mean(vorticity**2))
vorticity_max = np.max(np.abs(vorticity))
```
## Output Directory Structure
```
simulation_dir/
├── params_simul.xml # Simulation parameters
├── stdout.txt # Standard output log
├── state_phys_t*.h5 # Physical fields at different times
├── spatial_means.txt # Time series of spatial averages
├── spectra_*.h5 # Spectral data
├── spect_energy_budg_*.h5 # Energy budget data
└── info_solver.txt # Solver information
```
## Performance Monitoring
```python
# During simulation, check progress
sim.output.print_stdout.complete_timestep()
# After simulation, review performance
sim.output.print_stdout.plot_deltat() # plot time step evolution
sim.output.print_stdout.plot_clock_times() # plot computation time
```
## Data Export
Convert fluidsim output to other formats:
```python
import h5py
import numpy as np
# Export to numpy array
with h5py.File("state_phys_t10.000.h5", "r") as f:
vx = f["state_phys"]["vx"][:]
np.save("vx.npy", vx)
# Export to CSV
df = sim.output.spatial_means.load()
df.to_csv("spatial_means.csv", index=False)
```

View File

@@ -0,0 +1,198 @@
# Parameter Configuration
## Parameters Object
The `Parameters` object is hierarchical and organized into logical groups. Access using dot notation:
```python
params = Simul.create_default_params()
params.group.subgroup.parameter = value
```
## Key Parameter Groups
### Operators (`params.oper`)
Define domain and resolution:
```python
params.oper.nx = 256 # number of grid points in x
params.oper.ny = 256 # number of grid points in y
params.oper.nz = 128 # number of grid points in z (3D only)
params.oper.Lx = 2 * pi # domain length in x
params.oper.Ly = 2 * pi # domain length in y
params.oper.Lz = pi # domain length in z (3D only)
params.oper.coef_dealiasing = 2./3. # dealiasing cutoff (default 2/3)
```
**Resolution guidance**: Use powers of 2 for optimal FFT performance (128, 256, 512, 1024, etc.)
### Physical Parameters
#### Viscosity
```python
params.nu_2 = 1e-3 # Laplacian viscosity (negative Laplacian)
params.nu_4 = 0 # hyperviscosity (optional)
params.nu_8 = 0 # hyper-hyperviscosity (very high wavenumber damping)
```
Higher-order viscosity (`nu_4`, `nu_8`) damps high wavenumbers without affecting large scales.
#### Stratification (Stratified Solvers)
```python
params.N = 1.0 # Brunt-Väisälä frequency (buoyancy frequency)
```
#### Rotation (Shallow Water)
```python
params.f = 1.0 # Coriolis parameter
params.c2 = 10.0 # squared phase velocity (gravity wave speed)
```
### Time Stepping (`params.time_stepping`)
```python
params.time_stepping.t_end = 10.0 # simulation end time
params.time_stepping.it_end = 100 # or maximum iterations
params.time_stepping.deltat0 = 0.01 # initial time step
params.time_stepping.USE_CFL = True # adaptive CFL-based time step
params.time_stepping.CFL = 0.5 # CFL number (if USE_CFL=True)
params.time_stepping.type_time_scheme = "RK4" # or "RK2", "Euler"
```
**Recommended**: Use `USE_CFL=True` with `CFL=0.5` for adaptive time stepping.
### Initial Fields (`params.init_fields`)
```python
params.init_fields.type = "noise" # initialization method
```
**Available types**:
- `"noise"`: Random noise
- `"dipole"`: Vortex dipole
- `"vortex"`: Single vortex
- `"taylor_green"`: Taylor-Green vortex
- `"from_file"`: Load from file
- `"in_script"`: Define in script
#### From File
```python
params.init_fields.type = "from_file"
params.init_fields.from_file.path = "path/to/state_file.h5"
```
#### In Script
```python
params.init_fields.type = "in_script"
# Define initialization after creating sim
sim = Simul(params)
# Access state fields
vx = sim.state.state_phys.get_var("vx")
vy = sim.state.state_phys.get_var("vy")
# Set fields
X, Y = sim.oper.get_XY_loc()
vx[:] = np.sin(X) * np.cos(Y)
vy[:] = -np.cos(X) * np.sin(Y)
# Run simulation
sim.time_stepping.start()
```
### Output Settings (`params.output`)
#### Output Directory
```python
params.output.sub_directory = "my_simulation"
```
Directory created within `$FLUIDSIM_PATH` or current directory.
#### Save Periods
```python
params.output.periods_save.phys_fields = 1.0 # save fields every 1.0 time units
params.output.periods_save.spectra = 0.5 # save spectra
params.output.periods_save.spatial_means = 0.1 # save spatial averages
params.output.periods_save.spect_energy_budg = 0.5 # spectral energy budget
```
Set to `0` to disable a particular output type.
#### Print Control
```python
params.output.periods_print.print_stdout = 0.5 # print status every 0.5 time units
```
#### Online Plotting
```python
params.output.periods_plot.phys_fields = 2.0 # plot every 2.0 time units
# Must also enable the output module
params.output.ONLINE_PLOT_OK = True
params.output.phys_fields.field_to_plot = "vorticity" # or "vx", "vy", etc.
```
### Forcing (`params.forcing`)
Add forcing terms to maintain energy:
```python
params.forcing.enable = True
params.forcing.type = "tcrandom" # time-correlated random forcing
# Forcing parameters
params.forcing.nkmax_forcing = 5 # maximum forced wavenumber
params.forcing.nkmin_forcing = 2 # minimum forced wavenumber
params.forcing.forcing_rate = 1.0 # energy injection rate
```
**Common forcing types**:
- `"tcrandom"`: Time-correlated random forcing
- `"proportional"`: Proportional forcing (maintains specific spectrum)
- `"in_script"`: Custom forcing defined in script
## Parameter Safety
The Parameters object raises `AttributeError` when accessing non-existent parameters:
```python
params.nu_2 = 1e-3 # OK
params.nu2 = 1e-3 # ERROR: AttributeError
```
This prevents typos that would be silently ignored in text-based configuration files.
## Viewing All Parameters
```python
# Print all parameters
params._print_as_xml()
# Get as dictionary
param_dict = params._make_dict()
```
## Saving Parameter Configuration
Parameters are automatically saved with simulation output:
```python
params._save_as_xml("simulation_params.xml")
params._save_as_json("simulation_params.json")
```

View File

@@ -0,0 +1,172 @@
# Simulation Workflow
## Standard Workflow
Follow these steps to run a fluidsim simulation:
### 1. Import Solver
```python
from fluidsim.solvers.ns2d.solver import Simul
# Or use dynamic import
import fluidsim
Simul = fluidsim.import_simul_class_from_key("ns2d")
```
### 2. Create Default Parameters
```python
params = Simul.create_default_params()
```
This returns a hierarchical `Parameters` object containing all simulation settings.
### 3. Configure Parameters
Modify parameters as needed. The Parameters object prevents typos by raising `AttributeError` for non-existent parameters:
```python
# Domain and resolution
params.oper.nx = 256 # grid points in x
params.oper.ny = 256 # grid points in y
params.oper.Lx = 2 * pi # domain size x
params.oper.Ly = 2 * pi # domain size y
# Physical parameters
params.nu_2 = 1e-3 # viscosity (negative Laplacian)
# Time stepping
params.time_stepping.t_end = 10.0 # end time
params.time_stepping.deltat0 = 0.01 # initial time step
params.time_stepping.USE_CFL = True # adaptive time step
# Initial conditions
params.init_fields.type = "noise" # or "dipole", "vortex", etc.
# Output settings
params.output.periods_save.phys_fields = 1.0 # save every 1.0 time units
params.output.periods_save.spectra = 0.5
params.output.periods_save.spatial_means = 0.1
```
### 4. Instantiate Simulation
```python
sim = Simul(params)
```
This initializes:
- Operators (FFT, differential operators)
- State variables (velocity, vorticity, etc.)
- Output handlers
- Time stepping scheme
### 5. Run Simulation
```python
sim.time_stepping.start()
```
The simulation runs until `t_end` or specified number of iterations.
### 6. Analyze Results During/After Simulation
```python
# Plot physical fields
sim.output.phys_fields.plot()
sim.output.phys_fields.plot("vorticity")
sim.output.phys_fields.plot("div")
# Plot spatial means
sim.output.spatial_means.plot()
# Plot spectra
sim.output.spectra.plot1d()
sim.output.spectra.plot2d()
```
## Loading Previous Simulations
### Quick Loading (For Plotting Only)
```python
from fluidsim import load_sim_for_plot
sim = load_sim_for_plot("path/to/simulation")
sim.output.phys_fields.plot()
sim.output.spatial_means.plot()
```
Fast loading without full state initialization. Use for post-processing.
### Full State Loading (For Restarting)
```python
from fluidsim import load_state_phys_file
sim = load_state_phys_file("path/to/state_file.h5")
sim.time_stepping.start() # continue simulation
```
Loads complete state for continuing simulations.
## Restarting Simulations
To restart from a saved state:
```python
params = Simul.create_default_params()
params.init_fields.type = "from_file"
params.init_fields.from_file.path = "path/to/state_file.h5"
# Optionally modify parameters for the continuation
params.time_stepping.t_end = 20.0 # extend simulation
sim = Simul(params)
sim.time_stepping.start()
```
## Running on Clusters
FluidSim integrates with cluster submission systems:
```python
from fluiddyn.clusters.legi import Calcul8 as Cluster
# Configure cluster job
cluster = Cluster()
cluster.submit_script(
"my_simulation.py",
name_run="my_job",
nb_nodes=4,
nb_cores_per_node=24,
walltime="24:00:00"
)
```
Script should contain standard workflow steps (import, configure, run).
## Complete Example
```python
from fluidsim.solvers.ns2d.solver import Simul
from math import pi
# Create and configure parameters
params = Simul.create_default_params()
params.oper.nx = params.oper.ny = 256
params.oper.Lx = params.oper.Ly = 2 * pi
params.nu_2 = 1e-3
params.time_stepping.t_end = 10.0
params.init_fields.type = "dipole"
params.output.periods_save.phys_fields = 1.0
# Run simulation
sim = Simul(params)
sim.time_stepping.start()
# Analyze results
sim.output.phys_fields.plot("vorticity")
sim.output.spatial_means.plot()
```

View File

@@ -0,0 +1,94 @@
# FluidSim Solvers
FluidSim provides multiple solvers for different fluid dynamics equations. All solvers work on periodic domains using pseudospectral methods with FFT.
## Available Solvers
### 2D Incompressible Navier-Stokes
**Solver key**: `ns2d`
**Import**:
```python
from fluidsim.solvers.ns2d.solver import Simul
# or dynamically
Simul = fluidsim.import_simul_class_from_key("ns2d")
```
**Use for**: 2D turbulence studies, vortex dynamics, fundamental fluid flow simulations
**Key features**: Energy and enstrophy cascades, vorticity dynamics
### 3D Incompressible Navier-Stokes
**Solver key**: `ns3d`
**Import**:
```python
from fluidsim.solvers.ns3d.solver import Simul
```
**Use for**: 3D turbulence, realistic fluid flow simulations, high-resolution DNS
**Key features**: Full 3D turbulence dynamics, parallel computing support
### Stratified Flows (2D/3D)
**Solver keys**: `ns2d.strat`, `ns3d.strat`
**Import**:
```python
from fluidsim.solvers.ns2d.strat.solver import Simul # 2D
from fluidsim.solvers.ns3d.strat.solver import Simul # 3D
```
**Use for**: Oceanic and atmospheric flows, density-driven flows
**Key features**: Boussinesq approximation, buoyancy effects, constant Brunt-Väisälä frequency
**Parameters**: Set stratification via `params.N` (Brunt-Väisälä frequency)
### Shallow Water Equations
**Solver key**: `sw1l` (one-layer)
**Import**:
```python
from fluidsim.solvers.sw1l.solver import Simul
```
**Use for**: Geophysical flows, tsunami modeling, rotating flows
**Key features**: Rotating frame support, geostrophic balance
**Parameters**: Set rotation via `params.f` (Coriolis parameter)
### Föppl-von Kármán Equations
**Solver key**: `fvk` (elastic plate equations)
**Import**:
```python
from fluidsim.solvers.fvk.solver import Simul
```
**Use for**: Elastic plate dynamics, fluid-structure interaction studies
## Solver Selection Guide
Choose a solver based on the physical problem:
1. **2D turbulence, quick testing**: Use `ns2d`
2. **3D flows, realistic simulations**: Use `ns3d`
3. **Density-stratified flows**: Use `ns2d.strat` or `ns3d.strat`
4. **Geophysical flows, rotating systems**: Use `sw1l`
5. **Elastic plates**: Use `fvk`
## Modified Versions
Many solvers have modified versions with additional physics:
- Forcing terms
- Different boundary conditions
- Additional scalar fields
Check `fluidsim.solvers` module for complete list.