Create dynamics interface to combine motion and dist
This commit is contained in:
133
README.md
133
README.md
@@ -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`
|
Simulate solid-state NMR spectra and stimulated echo (STE) decays using random walk models.
|
||||||
2. After download, change permissions of build.sh in terminal with `chmod a+x build.sh`
|
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
|
|
||||||
# Running
|
Requires CMake 3.18+, a C++17 compiler, and OpenMP.
|
||||||
|
|
||||||
## Command line
|
|
||||||
|
|
||||||
To run a random walk simulation Execute `rwsim` in the command line with
|
|
||||||
|
|
||||||
```bash
|
```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.
|
The executable is `build/src/rwsim`.
|
||||||
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.
|
|
||||||
|
|
||||||
|
# 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 |
|
| Parameter | Description |
|
||||||
|------------|----------------------------|
|
|------------|----------------------------|
|
||||||
@@ -36,48 +41,88 @@ This list of general parameter are necessary for all simulations:
|
|||||||
|
|
||||||
### Distribution of correlation times
|
### 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`.
|
| Model | CLI name | Parameters |
|
||||||
|
|-------|----------|------------|
|
||||||
+ Parameters for delta distribution `Delta`
|
| Delta distribution (same tau for all walkers) | `Delta` | `tau` (jump time in s) |
|
||||||
|
| Log-normal distribution | `LogNormal` | `tau` (peak time in s), `sigma` (width) |
|
||||||
| 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 |
|
|
||||||
|
|
||||||
### Motion models
|
### 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` (0–1) |
|
||||||
|
| 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.
|
### Spectrum parameters
|
||||||
+ Tetrahedral jump `TetrahedralJump` does not have additional parameters.
|
|
||||||
+ Parameters for isotropic jump by an angle `IsotropicAngle`
|
|
||||||
|
|
||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
|-----------|----------------------|
|
|--------------|---------------------------------|
|
||||||
| angle | Jump angle in degree |
|
| 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 |
|
| Parameter | Description |
|
||||||
|--------------|--------------------------------------|
|
|-------------|---------------------------------|
|
||||||
| angle1 | First jump angle in degree |
|
| tevo_start | First evolution time in s |
|
||||||
| angle2 | Second jump angle in degree |
|
| tevo_stop | Last evolution time in s |
|
||||||
| probability1 | Probality that jump has angle1 (0-1) |
|
| 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.
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ add_subdirectory(times)
|
|||||||
add_subdirectory(motions)
|
add_subdirectory(motions)
|
||||||
add_subdirectory(utils)
|
add_subdirectory(utils)
|
||||||
add_subdirectory(experiments)
|
add_subdirectory(experiments)
|
||||||
|
add_subdirectory(dynamics)
|
||||||
|
|
||||||
add_library(simulation STATIC sims.cpp sims.h)
|
add_library(simulation STATIC sims.cpp sims.h)
|
||||||
target_link_libraries(simulation PRIVATE utils experiments OpenMP::OpenMP_CXX)
|
target_link_libraries(simulation PRIVATE utils experiments dynamics OpenMP::OpenMP_CXX)
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
rwsim
|
rwsim
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(rwsim PUBLIC RWMotion RWTime utils experiments simulation)
|
target_link_libraries(rwsim PUBLIC RWMotion RWTime utils experiments dynamics simulation)
|
||||||
|
|
||||||
target_compile_options(rwsim PUBLIC -Werror -Wall -Wextra -Wconversion -O2)
|
target_compile_options(rwsim PUBLIC -Werror -Wall -Wextra -Wconversion -O2)
|
||||||
|
|||||||
6
src/dynamics/CMakeLists.txt
Normal file
6
src/dynamics/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
add_library(
|
||||||
|
dynamics STATIC
|
||||||
|
base.h
|
||||||
|
decoupled.cpp
|
||||||
|
decoupled.h
|
||||||
|
)
|
||||||
26
src/dynamics/base.h
Normal file
26
src/dynamics/base.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef RWSIM_DYNAMICSBASE_H
|
||||||
|
#define RWSIM_DYNAMICSBASE_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct Step {
|
||||||
|
double dt;
|
||||||
|
double omega;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Dynamics {
|
||||||
|
public:
|
||||||
|
virtual ~Dynamics() = default;
|
||||||
|
|
||||||
|
virtual void setParameters(const std::unordered_map<std::string, double>& parameters) = 0;
|
||||||
|
virtual void initialize(std::mt19937_64& rng) = 0;
|
||||||
|
virtual Step next(std::mt19937_64& rng) = 0;
|
||||||
|
[[nodiscard]] virtual double getInitOmega() const = 0;
|
||||||
|
[[nodiscard]] virtual std::unique_ptr<Dynamics> clone() const = 0;
|
||||||
|
[[nodiscard]] virtual std::string toString() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //RWSIM_DYNAMICSBASE_H
|
||||||
35
src/dynamics/decoupled.cpp
Normal file
35
src/dynamics/decoupled.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "decoupled.h"
|
||||||
|
|
||||||
|
DecoupledDynamics::DecoupledDynamics(
|
||||||
|
std::unique_ptr<motions::BaseMotion> motion,
|
||||||
|
std::unique_ptr<times::BaseDistribution> dist)
|
||||||
|
: m_motion(std::move(motion)), m_dist(std::move(dist)) {}
|
||||||
|
|
||||||
|
void DecoupledDynamics::setParameters(const std::unordered_map<std::string, double>& parameters) {
|
||||||
|
m_motion->setParameters(parameters);
|
||||||
|
m_dist->setParameters(parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecoupledDynamics::initialize(std::mt19937_64& rng) {
|
||||||
|
m_motion->initialize(rng);
|
||||||
|
m_dist->initialize(rng);
|
||||||
|
}
|
||||||
|
|
||||||
|
Step DecoupledDynamics::next(std::mt19937_64& rng) {
|
||||||
|
double dt = m_dist->tau_wait(rng);
|
||||||
|
double omega = m_motion->jump(rng);
|
||||||
|
return {dt, omega};
|
||||||
|
}
|
||||||
|
|
||||||
|
double DecoupledDynamics::getInitOmega() const {
|
||||||
|
return m_motion->getInitOmega();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Dynamics> DecoupledDynamics::clone() const {
|
||||||
|
return std::make_unique<DecoupledDynamics>(
|
||||||
|
m_motion->clone(), m_dist->clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DecoupledDynamics::toString() const {
|
||||||
|
return m_motion->toString() + "/" + m_dist->toString();
|
||||||
|
}
|
||||||
27
src/dynamics/decoupled.h
Normal file
27
src/dynamics/decoupled.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef RWSIM_DECOUPLED_H
|
||||||
|
#define RWSIM_DECOUPLED_H
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
#include "../motions/base.h"
|
||||||
|
#include "../times/base.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class DecoupledDynamics final : public Dynamics {
|
||||||
|
public:
|
||||||
|
DecoupledDynamics(std::unique_ptr<motions::BaseMotion> motion,
|
||||||
|
std::unique_ptr<times::BaseDistribution> dist);
|
||||||
|
|
||||||
|
void setParameters(const std::unordered_map<std::string, double>& parameters) override;
|
||||||
|
void initialize(std::mt19937_64& rng) override;
|
||||||
|
Step next(std::mt19937_64& rng) override;
|
||||||
|
[[nodiscard]] double getInitOmega() const override;
|
||||||
|
[[nodiscard]] std::unique_ptr<Dynamics> clone() const override;
|
||||||
|
[[nodiscard]] std::string toString() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<motions::BaseMotion> m_motion;
|
||||||
|
std::unique_ptr<times::BaseDistribution> m_dist;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //RWSIM_DECOUPLED_H
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
#ifndef RWSIM_EXPERIMENTBASE_H
|
#ifndef RWSIM_EXPERIMENTBASE_H
|
||||||
#define RWSIM_EXPERIMENTBASE_H
|
#define RWSIM_EXPERIMENTBASE_H
|
||||||
|
|
||||||
#include "../motions/base.h"
|
|
||||||
#include "../times/base.h"
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -23,7 +20,7 @@ public:
|
|||||||
const std::unordered_map<std::string, double>& optional) = 0;
|
const std::unordered_map<std::string, double>& optional) = 0;
|
||||||
[[nodiscard]] virtual double tmax() const = 0;
|
[[nodiscard]] virtual double tmax() const = 0;
|
||||||
virtual void accumulate(const Trajectory& traj, double init_omega, int num_walkers) = 0;
|
virtual void accumulate(const Trajectory& traj, double init_omega, int num_walkers) = 0;
|
||||||
virtual void save(const motions::BaseMotion& motion, const times::BaseDistribution& dist) = 0;
|
virtual void save(const std::string& directory) = 0;
|
||||||
[[nodiscard]] virtual std::unique_ptr<Experiment> clone() const = 0;
|
[[nodiscard]] virtual std::unique_ptr<Experiment> clone() const = 0;
|
||||||
virtual void merge(const Experiment& other) = 0;
|
virtual void merge(const Experiment& other) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "../utils/ranges.h"
|
#include "../utils/ranges.h"
|
||||||
#include "../utils/io.h"
|
#include "../utils/io.h"
|
||||||
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@@ -44,10 +45,9 @@ void SpectrumExperiment::accumulate(const Trajectory& traj, double, int num_walk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpectrumExperiment::save(const motions::BaseMotion& motion, const times::BaseDistribution& dist) {
|
void SpectrumExperiment::save(const std::string& directory) {
|
||||||
const auto path = make_directory(motion, dist);
|
save_parameter_to_file(std::string("timesignal"), directory, m_parameter, m_optional);
|
||||||
save_parameter_to_file(std::string("timesignal"), path, m_parameter, m_optional);
|
save_data_to_file(std::string("timesignal"), directory, m_t_fid, m_fid_dict, m_optional);
|
||||||
save_data_to_file(std::string("timesignal"), path, m_t_fid, m_fid_dict, m_optional);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Experiment> SpectrumExperiment::clone() const {
|
std::unique_ptr<Experiment> SpectrumExperiment::clone() const {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
const std::unordered_map<std::string, double>& optional) override;
|
const std::unordered_map<std::string, double>& optional) override;
|
||||||
[[nodiscard]] double tmax() const override;
|
[[nodiscard]] double tmax() const override;
|
||||||
void accumulate(const Trajectory& traj, double init_omega, int num_walkers) override;
|
void accumulate(const Trajectory& traj, double init_omega, int num_walkers) override;
|
||||||
void save(const motions::BaseMotion& motion, const times::BaseDistribution& dist) override;
|
void save(const std::string& directory) override;
|
||||||
[[nodiscard]] std::unique_ptr<Experiment> clone() const override;
|
[[nodiscard]] std::unique_ptr<Experiment> clone() const override;
|
||||||
void merge(const Experiment& other) override;
|
void merge(const Experiment& other) override;
|
||||||
|
|
||||||
|
|||||||
@@ -70,12 +70,11 @@ void STEExperiment::accumulate(const Trajectory& traj, double init_omega, int nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void STEExperiment::save(const motions::BaseMotion& motion, const times::BaseDistribution& dist) {
|
void STEExperiment::save(const std::string& directory) {
|
||||||
const auto folders = make_directory(motion, dist);
|
save_parameter_to_file(std::string("ste"), directory, m_parameter, m_optional);
|
||||||
save_parameter_to_file(std::string("ste"), folders, m_parameter, m_optional);
|
save_data_to_file(std::string("coscos"), directory, m_mixing_times, m_cc_dict, m_optional);
|
||||||
save_data_to_file(std::string("coscos"), folders, m_mixing_times, m_cc_dict, m_optional);
|
save_data_to_file(std::string("sinsin"), directory, m_mixing_times, m_ss_dict, m_optional);
|
||||||
save_data_to_file(std::string("sinsin"), folders, m_mixing_times, m_ss_dict, m_optional);
|
save_data_to_file(std::string("f2"), directory, m_mixing_times, m_f2, m_optional);
|
||||||
save_data_to_file(std::string("f2"), folders, m_mixing_times, m_f2, m_optional);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Experiment> STEExperiment::clone() const {
|
std::unique_ptr<Experiment> STEExperiment::clone() const {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
const std::unordered_map<std::string, double>& optional) override;
|
const std::unordered_map<std::string, double>& optional) override;
|
||||||
[[nodiscard]] double tmax() const override;
|
[[nodiscard]] double tmax() const override;
|
||||||
void accumulate(const Trajectory& traj, double init_omega, int num_walkers) override;
|
void accumulate(const Trajectory& traj, double init_omega, int num_walkers) override;
|
||||||
void save(const motions::BaseMotion& motion, const times::BaseDistribution& dist) override;
|
void save(const std::string& directory) override;
|
||||||
[[nodiscard]] std::unique_ptr<Experiment> clone() const override;
|
[[nodiscard]] std::unique_ptr<Experiment> clone() const override;
|
||||||
void merge(const Experiment& other) override;
|
void merge(const Experiment& other) override;
|
||||||
|
|
||||||
|
|||||||
10
src/main.cpp
10
src/main.cpp
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
#include "sims.h"
|
#include "sims.h"
|
||||||
|
#include "dynamics/decoupled.h"
|
||||||
#include "experiments/spectrum.h"
|
#include "experiments/spectrum.h"
|
||||||
#include "experiments/ste.h"
|
#include "experiments/ste.h"
|
||||||
#include "utils/io.h"
|
#include "utils/io.h"
|
||||||
@@ -43,16 +44,17 @@ int main (const int argc, char *argv[]) {
|
|||||||
rng.seed(rd());
|
rng.seed(rd());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto motion = motions::BaseMotion::createFromInput(args.motion_type);
|
DecoupledDynamics dynamics(
|
||||||
auto dist = times::BaseDistribution::createFromInput(args.distribution_type);
|
motions::BaseMotion::createFromInput(args.motion_type),
|
||||||
|
times::BaseDistribution::createFromInput(args.distribution_type));
|
||||||
|
|
||||||
if (args.spectrum) {
|
if (args.spectrum) {
|
||||||
SpectrumExperiment experiment;
|
SpectrumExperiment experiment;
|
||||||
run_simulation(experiment, parameter, args.optional, *motion, *dist, rng);
|
run_simulation(experiment, parameter, args.optional, dynamics, rng);
|
||||||
}
|
}
|
||||||
if (args.ste) {
|
if (args.ste) {
|
||||||
STEExperiment experiment;
|
STEExperiment experiment;
|
||||||
run_simulation(experiment, parameter, args.optional, *motion, *dist, rng);
|
run_simulation(experiment, parameter, args.optional, dynamics, rng);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
41
src/sims.cpp
41
src/sims.cpp
@@ -1,5 +1,6 @@
|
|||||||
#include "sims.h"
|
#include "sims.h"
|
||||||
#include "utils/functions.h"
|
#include "utils/functions.h"
|
||||||
|
#include "utils/io.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -10,14 +11,12 @@ void run_simulation(
|
|||||||
Experiment& experiment,
|
Experiment& experiment,
|
||||||
std::unordered_map<std::string, double>& parameter,
|
std::unordered_map<std::string, double>& parameter,
|
||||||
std::unordered_map<std::string, double>& optional,
|
std::unordered_map<std::string, double>& optional,
|
||||||
motions::BaseMotion& motion,
|
Dynamics& dynamics,
|
||||||
times::BaseDistribution& dist,
|
|
||||||
std::mt19937_64& rng
|
std::mt19937_64& rng
|
||||||
) {
|
) {
|
||||||
const int num_walker = static_cast<int>(parameter["num_walker"]);
|
const int num_walker = static_cast<int>(parameter["num_walker"]);
|
||||||
|
|
||||||
dist.setParameters(parameter);
|
dynamics.setParameters(parameter);
|
||||||
motion.setParameters(parameter);
|
|
||||||
experiment.setup(parameter, optional);
|
experiment.setup(parameter, optional);
|
||||||
|
|
||||||
const auto start = printStart(optional);
|
const auto start = printStart(optional);
|
||||||
@@ -31,13 +30,11 @@ void run_simulation(
|
|||||||
thread_rngs.emplace_back(rng());
|
thread_rngs.emplace_back(rng());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create per-thread clones of motion, distribution, and experiment
|
// Create per-thread clones of dynamics and experiment
|
||||||
std::vector<std::unique_ptr<motions::BaseMotion>> thread_motions;
|
std::vector<std::unique_ptr<Dynamics>> thread_dynamics;
|
||||||
std::vector<std::unique_ptr<times::BaseDistribution>> thread_dists;
|
|
||||||
std::vector<std::unique_ptr<Experiment>> thread_experiments;
|
std::vector<std::unique_ptr<Experiment>> thread_experiments;
|
||||||
for (int i = 0; i < num_threads; i++) {
|
for (int i = 0; i < num_threads; i++) {
|
||||||
thread_motions.push_back(motion.clone());
|
thread_dynamics.push_back(dynamics.clone());
|
||||||
thread_dists.push_back(dist.clone());
|
|
||||||
thread_experiments.push_back(experiment.clone());
|
thread_experiments.push_back(experiment.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,14 +45,13 @@ void run_simulation(
|
|||||||
{
|
{
|
||||||
const int tid = omp_get_thread_num();
|
const int tid = omp_get_thread_num();
|
||||||
auto& local_rng = thread_rngs[tid];
|
auto& local_rng = thread_rngs[tid];
|
||||||
auto& local_motion = *thread_motions[tid];
|
auto& local_dynamics = *thread_dynamics[tid];
|
||||||
auto& local_dist = *thread_dists[tid];
|
|
||||||
auto& local_experiment = *thread_experiments[tid];
|
auto& local_experiment = *thread_experiments[tid];
|
||||||
|
|
||||||
#pragma omp for schedule(static)
|
#pragma omp for schedule(static)
|
||||||
for (int mol_i = 0; mol_i < num_walker; mol_i++) {
|
for (int mol_i = 0; mol_i < num_walker; mol_i++) {
|
||||||
auto traj = make_trajectory(local_motion, local_dist, experiment.tmax(), local_rng);
|
auto traj = make_trajectory(local_dynamics, experiment.tmax(), local_rng);
|
||||||
local_experiment.accumulate(traj, local_motion.getInitOmega(), num_walker);
|
local_experiment.accumulate(traj, local_dynamics.getInitOmega(), num_walker);
|
||||||
|
|
||||||
if (tid == 0) {
|
if (tid == 0) {
|
||||||
#pragma omp atomic
|
#pragma omp atomic
|
||||||
@@ -73,24 +69,23 @@ void run_simulation(
|
|||||||
experiment.merge(*thread_experiments[i]);
|
experiment.merge(*thread_experiments[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
experiment.save(motion, dist);
|
const auto directory = make_directory(dynamics.toString());
|
||||||
|
experiment.save(directory);
|
||||||
printEnd(start);
|
printEnd(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Trajectory make_trajectory(
|
Trajectory make_trajectory(
|
||||||
motions::BaseMotion& motion,
|
Dynamics& dynamics,
|
||||||
times::BaseDistribution& dist,
|
|
||||||
const double t_max,
|
const double t_max,
|
||||||
std::mt19937_64& rng
|
std::mt19937_64& rng
|
||||||
) {
|
) {
|
||||||
double t_passed = 0;
|
double t_passed = 0;
|
||||||
double phase = 0;
|
double phase = 0;
|
||||||
|
|
||||||
motion.initialize(rng);
|
dynamics.initialize(rng);
|
||||||
dist.initialize(rng);
|
|
||||||
|
|
||||||
double omega = motion.getInitOmega();
|
double omega = dynamics.getInitOmega();
|
||||||
|
|
||||||
Trajectory traj;
|
Trajectory traj;
|
||||||
traj.time.emplace_back(t_passed);
|
traj.time.emplace_back(t_passed);
|
||||||
@@ -98,10 +93,10 @@ Trajectory make_trajectory(
|
|||||||
traj.omega.emplace_back(omega);
|
traj.omega.emplace_back(omega);
|
||||||
|
|
||||||
while (t_passed < t_max) {
|
while (t_passed < t_max) {
|
||||||
const double t = dist.tau_wait(rng);
|
auto [dt, new_omega] = dynamics.next(rng);
|
||||||
t_passed += t;
|
phase += omega * dt;
|
||||||
omega = motion.jump(rng);
|
t_passed += dt;
|
||||||
phase += omega * t;
|
omega = new_omega;
|
||||||
|
|
||||||
traj.time.emplace_back(t_passed);
|
traj.time.emplace_back(t_passed);
|
||||||
traj.phase.emplace_back(phase);
|
traj.phase.emplace_back(phase);
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
#ifndef RWSIM_SIMS_H
|
#ifndef RWSIM_SIMS_H
|
||||||
#define RWSIM_SIMS_H
|
#define RWSIM_SIMS_H
|
||||||
|
|
||||||
|
#include "dynamics/base.h"
|
||||||
#include "experiments/base.h"
|
#include "experiments/base.h"
|
||||||
#include "motions/base.h"
|
|
||||||
#include "times/base.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -14,11 +13,10 @@ void run_simulation(
|
|||||||
Experiment& experiment,
|
Experiment& experiment,
|
||||||
std::unordered_map<std::string, double>& parameter,
|
std::unordered_map<std::string, double>& parameter,
|
||||||
std::unordered_map<std::string, double>& optional,
|
std::unordered_map<std::string, double>& optional,
|
||||||
motions::BaseMotion& motion,
|
Dynamics& dynamics,
|
||||||
times::BaseDistribution& dist,
|
|
||||||
std::mt19937_64& rng);
|
std::mt19937_64& rng);
|
||||||
|
|
||||||
Trajectory make_trajectory(motions::BaseMotion& motion, times::BaseDistribution& dist, double t_max, std::mt19937_64& rng);
|
Trajectory make_trajectory(Dynamics& dynamics, double t_max, std::mt19937_64& rng);
|
||||||
|
|
||||||
std::chrono::system_clock::time_point printStart(std::unordered_map<std::string, double> &optional);
|
std::chrono::system_clock::time_point printStart(std::unordered_map<std::string, double> &optional);
|
||||||
void printEnd(std::chrono::system_clock::time_point start);
|
void printEnd(std::chrono::system_clock::time_point start);
|
||||||
|
|||||||
@@ -11,11 +11,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "../motions/base.h"
|
|
||||||
#include "../times/base.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Motion;
|
|
||||||
|
|
||||||
std::pair<std::string, double> get_optional_parameter(std::vector<std::string>::const_iterator &it) {
|
std::pair<std::string, double> get_optional_parameter(std::vector<std::string>::const_iterator &it) {
|
||||||
std::string stripped_arg;
|
std::string stripped_arg;
|
||||||
@@ -128,19 +123,12 @@ std::unordered_map<std::string, double> read_parameter(const std::filesystem::pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string make_directory(
|
std::string make_directory(const std::string& path_name) {
|
||||||
const motions::BaseMotion& motion,
|
if (!std::filesystem::create_directories(path_name)) {
|
||||||
const times::BaseDistribution& distribution
|
std::cout << "Created directory " << path_name << std::endl;
|
||||||
) {
|
|
||||||
std::ostringstream path_name;
|
|
||||||
path_name << motion.toString() << "/" << distribution.toString();
|
|
||||||
|
|
||||||
if (!std::filesystem::create_directories(path_name.str())) {
|
|
||||||
std::cout << "Created directory " << path_name.str() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return path_name;
|
||||||
return path_name.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,6 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../motions/base.h"
|
|
||||||
#include "../times/base.h"
|
|
||||||
|
|
||||||
struct Arguments {
|
struct Arguments {
|
||||||
std::string parameter_file{};
|
std::string parameter_file{};
|
||||||
bool ste = false;
|
bool ste = false;
|
||||||
@@ -23,7 +20,7 @@ Arguments parse_args(int argc, char* argv[]);
|
|||||||
std::pair<std::string, double> get_optional_parameter(std::vector<std::string>::const_iterator &it);
|
std::pair<std::string, double> get_optional_parameter(std::vector<std::string>::const_iterator &it);
|
||||||
std::unordered_map<std::string, double> read_parameter(const std::filesystem::path&);
|
std::unordered_map<std::string, double> read_parameter(const std::filesystem::path&);
|
||||||
|
|
||||||
std::string make_directory(const motions::BaseMotion&, const times::BaseDistribution&);
|
std::string make_directory(const std::string& path_name);
|
||||||
|
|
||||||
void save_parameter_to_file(const std::string&, const std::string&, const std::unordered_map<std::string, double>&, const std::unordered_map<std::string, double>&);
|
void save_parameter_to_file(const std::string&, const std::string&, const std::unordered_map<std::string, double>&, const std::unordered_map<std::string, double>&);
|
||||||
void save_data_to_file(const std::string&, const std::string&, const std::vector<double>&, const std::map<double, std::vector<double>>&, const std::unordered_map<std::string, double>&);
|
void save_data_to_file(const std::string&, const std::string&, const std::vector<double>&, const std::map<double, std::vector<double>>&, const std::unordered_map<std::string, double>&);
|
||||||
|
|||||||
Reference in New Issue
Block a user