-
Notifications
You must be signed in to change notification settings - Fork 4
/
random_walk.hpp
132 lines (111 loc) · 3.83 KB
/
random_walk.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <random>
#define SPHERE_RADIUS 100
#define MEAN_FREE_PATH 3
#define SEED 123
#define SET_COL 15
std::vector<double> sample_direction();
double sample_path_length();
class event_log {
// This class stores information about particle collision events. It also
// updates particle radius and location based on sampled collision data.
public:
// store path length
double pl;
// collision location
double x = 0; double y = 0; double z = 0;
// particle direction
double u; double v; double w;
// store particle energy
double E;
std::default_random_engine generator;
// Get particle distance
void get_distance(){ pl = sample_path_length();}
// Get particle direction
void get_direction(){
std::vector<double> direction = sample_direction();
u = direction[0];
v = direction[1];
w = direction[2];
}
// Get particle energy
void get_energy(){
// set normal dist for E sampling
std::normal_distribution<double> normal_dist(5.0,2.0);
E = normal_dist(generator);
}
// calculate particle radius
double radius() {return sqrt(x*x + y*y + z*z);}
// update particle location
void update_location() {
x += pl*u;
y += pl*v;
z += pl*w;
}
// save particle log
void save_log(std::ofstream& logfile){
logfile << std::left << std::setw(SET_COL) << x
<< std::left << std::setw(SET_COL) << y
<< std::left << std::setw(SET_COL) << z
<< std::left << std::setw(SET_COL) << u
<< std::left << std::setw(SET_COL) << v
<< std::left << std::setw(SET_COL) << w
<< std::left << std::setw(SET_COL) << pl
<< std::left << std::setw(SET_COL) << E << "\n";
}
};
double sample_path_length(){
// Sample path length and return distance traveled along the particle
// direction
double rn = static_cast<double>( rand() ) / static_cast<double>(RAND_MAX);
double path_length = -log(1 - rn);
return path_length*MEAN_FREE_PATH;
}
std::vector<double> sample_direction(){
// sample the particle direction in cartesian space, return a direction
// vector, (u, v, w)
double psi = static_cast<double>( rand() ) / static_cast<double>(RAND_MAX);
double eta = static_cast<double>( rand() ) / static_cast<double>(RAND_MAX);
std::vector<double> direction(3);
double pi = 4*atan(1);
double w = 2*psi - 1;
double u = sqrt(1-w*w)*cos(2*pi*eta);
double v = sqrt(1-w*w)*sin(2*pi*eta);
direction[0] = u;
direction[1] = v;
direction[2] = w;
return direction;
}
void walk_particle(std::ofstream& logfile){
// Performs the random walk for each particle
// This function calls the required methods to sample the random-walk
// physics for a single particle. For each path traversed, store the
// starting location, direction, energy, and path-length
// intialize particle
event_log collision;
// set initial energy, distance, direction
collision.get_energy();
collision.get_distance();
collision.get_direction();
// save initial particle pos, energy, direction, distance
collision.save_log(logfile);
// update location for next interaction
collision.update_location();
// run collisions until particle leaves sphere
while (collision.radius() < SPHERE_RADIUS){
// update info, save and calculate new location
collision.get_energy();
collision.get_distance();
collision.get_direction();
collision.save_log(logfile);
collision.update_location();
}
}
void execute_walk(int N){
srand(SEED);
std::ofstream event_history;
event_history.open("event_history.txt");
for (int i=0; i < N; i++){
walk_particle(event_history);
}
event_history.close();
}