重构:分级设计,EsoPull
This commit is contained in:
1 parent
b339f302d3
commit
654e3290a4
40 files changed
+2767
-619
No files matched your search
@@ -7,13 +7,14 @@ CelerisLab is a high-performance computational fluid dynamics (CFD) solver based
|
||||
## Features
|
||||
|
||||
- **GPU Acceleration**: CUDA-based kernels for high-performance simulations
|
||||
- **D2Q9 Lattice**: 2D nine-velocity lattice implementation
|
||||
- **MRT Collision Model**: Multiple-Relaxation-Time collision operator for improved stability
|
||||
- **D2Q9 / D3Q19 Lattice**: 2D and 3D lattice implementations
|
||||
- **Multiple Collision Models**: SRT, TRT, and MRT operators; Smagorinsky LES subgrid model
|
||||
- **Dual Streaming Paths**: Standard double-buffer pull and memory-efficient esoteric-pull (EsoPull)
|
||||
- **Immersed Boundary Method (IBM)**: Support for complex geometries (cylinders, arbitrary shapes)
|
||||
- **Flexible Boundary Conditions**: Periodic, velocity inlet, pressure outlet
|
||||
- **Real-time Sensors**: Monitor flow properties at specific locations during simulation
|
||||
- **Vortex Initialization**: Built-in support for Lamb, Oseen, and Taylor vortices
|
||||
- **Dynamic Compilation**: Runtime CUDA kernel compilation with configurable parameters
|
||||
- **Flexible Boundary Conditions**: NEQ-extrapolation pressure outlet, parabolic/uniform velocity inlet, half-way bounce-back walls
|
||||
- **Layered Configuration**: Compile-time parameters organized into Global / Method / Case / Debug tiers
|
||||
- **High-Re Validated**: Tested up to Re=5000 (2D cylinder); MRT+LES and SRT+LES stable; TRT+LES stable with tuned Lambda and WMAX
|
||||
- **Python API**: High-level `Simulation` class for scripting and RL integration
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -40,162 +41,149 @@ pip install -e . # Installs from src/ directory
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Basic Flow Simulation
|
||||
```python
|
||||
from CelerisLab import Simulation
|
||||
|
||||
sim = Simulation("configs/config_lbm.json")
|
||||
sim.add_cylinder(center=(50, 50), radius=10)
|
||||
sim.initialize()
|
||||
|
||||
for step in range(10000):
|
||||
sim.run(1)
|
||||
|
||||
macro = sim.get_macroscopic() # {"rho": ..., "ux": ..., "uy": ...}
|
||||
sim.close()
|
||||
```
|
||||
|
||||
Or as a context manager:
|
||||
|
||||
```python
|
||||
from CelerisLab import FlowField, utils
|
||||
|
||||
# Load configurations
|
||||
config_cuda = utils.load_cuda_config() # Uses default or CELERISLAB_CONFIG_DIR
|
||||
config_field = utils.load_flow_field_config()
|
||||
|
||||
# Initialize flow field
|
||||
flow = FlowField(
|
||||
config_cuda=config_cuda,
|
||||
config_field=config_field,
|
||||
device_id=0
|
||||
)
|
||||
|
||||
# Add a cylinder obstacle
|
||||
flow.add_cylinder(
|
||||
center=(50, 50, 0),
|
||||
radius=10,
|
||||
velocity=(0, 0, 0),
|
||||
use_IBM=True
|
||||
)
|
||||
|
||||
# Add sensors to monitor flow
|
||||
flow.add_sensor(position=(70, 50, 0))
|
||||
|
||||
# Run simulation
|
||||
for step in range(10000):
|
||||
flow.run(1)
|
||||
|
||||
# Read sensor data every 100 steps
|
||||
if step % 100 == 0:
|
||||
sensor_data = flow.read_sensor()
|
||||
print(f"Step {step}: Velocity = {sensor_data[0]}")
|
||||
with Simulation("configs/config_lbm.json") as sim:
|
||||
sim.add_cylinder(center=(96, 64), radius=12)
|
||||
sim.initialize()
|
||||
sim.run(5000)
|
||||
data = sim.get_macroscopic()
|
||||
```
|
||||
|
||||
### Configuration
|
||||
## Configuration
|
||||
|
||||
CelerisLab searches for configuration files in the following order:
|
||||
### `configs/config_lbm.json`
|
||||
|
||||
1. **Explicit path**: Passed to `load_*_config(config_path)`
|
||||
2. **Environment variable**: `CELERISLAB_CONFIG_DIR` environment variable
|
||||
3. **Current directory**: `./configs/` in current working directory
|
||||
4. **Package default**: Bundled `CelerisLab/configs/` directory
|
||||
|
||||
#### Configuration Files
|
||||
|
||||
**config_cuda.json**: CUDA execution parameters
|
||||
```json
|
||||
{
|
||||
"multi_gpu": false,
|
||||
"gpu_connection": "NVLINK",
|
||||
"required_cuda_capability": "6.0",
|
||||
"threads_per_block": 256,
|
||||
"X_1U": 16,
|
||||
"Y_1U": 16,
|
||||
"Z_1U": 1
|
||||
"dim": 2,
|
||||
"nq": 9,
|
||||
"nx": 384,
|
||||
"ny": 192,
|
||||
"nz": 1,
|
||||
"viscosity": 0.0005,
|
||||
"velocity": 0.04,
|
||||
"rho": 1.0,
|
||||
"collision": "MRT",
|
||||
"streaming": "double_buffer",
|
||||
"les_enabled": true,
|
||||
"les_cs": 0.16,
|
||||
"trt_magic_param": 0.001,
|
||||
"omega_max": 1.90,
|
||||
"inlet_profile": "parabolic",
|
||||
"outlet_mode": "neq_extrap",
|
||||
"compute_capability": "auto",
|
||||
"threads_per_block": 256
|
||||
}
|
||||
```
|
||||
|
||||
**config_flowfield.json**: Flow physics parameters
|
||||
```json
|
||||
{
|
||||
"data_type": "FP32",
|
||||
"dimensionality": 2,
|
||||
"lattice": 9,
|
||||
"field_dim_in_U": [100, 100, 1],
|
||||
"viscosity": 0.01,
|
||||
"velocity": 0.1,
|
||||
"boundary_conditions": {
|
||||
"x": ["periodic", "periodic"],
|
||||
"y": ["periodic", "periodic"],
|
||||
"z": ["periodic", "periodic"]
|
||||
}
|
||||
}
|
||||
```
|
||||
### Parameter tiers
|
||||
|
||||
| Tier | Headers | Examples |
|
||||
|---|---|---|
|
||||
| Global/Grid | `config_grid.h` | DIM, NQ, NX, NY, NZ |
|
||||
| Global/Physics | `config_physics.h` | VIS, RHO, U0, flag constants |
|
||||
| Method | `config_method.h` | COLLISION_MODEL, USE_LES, TRT_MAGIC_PARAM, OMEGA_COLLISION_MAX |
|
||||
| Case | `config_objects.h` | N_OBJS |
|
||||
|
||||
Headers are auto-generated by the compiler from `LBMConfig`; do not edit manually.
|
||||
|
||||
## API Reference
|
||||
|
||||
### FlowField Class
|
||||
|
||||
Main interface for running LBM simulations.
|
||||
|
||||
#### Constructor
|
||||
```python
|
||||
FlowField(config_cuda, config_field, device_id=0)
|
||||
```
|
||||
|
||||
#### Methods
|
||||
|
||||
- `add_cylinder(center, radius, velocity, use_IBM=False)`: Add cylindrical obstacle
|
||||
- `add_sensor(position)`: Add flow monitoring sensor
|
||||
- `add_vortex(center, circulation, core_radius, vortex_type='Lamb')`: Initialize vortex
|
||||
- `run(n_steps)`: Execute simulation steps
|
||||
- `read_sensor()`: Read current sensor values
|
||||
- `get_ddf()`: Get distribution function data
|
||||
- `apply_ddf(ddf)`: Set distribution function data
|
||||
|
||||
### Utility Functions
|
||||
|
||||
- `load_cuda_config(config_path=None)`: Load CUDA configuration
|
||||
- `load_flow_field_config(config_path=None)`: Load flow field configuration
|
||||
- `check_cuda_device_availability(device_id=0)`: Verify CUDA device
|
||||
- `get_device_info(device_id=0)`: Query GPU properties
|
||||
- `estimate_memory_consumption(config_field, num_objects, num_sensors)`: Calculate memory usage
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Geometry with IBM
|
||||
### `Simulation`
|
||||
|
||||
```python
|
||||
# IBM enables smooth treatment of curved boundaries
|
||||
flow.add_cylinder(
|
||||
center=(grid_x//2, grid_y//2, 0),
|
||||
radius=20,
|
||||
velocity=(0.0, 0.0, 0.0),
|
||||
use_IBM=True # Enables immersed boundary method
|
||||
)
|
||||
sim = Simulation(lbm_config_path=None, body_config_path=None, device_id=0)
|
||||
sim.add_cylinder(center, radius) -> int
|
||||
sim.add_sensor(center, radius) -> int
|
||||
sim.initialize()
|
||||
sim.run(steps)
|
||||
sim.step(n=1)
|
||||
sim.get_macroscopic() -> {"rho": ndarray, "ux": ndarray, "uy": ndarray}
|
||||
sim.get_ddf() -> ndarray
|
||||
sim.get_flags() -> ndarray
|
||||
sim.update_runtime_params(omega=..., u_inlet=...)
|
||||
sim.snapshot() / sim.restore()
|
||||
sim.close()
|
||||
```
|
||||
|
||||
### Multiple Sensors
|
||||
### Vortex initialization
|
||||
|
||||
```python
|
||||
# Add sensors in a line downstream of obstacle
|
||||
for i in range(5):
|
||||
flow.add_sensor(position=(100 + i*10, 50, 0))
|
||||
from CelerisLab.lbm.initializers import add_vortex
|
||||
|
||||
# Read all sensors at once
|
||||
sensor_data = flow.read_sensor() # Returns array of shape (n_sensors, 3)
|
||||
# Superimpose a Lamb–Oseen vortex on an existing LBMField
|
||||
add_vortex(sim.field, center=(50, 50), radius=10.0, strength=1.0, vortex_type="lamb")
|
||||
```
|
||||
|
||||
### Vortex Initialization
|
||||
## Collision & LES Recommendations
|
||||
|
||||
```python
|
||||
# Initialize Lamb-Oseen vortex
|
||||
flow.add_vortex(
|
||||
center=(50, 50, 0),
|
||||
circulation=1.0,
|
||||
core_radius=10.0,
|
||||
vortex_type='Lamb'
|
||||
)
|
||||
| Use case | Recommended config |
|
||||
|---|---|
|
||||
| Low Re (≤ 500) | SRT or TRT, LES off |
|
||||
| Medium Re (500–2000) | MRT or SRT+LES |
|
||||
| High Re (2000–5000) | MRT+LES (most robust); SRT+LES; TRT+LES with `omega_max=1.90`, `trt_magic_param=0.001` |
|
||||
|
||||
## Project Layout
|
||||
|
||||
```
|
||||
src/CelerisLab/
|
||||
simulation.py High-level API
|
||||
config.py LBMConfig / BodyConfig dataclasses
|
||||
cuda/
|
||||
compiler_v2.py Config header generation + nvcc + PTX load
|
||||
context.py CUDA context lifecycle
|
||||
lbm/
|
||||
field.py GPU memory management
|
||||
stepper.py Time-step driver
|
||||
initializers.py Vortex superposition
|
||||
kernels/
|
||||
kernel_v2.cu Kernel entry (thin wrapper)
|
||||
config/ Auto-generated config headers
|
||||
core/ Descriptors, layout, flags, params
|
||||
operators/ Collision, LES, forcing
|
||||
boundary/ Inlet, outlet, wall, curved, IBM
|
||||
streaming/ Double-buffer & esopull
|
||||
step/ Step orchestration
|
||||
body/
|
||||
objects.py SimObject / Cylinder / Sensor
|
||||
manager.py ObjectManager + GPU sync
|
||||
common/
|
||||
preprocess.py Geometry utilities
|
||||
tests/
|
||||
test_stability_matrix.py 13-case stability matrix (Re × collision × LES × streaming)
|
||||
test_high_re_validation.py High-Re directed validation (Re5000, 2D/3D, parameter sweep)
|
||||
output/
|
||||
CelerisLab_stage1_architecture.md Architecture specification (v3)
|
||||
refactor_brief_stage1.md Refactoring brief
|
||||
high_re_audit_round1.md 8-round audit log
|
||||
legacy/ Superseded code (FlowField, compiler v1, macros.h)
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
## Performance
|
||||
|
||||
- `CELERISLAB_CONFIG_DIR`: Directory containing configuration JSON files
|
||||
- `OMP_NUM_THREADS`: OpenMP thread count (recommend setting to 1 for GPU workflows)
|
||||
- `MKL_NUM_THREADS`: Intel MKL thread count (recommend setting to 1)
|
||||
Tested on Tesla V100-SXM2-16GB (CUDA 12.4):
|
||||
|
||||
## Performance Tips
|
||||
|
||||
1. **Grid Size**: Choose dimensions that are multiples of `unit_dimensions` in config_cuda.json
|
||||
2. **Thread Block Size**: 256 threads/block works well for most GPUs
|
||||
3. **Memory**: Estimate memory with `utils.estimate_memory_consumption()` before large runs
|
||||
4. **Single-threaded Python**: Set `OMP_NUM_THREADS=1` to avoid CPU interference with GPU
|
||||
| Config | Grid | MLUPS |
|
||||
|---|---|---|
|
||||
| Re100 MRT noLES | 384×192 | ~4200 |
|
||||
| Re100 EsoPull SRT | 384×192 | ~3900 |
|
||||
| Re3000 MRT+LES | 384×192 | ~4360 |
|
||||
|
||||
## Citation
|
||||
|
||||
@@ -212,13 +200,4 @@ If you use CelerisLab in your research, please cite:
|
||||
|
||||
## License
|
||||
|
||||
MIT License - see LICENSE file for details
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please feel free to submit issues and pull requests.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- Built with PyCUDA by Andreas Klöckner
|
||||
- Inspired by the palabos C++ LBM library
|
||||
MIT License — see LICENSE file for details.
|
||||
Reference in new issue
Block a user