Create dynamics interface to combine motion and dist

This commit is contained in:
Dominik Demuth
2026-03-08 13:04:40 +01:00
parent 6b42051e45
commit c4485aac6f
16 changed files with 232 additions and 116 deletions

137
README.md
View File

@@ -1,32 +1,37 @@
# Download
# NMR Random Walk Simulation
1. Clone repository with `git clone https://gitea.pkm.physik.tu-darmstadt.de/NMRRWSims/cpp.git`
2. After download, change permissions of build.sh in terminal with `chmod a+x build.sh`
Simulate solid-state NMR spectra and stimulated echo (STE) decays using random walk models.
# Build
# Running
## Command line
To run a random walk simulation Execute `rwsim` in the command line with
Requires CMake 3.18+, a C++17 compiler, and OpenMP.
```bash
./rwsim /path/to/config.txt MotionModel DistributionModel --ste --spectrum -ARG1 1 -ARG2 2
cmake -B build
cmake --build build
```
It needs three positional arguments: the path to your basic configuration file (see below) and the names of the motional model and of the distribution of correlation times.
Set the optional arguments `--ste` and/or `--spectrum` to create Stimulated Echos or normal echo spectra, respectively.
You can overwrite any parameter given in the configuration file by adding it as optional argument with a numerical value, e.g. `-TAU 1e-3` for a correlation time of 1 ms.
The executable is `build/src/rwsim`.
# Running
## Configuration file `config.txt`
```bash
./build/src/rwsim /path/to/config.txt MotionModel DistributionModel --ste --spectrum -ARG1 1 -ARG2 2
```
Change the values of delta, eta, mixing times, echo times,... in this file. If a paramter is defined multiple times, only the last one is used.
Three positional arguments are required: the path to a configuration file, the motion model name, and the distribution model name.
Set `--ste` and/or `--spectrum` to run stimulated echo or spectrum simulations.
Any parameter from the configuration file can be overridden on the command line, e.g. `-tau 1e-3`.
### General parameter
Use `-seed 42` for reproducible results. Without a seed, a random one is used.
This list of general parameter are necessary for all simulations:
**Output files are overwritten if a simulation with the same parameters is run again.**
## Configuration file
Change delta, eta, mixing times, echo times, etc. in this file. If a parameter appears multiple times, only the last value is used.
### General parameters
| Parameter | Description |
|------------|----------------------------|
@@ -36,48 +41,88 @@ This list of general parameter are necessary for all simulations:
### Distribution of correlation times
Two distributions are available: A delta distribution `Delta`, i.e. the same correlation time for every walker, and a log-normal distribution `LogNormal`.
+ Parameters for delta distribution `Delta`
| Parameter | Description |
|-----------|-----------------------|
| tau | Jump time in s |
+ Parameters for log-normal distribution `LogNormal`
| Parameter | Description |
|-----------|--------------------------------------------|
| tau | Maximum jump time of the distribution in s |
| sigma | Standard deviation of the distribution |
| Model | CLI name | Parameters |
|-------|----------|------------|
| Delta distribution (same tau for all walkers) | `Delta` | `tau` (jump time in s) |
| Log-normal distribution | `LogNormal` | `tau` (peak time in s), `sigma` (width) |
### Motion models
Four different jump models are implemented: Isotropic random jump `RandomJump`, isotropic jump with a certain angle, isotropic jump with a bimodal distribution of angles, and a tetrahedral jump `TetrahedralJump`.
| Model | CLI name | Parameters |
|-------|----------|------------|
| Isotropic random jump | `RandomJump` | — |
| Isotropic jump by fixed angle | `IsotropicAngle` | `angle` (degrees) |
| Bimodal angle distribution | `BimodalAngle` | `angle1`, `angle2` (degrees), `probability1` (01) |
| Tetrahedral 4-site jump | `FourSiteTetrahedral` | — |
| Octahedral 6-site jump (C3) | `SixSiteOctahedralC3` | — |
| N-site jump on cone | `NSiteConeJump` | `num_sites`, `chi` (cone angle, degrees) |
| Random jump on cone | `RandomJumpOnCone` | `angle` (cone angle) |
| Wobbling in cone | `ConeWobble` | `angle` (cone angle) |
+ Isotropic random jump `RandomJump` does not have additional parameters.
+ Tetrahedral jump `TetrahedralJump` does not have additional parameters.
+ Parameters for isotropic jump by an angle `IsotropicAngle`
### Spectrum parameters
| Parameter | Description |
|-----------|----------------------|
| angle | Jump angle in degree |
| Parameter | Description |
|--------------|---------------------------------|
| dwell_time | Acquisition dwell time in s |
| num_acq | Number of acquisition points |
| techo_start | First echo time in s |
| techo_stop | Last echo time in s |
| techo_steps | Number of echo times |
+ Parameters for isotropic jump with bimodal angle distribution `BimodalAngle`
### STE parameters
| Parameter | Description |
|--------------|--------------------------------------|
| angle1 | First jump angle in degree |
| angle2 | Second jump angle in degree |
| probability1 | Probality that jump has angle1 (0-1) |
| Parameter | Description |
|-------------|---------------------------------|
| tevo_start | First evolution time in s |
| tevo_stop | Last evolution time in s |
| tevo_steps | Number of evolution times |
| tmix_start | First mixing time in s |
| tmix_stop | Last mixing time in s |
| tmix_steps | Number of mixing times (log-spaced) |
| tpulse4 | Delay of 4th pulse in s |
# Architecture
The simulation is built around three abstractions:
## Dynamics
`Dynamics` (`src/dynamics/base.h`) produces trajectory steps — pairs of `{dt, omega}` representing a waiting time and the NMR frequency after a jump. This is the core interface for defining physical models.
**`DecoupledDynamics`** wraps a separate motion model and time distribution, calling them independently. This covers all existing models.
# Running
To implement a **coupled model** where motion and time are interdependent (e.g. jump angle affects waiting time, or position-dependent dynamics), implement the `Dynamics` interface directly:
**Because filenames are always the same, previous simulations and results are overwritten!**
```cpp
class MyModel : public Dynamics {
void initialize(std::mt19937_64& rng) override { /* set initial state */ }
Step next(std::mt19937_64& rng) override {
// draw angle, compute rate from angle, draw wait time from rate
return {dt, omega};
}
// ... clone(), setParameters(), etc.
};
```
1. Execute `build.sh` (in terminal with `./build.sh`). It compiles the source code and executes test.py
## Experiment
`Experiment` (`src/experiments/base.h`) defines how trajectory data is turned into observables:
- `setup(params)` — configure time axes, allocate accumulators
- `accumulate(trajectory)` — process one walker's trajectory
- `save(directory)` — write results to files
- `clone()` / `merge()` — for thread-parallel accumulation
Existing experiments: `SpectrumExperiment`, `STEExperiment`.
## Simulation runner
`run_simulation()` (`src/sims.h`) connects a `Dynamics` and an `Experiment`:
1. Sets parameters on both
2. Generates trajectories in parallel (OpenMP, one clone per thread)
3. Each thread accumulates into its own experiment clone
4. Merges thread-local results
5. Saves output
The walker loop is parallelized with OpenMP using static scheduling for deterministic reproducibility with a given seed and thread count.