first commit
This commit is contained in:
commit
17f95627a9
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/cmake-build-debug/
|
||||||
|
.idea
|
27
CMakeLists.txt
Normal file
27
CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.28)
|
||||||
|
project(rwsim)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
add_executable(rwsim main.cpp
|
||||||
|
functions.cpp
|
||||||
|
functions.h
|
||||||
|
io.cpp
|
||||||
|
io.h
|
||||||
|
motions/base.cpp
|
||||||
|
motions/base.h
|
||||||
|
motions/random.cpp
|
||||||
|
motions/random.h
|
||||||
|
times/base.cpp
|
||||||
|
times/base.h
|
||||||
|
times/delta.cpp
|
||||||
|
times/delta.h
|
||||||
|
sims.cpp
|
||||||
|
sims.h
|
||||||
|
ranges.cpp
|
||||||
|
ranges.h
|
||||||
|
motions/tetrahedral.cpp
|
||||||
|
motions/tetrahedral.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(rwsim PUBLIC -Werror -Wall -Wextra -Wconversion -O2)
|
51
functions.cpp
Normal file
51
functions.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/14/24.
|
||||||
|
//#
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
int nearest_index(const std::vector<double> &x_ref, const double x, int start=0) {
|
||||||
|
while (x > x_ref[start+1]) {
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
double lerp(const std::vector<double>& x_ref, const std::vector<double>& y_ref, const double x, const int i) {
|
||||||
|
const double x_left = x_ref[i];
|
||||||
|
const double y_left = y_ref[i];
|
||||||
|
const double x_right = x_ref[i+1];
|
||||||
|
const double y_right = y_ref[i+1];
|
||||||
|
|
||||||
|
const double dydx = (y_right - y_left) / ( x_right - x_left );
|
||||||
|
|
||||||
|
return y_left + dydx * (x - x_left);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> printSteps(
|
||||||
|
const std::chrono::time_point<std::chrono::system_clock> last_print_out,
|
||||||
|
const std::chrono::time_point<std::chrono::system_clock> start,
|
||||||
|
const int total,
|
||||||
|
const int steps
|
||||||
|
) {
|
||||||
|
const auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
if (const std::chrono::duration<float> duration = now - last_print_out; duration.count() < 10.) {
|
||||||
|
return last_print_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::duration<float> duration = now - start;
|
||||||
|
const auto passed = duration.count();
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << steps << " of " << total << " steps: " << passed << "s passed; ~" << passed * static_cast<float>(total-steps) / static_cast<float>(steps) << "s remaining\n";
|
||||||
|
|
||||||
|
return now;
|
||||||
|
// time_t end_time = std::chrono::system_clock::to_time_t(end);
|
||||||
|
// std::cout << "End tau = " << tau_i << "s : " << ctime(&end_time);
|
||||||
|
// std::cout << "Duration: " << duration.count() << "s\n" << std::endl;
|
||||||
|
|
||||||
|
}
|
13
functions.h
Normal file
13
functions.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef RWSIM_FUNCTIONS_H
|
||||||
|
#define RWSIM_FUNCTIONS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
int nearest_index(const std::vector<double>&, double, int);
|
||||||
|
|
||||||
|
double lerp(const std::vector<double>&, const std::vector<double>&, double, int);
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> printSteps(std::chrono::time_point<std::chrono::system_clock>, std::chrono::time_point<std::chrono::system_clock>, int, int);
|
||||||
|
|
||||||
|
#endif
|
88
io.cpp
Normal file
88
io.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/14/24.
|
||||||
|
//
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
std::unordered_map<std::string, double> parse_arguments(const char *infile) {
|
||||||
|
std::ifstream instream(infile);
|
||||||
|
|
||||||
|
std::unordered_map<std::string, double> parameter;
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
std::string delim = "=";
|
||||||
|
std::string key;
|
||||||
|
std::string value;
|
||||||
|
size_t delim_pos;
|
||||||
|
|
||||||
|
// TODO this needs a check for file existence
|
||||||
|
|
||||||
|
while (std::getline(instream, line)) {
|
||||||
|
line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
|
||||||
|
delim_pos = line.find('=');
|
||||||
|
key = line.substr(0, delim_pos);
|
||||||
|
value = line.substr(delim_pos+1);
|
||||||
|
parameter[key] = std::stod(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Found parameter\n";
|
||||||
|
for (const auto& [key, value]: parameter) {
|
||||||
|
std::cout << " " << key << ": " << std::to_string(value) << "\n";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fid_write_out(const std::string& filename, const std::vector<double>& x, const std::vector<double>& y, const double tau, const double t_evo) {
|
||||||
|
auto size = x.size();
|
||||||
|
|
||||||
|
std::ostringstream sfile;
|
||||||
|
sfile << filename << "_";
|
||||||
|
sfile << std::setprecision(6) << std::scientific;
|
||||||
|
sfile << "tau=" << tau << "_tevo=" << t_evo << ".dat";
|
||||||
|
{
|
||||||
|
std::string outfile = sfile.str();
|
||||||
|
std::ofstream fid_file(outfile, std::ios::out);
|
||||||
|
for (unsigned int i = 0; i < size; i++) {
|
||||||
|
fid_file << x[i] << "\t" << y[i] << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fid_write_out(const std::string& filename, const std::vector<double>& x, const std::map<double, std::vector<double>>& y, const double tau) {
|
||||||
|
auto size = x.size();
|
||||||
|
|
||||||
|
std::ostringstream sfile;
|
||||||
|
sfile << filename << "_";
|
||||||
|
sfile << std::setprecision(6) << std::scientific;
|
||||||
|
sfile << "tau=" << tau << ".dat";
|
||||||
|
{
|
||||||
|
std::string outfile = sfile.str();
|
||||||
|
std::ofstream fid_file(outfile, std::ios::out);
|
||||||
|
fid_file << "#";
|
||||||
|
for (const auto& [t_echo_j, _] : y) {
|
||||||
|
fid_file << t_echo_j << "\t";
|
||||||
|
}
|
||||||
|
fid_file << std::endl;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < size; i++) {
|
||||||
|
fid_file << x[i];
|
||||||
|
for (const auto& [_, fid_j] : y) {
|
||||||
|
fid_file << "\t" << fid_j[i];
|
||||||
|
}
|
||||||
|
fid_file << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
io.h
Normal file
15
io.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
#ifndef RWSIM_IO_H
|
||||||
|
#define RWSIM_IO_H
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::unordered_map<std::string, double> parse_arguments(const char *);
|
||||||
|
|
||||||
|
void fid_write_out(const std::string&, const std::vector<double>&, const std::vector<double>&, double, double);
|
||||||
|
void fid_write_out(const std::string&, const std::vector<double>&, const std::map<double, std::vector<double>>&, double tau);
|
||||||
|
|
||||||
|
#endif
|
21
main.cpp
Normal file
21
main.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <unordered_map>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
#include "io.h"
|
||||||
|
#include "sims.h"
|
||||||
|
#include "motions/random.h"
|
||||||
|
#include "times/delta.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
std::unordered_map parameter { parse_arguments("config.txt") };
|
||||||
|
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937_64 rng(rd());
|
||||||
|
|
||||||
|
auto motion = RandomJump(rng);
|
||||||
|
auto dist = DeltaDistribution(rng);
|
||||||
|
|
||||||
|
run_spectrum(parameter, motion, dist);
|
||||||
|
|
||||||
|
}
|
31
motions/base.cpp
Normal file
31
motions/base.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
Motion::Motion(const double delta, const double eta, std::mt19937_64& rng) : m_delta(delta), m_eta(eta), m_rng(rng) {
|
||||||
|
m_uni_dist = std::uniform_real_distribution(0., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
Motion::Motion(std::mt19937_64& rng) : m_rng(rng) {
|
||||||
|
m_uni_dist = std::uniform_real_distribution(0., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Motion::omega_q(const double cos_theta, const double phi) const {
|
||||||
|
const double cos_theta_square = cos_theta * cos_theta;
|
||||||
|
const double sin_theta_square = 1. - cos_theta_square;
|
||||||
|
|
||||||
|
return M_PI * m_delta * (3 * cos_theta_square - 1 - m_eta * sin_theta_square * cos(2.*phi));
|
||||||
|
}
|
||||||
|
|
||||||
|
double Motion::draw_position() {
|
||||||
|
const double cos_theta = 1 - 2 * m_uni_dist(m_rng);
|
||||||
|
const double phi = 2.0 * M_PI * m_uni_dist(m_rng);
|
||||||
|
|
||||||
|
return omega_q(cos_theta, phi);
|
||||||
|
}
|
||||||
|
|
35
motions/base.h
Normal file
35
motions/base.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RWSIM_MOTIONBASE_H
|
||||||
|
#define RWSIM_MOTIONBASE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
class Motion {
|
||||||
|
public:
|
||||||
|
virtual ~Motion() = default;
|
||||||
|
|
||||||
|
Motion(double, double, std::mt19937_64&);
|
||||||
|
explicit Motion(std::mt19937_64&);
|
||||||
|
|
||||||
|
double draw_position();
|
||||||
|
[[nodiscard]] double omega_q(double, double) const;
|
||||||
|
|
||||||
|
virtual double jump() = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] double getDelta() const { return m_delta; }
|
||||||
|
void setDelta(const double delta) { m_delta = delta; }
|
||||||
|
[[nodiscard]] double getEta() const { return m_eta; }
|
||||||
|
void setEta(const double eta) { m_eta = eta; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_delta{1.};
|
||||||
|
double m_eta{0.};
|
||||||
|
std::mt19937_64& m_rng;
|
||||||
|
std::uniform_real_distribution<double> m_uni_dist;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //RWSIM_MOTIONBASE_H
|
14
motions/random.cpp
Normal file
14
motions/random.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
|
|
||||||
|
RandomJump::RandomJump(const double delta, const double eta, std::mt19937_64 &rng) : Motion(delta, eta, rng) {}
|
||||||
|
|
||||||
|
RandomJump::RandomJump(std::mt19937_64 &rng) : Motion(rng) {}
|
||||||
|
|
||||||
|
double RandomJump::jump() {
|
||||||
|
return draw_position();
|
||||||
|
}
|
19
motions/random.h
Normal file
19
motions/random.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RWSIM_MOTIONRANDOMJUMP_H
|
||||||
|
#define RWSIM_MOTIONRANDOMJUMP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
#include <random>
|
||||||
|
class RandomJump final : public Motion {
|
||||||
|
public:
|
||||||
|
RandomJump(double, double, std::mt19937_64&);
|
||||||
|
explicit RandomJump(std::mt19937_64&);
|
||||||
|
|
||||||
|
double jump() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //RWSIM_MOTIONRANDOMJUMP_H
|
14
motions/tetrahedral.cpp
Normal file
14
motions/tetrahedral.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/16/24.
|
||||||
|
//
|
||||||
|
#include <random>
|
||||||
|
#include "tetrahedral.h"
|
||||||
|
|
||||||
|
|
||||||
|
TetrahedralJump::TetrahedralJump(const double delta, const double eta, std::mt19937_64& rng) : Motion(delta, eta, rng) {}
|
||||||
|
|
||||||
|
TetrahedralJump::TetrahedralJump(std::mt19937_64& rng) : Motion(rng) {}
|
||||||
|
|
||||||
|
double TetrahedralJump::jump() {
|
||||||
|
return draw_position();
|
||||||
|
}
|
20
motions/tetrahedral.h
Normal file
20
motions/tetrahedral.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/16/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RWSIM_MOTIONTETRAHEDRAL_H
|
||||||
|
#define RWSIM_MOTIONTETRAHEDRAL_H
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
class TetrahedralJump final : public Motion {
|
||||||
|
public:
|
||||||
|
TetrahedralJump(double, double, std::mt19937_64&);
|
||||||
|
explicit TetrahedralJump(std::mt19937_64&);
|
||||||
|
|
||||||
|
double jump() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //RWSIM_MOTIONTETRAHEDRAL_H
|
60
ranges.cpp
Normal file
60
ranges.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/14/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "ranges.h"
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<double> arange(const int size, const double spacing=1.) {
|
||||||
|
std::vector<double> out(size);
|
||||||
|
std::generate(out.begin(), out.end(), [n = 0, spacing]() mutable { return n++ * spacing; });
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> linspace(const double start, const double stop, const int steps) {
|
||||||
|
std::vector<double> range;
|
||||||
|
|
||||||
|
if (steps == 0) {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (steps == 1) {
|
||||||
|
range.push_back(start);
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double stepsize = (stop-start) / (steps-1);
|
||||||
|
for (int i=0; i<steps; i++) {
|
||||||
|
range.push_back(start + stepsize * i);
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<double> logspace(const double start, const double stop, const int steps) {
|
||||||
|
std::vector<double> range;
|
||||||
|
|
||||||
|
if (steps == 0) {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (steps == 1) {
|
||||||
|
range.push_back(start);
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double logstart = log10(start);
|
||||||
|
const double logstop = log10(stop);
|
||||||
|
|
||||||
|
const double stepsize = (logstop-logstart) / (steps-1);
|
||||||
|
for (int i=0; i<steps; i++) {
|
||||||
|
range.push_back(pow(10, logstart + stepsize * i));
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
}
|
12
ranges.h
Normal file
12
ranges.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef RWSIM_RANGES_H
|
||||||
|
#define RWSIM_RANGES_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::vector<double> arange(int, double);
|
||||||
|
|
||||||
|
std::vector<double> linspace(double, double, int);
|
||||||
|
|
||||||
|
std::vector<double> logspace(double, double, int);
|
||||||
|
|
||||||
|
#endif
|
184
sims.cpp
Normal file
184
sims.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/14/24.
|
||||||
|
//
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "functions.h"
|
||||||
|
#include "motions/base.h"
|
||||||
|
#include "times/base.h"
|
||||||
|
#include "ranges.h"
|
||||||
|
#include "sims.h"
|
||||||
|
|
||||||
|
#include <bits/fs_fwd.h>
|
||||||
|
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
|
||||||
|
void run_spectrum(std::unordered_map<std::string, double>& parameter, Motion& motion, Distribution& dist) {
|
||||||
|
const int num_acq = static_cast<int>(parameter["num_acq"]);
|
||||||
|
const int num_walker = static_cast<int>(parameter["num_walker"]);
|
||||||
|
|
||||||
|
const std::vector<double> correlation_times = logspace(parameter["tau_start"], parameter["tau_stop"], static_cast<int>(parameter["tau_steps"]));
|
||||||
|
motion.setDelta(parameter["delta"]);
|
||||||
|
motion.setEta(parameter["eta"]);
|
||||||
|
|
||||||
|
// time axis for all time signals
|
||||||
|
const auto t_fid = arange(num_acq, parameter["dwell_time"]);
|
||||||
|
const std::vector<double> echo_times = linspace(parameter["techo_start"], parameter["techo_stop"], static_cast<int>(parameter["techo_steps"]));
|
||||||
|
|
||||||
|
std::map<double, std::vector<double>> fid_dict;
|
||||||
|
for (auto t_evo_i: echo_times) {
|
||||||
|
fid_dict[t_evo_i] = std::vector<double>(num_acq);
|
||||||
|
std::fill(fid_dict[t_evo_i].begin(), fid_dict[t_evo_i].end(), 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
const double tmax = *std::max_element(echo_times.begin(), echo_times.end()) * 2 + t_fid.back();
|
||||||
|
|
||||||
|
for (const auto tau_i: correlation_times) {
|
||||||
|
auto start = std::chrono::system_clock::now();
|
||||||
|
auto last_print_out = std::chrono::system_clock::now();
|
||||||
|
time_t start_time = std::chrono::system_clock::to_time_t(start);
|
||||||
|
std::cout << "Start tau = " << tau_i << "s : " << ctime(&start_time);
|
||||||
|
|
||||||
|
dist.setTau(tau_i);
|
||||||
|
|
||||||
|
for (auto& [_, fid_j]: fid_dict) {
|
||||||
|
std::fill(fid_j.begin(), fid_j.end(), 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset array for each correlation time
|
||||||
|
for (int mol_i = 0; mol_i < num_walker; mol_i++){
|
||||||
|
std::vector<double> traj_time{};
|
||||||
|
std::vector<double> traj_phase{};
|
||||||
|
|
||||||
|
make_trajectory(motion, dist, tmax, traj_time, traj_phase);
|
||||||
|
|
||||||
|
for (auto& [t_echo_j, fid_j] : fid_dict) {
|
||||||
|
// get phase at echo pulse
|
||||||
|
int current_pos = nearest_index(traj_time, t_echo_j, 0);
|
||||||
|
const double phase_tevo = lerp(traj_time, traj_phase, t_echo_j, current_pos);
|
||||||
|
|
||||||
|
// time axis by echo delay to get time in trajectory
|
||||||
|
|
||||||
|
for (int acq_idx = 0; acq_idx < num_acq; acq_idx++) {
|
||||||
|
const double real_time = t_fid[acq_idx] + 2 * t_echo_j;
|
||||||
|
|
||||||
|
current_pos = nearest_index(traj_time, real_time, current_pos);
|
||||||
|
const double phase_acq = lerp(traj_time, traj_phase, real_time, current_pos);
|
||||||
|
|
||||||
|
fid_j[acq_idx] += cos(phase_acq - 2 * phase_tevo) / num_walker;
|
||||||
|
}
|
||||||
|
last_print_out = printSteps(last_print_out, start, num_walker, mol_i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write fid to files
|
||||||
|
fid_write_out("fid", t_fid, fid_dict, tau_i);
|
||||||
|
|
||||||
|
auto end = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
std::chrono::duration<float> duration = end - start;
|
||||||
|
time_t end_time = std::chrono::system_clock::to_time_t(end);
|
||||||
|
std::cout << "End tau = " << tau_i << "s : " << ctime(&end_time);
|
||||||
|
std::cout << "Duration: " << duration.count() << "s\n" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_ste(std::unordered_map<std::string, double>& parameter, Motion& motion, Distribution& dist) {
|
||||||
|
const int num_acq = static_cast<int>(parameter[std::string("num_acq")]);
|
||||||
|
const int num_walker = static_cast<int>(parameter[std::string("num_walker")]);
|
||||||
|
|
||||||
|
const std::vector<double> correlation_times = logspace(parameter["tau_start"], parameter["tau_stop"], static_cast<int>(parameter["tau_steps"]));
|
||||||
|
|
||||||
|
motion.setDelta(parameter["delta"]);
|
||||||
|
motion.setEta(parameter["eta"]);
|
||||||
|
|
||||||
|
const std::vector<double> evolution_times = linspace(parameter["tevo_start"], parameter["tevo_stop"], static_cast<int>(parameter["tevo_steps"]));
|
||||||
|
const std::vector<double> mixing_times = linspace(parameter["tevo_start"], parameter["tevo_stop"], static_cast<int>(parameter["tevo_steps"]));
|
||||||
|
|
||||||
|
|
||||||
|
std::map<double, std::vector<double>> fid_dict;
|
||||||
|
for (auto t_evo_i: evolution_times) {
|
||||||
|
fid_dict[t_evo_i] = std::vector<double>(num_acq);
|
||||||
|
std::fill(fid_dict[t_evo_i].begin(), fid_dict[t_evo_i].end(), 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
// each trajectory must have a duration of at least tmax
|
||||||
|
|
||||||
|
const double tmax = *std::max_element(evolution_times.begin(), evolution_times.end()) * 2 + *std::max_element(mixing_times.begin(), mixing_times.end());
|
||||||
|
|
||||||
|
for (const auto tau_i: correlation_times) {
|
||||||
|
auto start = std::chrono::system_clock::now();
|
||||||
|
time_t start_time = std::chrono::system_clock::to_time_t(start);
|
||||||
|
std::cout << "Start tau = " << tau_i << "s : " << ctime(&start_time);
|
||||||
|
|
||||||
|
dist.setTau(tau_i);
|
||||||
|
|
||||||
|
for (auto& [_, fid_j]: fid_dict) {
|
||||||
|
std::fill(fid_j.begin(), fid_j.end(), 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset array for each correlation time
|
||||||
|
for (int mol_i = 0; mol_i < num_walker; mol_i++){
|
||||||
|
std::vector<double> traj_time{};
|
||||||
|
std::vector<double> traj_phase{};
|
||||||
|
|
||||||
|
make_trajectory(motion, dist, tmax, traj_time, traj_phase);
|
||||||
|
|
||||||
|
for (auto& [t_evo_j, fid_j] : fid_dict) {
|
||||||
|
int current_pos = nearest_index(traj_time, t_evo_j, 0);
|
||||||
|
const double phase_tevo = lerp(traj_time, traj_phase, t_evo_j, current_pos);
|
||||||
|
|
||||||
|
// time axis by echo delay to get time in trajectory
|
||||||
|
|
||||||
|
for (int acq_idx = 0; acq_idx < num_acq; acq_idx++) {
|
||||||
|
const double real_time = mixing_times[acq_idx] + t_evo_j;
|
||||||
|
|
||||||
|
current_pos = nearest_index(traj_time, real_time, current_pos);
|
||||||
|
const double phase_acq = lerp(traj_time, traj_phase, real_time, current_pos);
|
||||||
|
|
||||||
|
fid_j[acq_idx] += cos(phase_acq - 2 * phase_tevo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write fid to files
|
||||||
|
fid_write_out("ste", mixing_times, fid_dict, tau_i);
|
||||||
|
|
||||||
|
auto end = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
std::chrono::duration<float> duration = end - start;
|
||||||
|
time_t end_time = std::chrono::system_clock::to_time_t(end);
|
||||||
|
std::cout << "End tau = " << tau_i << "s : " << ctime(&end_time);
|
||||||
|
std::cout << "Duration: " << duration.count() << "s\n" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void make_trajectory(Motion& motion, const Distribution& dist, const double t_max, std::vector<double>& out_time, std::vector<double>& out_phase) {
|
||||||
|
// Starting position
|
||||||
|
double t_passed = 0;
|
||||||
|
double phase = 0;
|
||||||
|
|
||||||
|
out_time.emplace_back(t_passed);
|
||||||
|
out_phase.emplace_back(0);
|
||||||
|
|
||||||
|
while (t_passed < t_max) {
|
||||||
|
const double t = dist.tau_wait();
|
||||||
|
t_passed += t;
|
||||||
|
|
||||||
|
phase += motion.jump() * t;
|
||||||
|
|
||||||
|
// phase += jump(delta, eta, rng) * t;
|
||||||
|
|
||||||
|
out_time.emplace_back(t_passed);
|
||||||
|
out_phase.emplace_back(phase);
|
||||||
|
}
|
||||||
|
}
|
17
sims.h
Normal file
17
sims.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/14/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RWSIM_SIMS_H
|
||||||
|
#define RWSIM_SIMS_H
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "motions/base.h"
|
||||||
|
#include "times/base.h"
|
||||||
|
|
||||||
|
void run_spectrum(std::unordered_map<std::string, double>& parameter, Motion& motion, Distribution& dist);
|
||||||
|
void make_trajectory(Motion&, const Distribution&, double, std::vector<double>&, std::vector<double>&);
|
||||||
|
|
||||||
|
#endif //RWSIM_SIMS_H
|
13
times/base.cpp
Normal file
13
times/base.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
Distribution::Distribution(const double tau, std::mt19937_64 &rng) : m_tau(tau), m_rng(rng) {}
|
||||||
|
|
||||||
|
Distribution::Distribution(std::mt19937_64 &rng) : m_rng(rng) {}
|
||||||
|
|
||||||
|
double Distribution::tau_wait() const {
|
||||||
|
return std::exponential_distribution(1./m_tau)(m_rng);
|
||||||
|
}
|
||||||
|
|
28
times/base.h
Normal file
28
times/base.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RWSIM_TIMESBASE_H
|
||||||
|
#define RWSIM_TIMESBASE_H
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
class Distribution {
|
||||||
|
public:
|
||||||
|
virtual ~Distribution() = default;
|
||||||
|
|
||||||
|
Distribution(double, std::mt19937_64&);
|
||||||
|
explicit Distribution(std::mt19937_64&);
|
||||||
|
|
||||||
|
[[nodiscard]] double getTau() const { return m_tau; }
|
||||||
|
void setTau(const double tau) { m_tau = tau;}
|
||||||
|
|
||||||
|
virtual void draw_tau() = 0;
|
||||||
|
[[nodiscard]] double tau_wait() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_tau{1.};
|
||||||
|
std::mt19937_64& m_rng;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //RWSIM_TIMESBASE_H
|
10
times/delta.cpp
Normal file
10
times/delta.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
#include "delta.h"
|
||||||
|
|
||||||
|
DeltaDistribution::DeltaDistribution(const double tau, std::mt19937_64& rng) : Distribution(tau, rng) {}
|
||||||
|
DeltaDistribution::DeltaDistribution(std::mt19937_64& rng) : Distribution(rng) {}
|
||||||
|
|
||||||
|
void DeltaDistribution::draw_tau() {}
|
||||||
|
|
18
times/delta.h
Normal file
18
times/delta.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Created by dominik on 8/12/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef RWSIM_TIMESDELTA_H
|
||||||
|
#define RWSIM_TIMESDELTA_H
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
class DeltaDistribution final : public Distribution {
|
||||||
|
public:
|
||||||
|
DeltaDistribution(double, std::mt19937_64&);
|
||||||
|
explicit DeltaDistribution(std::mt19937_64 &rng);
|
||||||
|
|
||||||
|
void draw_tau() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //RWSIM_TIMESDELTA_H
|
Loading…
Reference in New Issue
Block a user