Skip to content

Commit 5c1df83

Browse files
committed
modify operator and collision doc page
1 parent f77df1a commit 5c1df83

3 files changed

Lines changed: 85 additions & 162 deletions

File tree

docs/api/operator.md

Lines changed: 48 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,72 @@
1-
# Operator
1+
# The Operator Concept
22

3-
Base class for all operators, including collision, streaming, equilibrium, etc.
4-
Responsible for handling compute backends like JAX and NVIDIA Warp.
3+
In XLB, an **Operator** is a fundamental building block that performs a single, well-defined action within a simulation. Think of operators as the "verbs" of the Lattice Boltzmann Method. Any distinct step in the algorithm, such as collision, streaming, or calculating equilibrium, is encapsulated within its own callable operator object.
54

6-
## Overview
7-
8-
The `Operator` class acts as the foundational interface for all lattice Boltzmann operators in XLB. It manages backend selection and provides a unified API to call backend-specific implementations transparently. It also facilitates registering backend implementations and handles precision policies and compute types.
9-
10-
## Usage
11-
12-
```python
13-
from xlb.operator import Operator
14-
from xlb.compute_backend import ComputeBackend
15-
from xlb.precision_policy import PrecisionPolicy
16-
17-
op = Operator(
18-
velocity_set=None, # or specify velocity set
19-
precision_policy=PrecisionPolicy.FP32FP32,
20-
compute_backend=ComputeBackend.JAX,
21-
)
22-
23-
# Call the operator (calls backend-specific implementation)
24-
result = op(some_input_data)
25-
```
26-
27-
## Constructor
5+
---
286

29-
```python
30-
Operator(
31-
velocity_set=None,
32-
precision_policy=None,
33-
compute_backend=None
34-
)
35-
```
7+
## Common Features (The Operator Base Class)
368

37-
- velocity_set: (optional) Velocity set used by the operator; defaults to global config.
38-
- precision_policy: (optional) Precision policy for compute and storage.
39-
- compute_backend: (optional) Backend to run on (e.g., JAX or Warp).
9+
The `Operator` base class provides a unified interface and a set of shared features for all operators in XLB. This ensures that every part of the simulation behaves consistently, regardless of its specific function. When you use any operator in XLB, you can rely on the following features:
4010

41-
Raises `ValueError` if the specified backend is unsupported.
11+
#### 1. Backend Management
12+
Every operator is aware of the compute backend (`JAX` or `Warp`). When an operator is called, it automatically dispatches the execution to the correct, highly optimized backend implementation without any extra effort from the user.
4213

43-
## Methods and Properties
14+
#### 2. Precision Policy Awareness
15+
Operators automatically respect the globally or locally defined `PrecisionPolicy`. They handle the data types for computation (`.compute_dtype`) and storage (`.store_dtype`) transparently, helping to balance performance and numerical accuracy.
4416

45-
`register_backend(backend_name)`
46-
Decorator to register backend implementations for subclasses.
17+
#### 3. Standardized Calling Convention
18+
All operators are **callable** (using `()`). This provides a clean, functional API that makes it simple to compose operators and build a custom simulation loop.
4719

48-
`__call__(*args, callback=None, **kwargs)`
49-
Calls the appropriate backend method, matching the subclass and backend, and passes args/kwargs.
50-
- callback (optional): Callable to be called with the result.
20+
### Conceptual Usage
5121

52-
`supported_compute_backend`
53-
Returns a list of supported backend keys registered for this operator.
22+
While you rarely instantiate the base `Operator` directly, all its subclasses follow the same pattern of creation and use. You first instantiate a specific operator (e.g., for BGK collision), configuring it with a velocity set and policies. Then, you call that instance with the required data to perform its action.
5423

55-
`backend`
56-
Returns the actual backend module (jax.numpy or warp), depending on the current backend.
24+
```python
25+
from xlb.operator.collision import BGKCollision # A concrete operator subclass
26+
from xlb.precision_policy import PrecisionPolicy
27+
from xlb.compute_backend import ComputeBackend
5728

58-
`compute_dtype`
59-
Returns the compute data type (e.g., float32, float64) according to the precision policy and backend.
29+
# Instantiate a specific operator (e.g., for BGK collision)
30+
collision_op = BGKCollision(
31+
velocity_set=my_velocity_set,
32+
precision_policy=PrecisionPolicy.FP32FP32,
33+
compute_backend=ComputeBackend.JAX
34+
)
6035

61-
`store_dtype`
62-
Returns the storage data type according to the precision policy and backend.
36+
# Call the operator with the required data
37+
# It automatically runs the JAX implementation in FP32.
38+
f_post_collision = collision_op(f_pre_collision, omega=1.8)
39+
```
6340

6441
---
6542

66-
## Precision Caster
43+
## Utility Operator: `PrecisionCaster`
6744

68-
The **PrecisionCaster** is a utility operator for converting lattice Boltzmann data between different numeric precisions.
45+
The `PrecisionCaster` is a prime example of a simple yet powerful utility operator provided by XLB. Its sole purpose is to convert the numerical precision of simulation data fields.
6946

7047
### Overview
7148

72-
Precision plays an important role in balancing **accuracy** and **performance** during simulations.
73-
For example, some steps may require high precision (`float64`) for stability, while others can run efficiently in lower precision (`float32`).
49+
Precision plays an important role in balancing **accuracy** and **performance**. Some simulation steps may require high precision (`float64`) for stability, while many others can run much faster in lower precision (`float32`), especially on GPUs. The `PrecisionCaster` handles this conversion seamlessly.
7450

75-
The `PrecisionCaster` operator handles this conversion seamlessly for both supported backends.
51+
### Use Cases
7652

77-
### Features
53+
- **Performance Optimization**: Run the bulk of a simulation in `FP32` for speed, but cast data to `FP64` before critical calculations.
54+
- **Mixed-Precision Workflows**: Adapt precision dynamically based on runtime stability needs.
55+
- **Memory Management**: Store data in a lower precision to reduce memory footprint, casting to a higher precision only when needed for computation.
7856

79-
- Converts distribution functions between precisions (e.g., FP32 → FP64).
80-
- Available for **JAX** and **Warp** backends.
81-
- Works transparently with any chosen velocity set (e.g., D2Q9, D3Q19, D3Q27).
82-
- Can be used before or after key operators to ensure data is in the desired format.
57+
### Usage
58+
To use the `PrecisionCaster`, you create an instance configured with the *target* precision policy you want to convert to. You then apply this operator to a data field, and it will return a new field with the converted precision.
8359

84-
### Use Cases
60+
```python
61+
from xlb.operator import PrecisionCaster
8562

86-
- **Performance optimization**: Run most of the simulation in FP32 for speed, while critical calculations use FP64.
87-
- **Mixed-precision workflows**: Adapt precision dynamically depending on stability needs.
88-
- **GPU acceleration**: Exploit lower-precision compute on GPUs while preserving accuracy where needed.
63+
# Assume 'f_low_precision' is a field with FP32 data
64+
# Create a caster to convert data to a higher precision (FP64)
65+
caster_to_fp64 = PrecisionCaster(
66+
velocity_set=my_velocity_set,
67+
precision_policy=PrecisionPolicy.FP64FP64 # Target policy
68+
)
69+
70+
# Apply the operator to cast the field
71+
f_high_precision = caster_to_fp64(f_low_precision)
72+
```
Lines changed: 35 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 🔄 StreamingOperator & CollisionOperator
1+
# StreamingOperator & CollisionOperator
22

33
In Lattice Boltzmann Method (LBM) simulations, the two core steps are **Streaming** and **Collision**. These operations define how distribution functions move across the grid and how they interact locally.
44

@@ -9,109 +9,67 @@ The following operators abstract these steps:
99

1010
---
1111

12-
## 🚀 Stream (Base Class)
12+
## Stream (Base Class)
1313

1414
The `Stream` operator performs the **streaming step** by pulling values from neighboring grid points, depending on the velocity set.
1515

16-
### 📌 Purpose
16+
### Purpose
1717

1818
- Implements the **pull scheme** of LBM streaming.
1919
- Ensures support for both 2D and 3D simulations.
20-
- Compatible with **JAX** and **Warp** backends.
2120

22-
### 🧩 Key Properties
2321

24-
| Property | Description |
25-
|------------------------|-----------------------------------------------------------|
26-
| `implementation_step` | `STREAMING` |
27-
| `backend_support` | JAX and Warp |
28-
| `supports_auxiliary_data` | ❌ No |
29-
30-
### ⚙️ JAX Implementation
31-
32-
```python
33-
@jit
34-
def jax_implementation(self, f):
35-
def _streaming_jax_i(f, c):
36-
return jnp.roll(f, (c[0], c[1]), axis=(0, 1)) # for 2D
37-
38-
return vmap(_streaming_jax_i, in_axes=(0, 0), out_axes=0)(f, jnp.array(self.velocity_set.c).T)
39-
```
40-
41-
This uses jax.numpy.roll to shift distributions in each velocity direction.
42-
43-
## ⚙️ Warp Implementation
44-
45-
```python
46-
@wp.kernel
47-
def kernel(f_0, f_1):
48-
index = wp.vec3i(i, j, k)
49-
_f = functional(f_0, index)
50-
f_1[...] = _f
51-
```
52-
Warp handles periodic boundary corrections and shift indexing manually within the kernel for 3D arrays.
53-
54-
## 💥 Collision (Base Class)
22+
## Collision (Base Class)
5523

5624
The `Collision` operator defines how particles interact locally after streaming, typically by relaxing towards equilibrium.
5725

58-
### 📌 Purpose
26+
### Purpose
5927

6028
- Base class for implementing collision models.
6129
- Uses distribution function `f`, equilibrium `feq`, and local properties (`rho`, `u`, etc.).
6230
- Meant to be subclassed (e.g., for `BGK`).
6331

64-
## 🧩 Key Properties
32+
## BGK (Bhatnagar–Gross–Krook)
6533

66-
| Property | Description |
67-
|------------------------|----------------------------------|
68-
| `implementation_step` | `COLLISION` |
69-
| `backend_support` | JAX and Warp |
70-
| `supports_auxiliary_data` | ✅ Yes (e.g., `omega`) |
34+
- **Concept**: BGK is a common collision model where the post-collision distribution is calculated by relaxing toward equilibrium at a single relaxation rate.
35+
- **When to use**:
36+
- Standard fluid simulations.
37+
- Good balance of performance and accuracy.
7138

72-
## 🧪 BGK: A Subclass of Collision
39+
---
7340

74-
**BGK** (Bhatnagar–Gross–Krook) is a common collision model where the post-collision distribution is calculated by relaxing toward equilibrium.
41+
### ForcedCollision
7542

76-
### ⚙️ JAX Implementation
43+
- **Concept**: Extends BGK by including external forces (such as gravity, pressure gradients, or body accelerations).
44+
- **When to use**:
45+
- Flows influenced by external fields.
46+
- Problems where force-driven effects are important.
7747

78-
```python
79-
@jit
80-
def jax_implementation(self, f, feq, rho, u, omega):
81-
fneq = f - feq
82-
return f - self.compute_dtype(omega) * fneq
83-
```
48+
---
8449

50+
### KBC (Karlin–Bösch–Chikatamarla)
8551

86-
### ⚙️ Warp Implementation
52+
- **Concept**: A more advanced model that improves numerical stability and accuracy, especially for high Reynolds number flows.
53+
- **When to use**:
54+
- Simulations at high Reynolds numbers.
55+
- Turbulent or under-resolved flows where BGK may become unstable.
8756

88-
```python
89-
@wp.func
90-
def functional(f, feq, rho, u, omega):
91-
fneq = f - feq
92-
return f - dtype(omega) * fneq
93-
```
94-
The Warp kernel loads and stores distribution values per node and performs the same BGK operation element-wise.
57+
---
9558

96-
### 🛠 Backend Support Summary
59+
## Summary of Support
9760

98-
| Operator | JAX Support | Warp Support | Streaming | Collision | Supports Aux Data |
99-
|------------|-------------|--------------|-----------|-----------|------------------------|
100-
| Stream | ✅ Yes | ✅ Yes | ✅ Yes | ❌ No | ❌ No |
101-
| Collision | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
102-
| BGK | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes (omega) |
103-
| ForcedCollision | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes (force vector) |
104-
| KBC | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes | ✅ Yes |
61+
| Operator | JAX Support | Warp Support | Typical Use Case |
62+
|-----------------|-------------|--------------|------------------------------------------|
63+
| Stream | Yes | Yes | Particle propagation |
64+
| BGK | Yes | Yes | Standard fluid simulations |
65+
| ForcedCollision | Yes | Yes | Flows with external forces |
66+
| KBC | Yes | Yes | High Reynolds number / turbulent flows |
10567

10668
---
10769

108-
### 🗂 Registry
109-
110-
All operator subclasses are registered via the Operator base class using decorators:
111-
112-
```python
113-
@Operator.register_backend(ComputeBackend.JAX)
114-
def jax_implementation(...)
115-
```
70+
## Choosing the Right Operator
11671

117-
This allows dynamic backend dispatch at runtime.
72+
- Start with **BGK** for most general-purpose LBM simulations.
73+
- Use **ForcedCollision** if external forces significantly affect your system.
74+
- Switch to **KBC** if you need more stability at high Reynolds numbers or for turbulent flows.
75+
- The **Stream** operator is always required to handle propagation.

mkdocs.yml

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -145,25 +145,6 @@ extra_javascript:
145145
- https://polyfill.io/v3/polyfill.min.js?features=es6
146146
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
147147

148-
# nav:
149-
# - XLB's home: index.md
150-
# - Installation: installation.md
151-
# - API & Modules:
152-
# - Common Steps: common_steps.md
153-
# - Constants: constants.md
154-
# - Velocity set: velocity_set.md
155-
# - Grid: grid.md
156-
# - Operator: operator.md
157-
# - Distribution: distribution.md
158-
# - Boundary Condition: BC.md
159-
# - Macroscopic: macroscopic.md
160-
# - Stepper: stepper.md
161-
# - Streaming and Collision: streaming_and_collision.md
162-
# - Force: force.md
163-
# - Equilibrium: equilibrium.md
164-
# - Examples: examples.md
165-
# - Contributing: contributing.md
166-
167148

168149
nav:
169150
- 'Home': 'index.md'
@@ -183,8 +164,8 @@ nav:
183164
- 'Velocity Set': 'api/velocity_set.md'
184165
- 'Grid': 'api/grid.md'
185166
- 'LBM Kernel':
186-
- 'Equilibrium': 'api/equilibrium.md'
187167
- 'Operator': 'api/operator.md'
168+
- 'Equilibrium': 'api/equilibrium.md'
188169
- 'Streaming and Collision': 'api/streaming_and_collision.md'
189170
- 'Physics & Numerics':
190171
- 'Boundary Condition': 'api/BC.md'
@@ -195,4 +176,4 @@ nav:
195176
- 'Distributed Computing':
196177
- 'Distribution': 'api/distribution.md'
197178
- 'Examples': examples.md
198-
- 'Contributing': 'contributing.md'
179+
- 'Contributing': 'contributing.md'

0 commit comments

Comments
 (0)