-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathoscillator.cpp
174 lines (153 loc) · 4.79 KB
/
oscillator.cpp
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "oscillator.h"
#include <vector>
#include <random>
//#include <iostream>
//using namespace std::complex_literals;
Distribution::Distribution(DistName name, double mean, double param) : _name{name}, _mean{mean}, _param{param} {
if (param == 998) {
switch (name) {
case DistName::Lorentz:
param = 0.5;
break;
case DistName::Gauss:
param = 1;
break;
case DistName::Boltzmann:
param = 2;
break;
}
}
if (name == DistName::Lorentz && param < 0)
param = -param;
}
double Distribution::evaluate(double freq) {
switch (_name) {
case DistName::Lorentz:
return _param / ( M_PI* (_param*_param + (freq-_mean)*(freq-_mean)) );
case DistName::Gauss:
return std::exp( (freq-_mean)*(freq-_mean) / (-2*_param)) / sqrt(2*M_PI*_param);
case DistName::Boltzmann:
return std::exp(-freq/_param);
case DistName::Exp:
return std::exp(-freq/_mean) / _mean;
}
return -1;
}
double Distribution::max() {
switch (_name) {
case DistName::Lorentz:
case DistName::Gauss:
return evaluate(_mean);
case DistName::Boltzmann:
case DistName::Exp:
return evaluate(0);
}
return -1;
}
std::string Distribution::toString() {
std::string result;
switch (_name) {
case DistName::Lorentz:
result = "Lorentz";
break;
case DistName::Gauss:
result = "Gauss";
break;
case DistName::Boltzmann:
result = "Boltzmann";
break;
case DistName::Exp:
result = "Exp";
break;
}
result += ',' + std::to_string(_mean) + ',' + std::to_string(_param);
return result;
}
/*
double lorentz_g(double freq, double mean, double gamma){
if(gamma < 0) { gamma = -gamma; }
if(gamma > 1) {
if (gamma != 998)
std::cout<< "Setting gamma > 1 will flatten the Loretzian density"<<'\n';
gamma = 0.5; //ho visto che in varie simulazioni online usavano 0.5 per gamma
}
return gamma/ ( M_PI*(gamma*gamma + (freq-mean)*(freq-mean)) );
}
double gauss_g(double freq, double mean, double sigma){
if (sigma == 998)
sigma = 1;
double c = 1/sqrt(2*M_PI*sigma);
return c*std::exp( (freq-mean)*(freq-mean) / (-2*sigma));
}
//Non ho capito bene che distribuzione sarebbe. Mi servirebbe poi un modo per calcolare la media, in analogia con le altre distribuzioni
/*
*è la distribuzione di maxwell boltzmann, quella del microcanonico in fisica della materia: ti dice che le frequenze
*sono maggiormente distribuite vicino a Omega (che sarebbe la frequenza media caratteristica del sistema) e la
*probabilità di avere freq>Omega diminuisce esponenzialmente. La media è Omega^2. Problema che ho realizzato dopo avere scritto tutto: non è simmetrica
*rispetto all'origine, quindi succederà un macello? da vedere
double boltzmann_g(double freq, double Omega){ //Maxwell-Boltzmann distribution, frequency has the same interpretation as Energy
if (Omega == 998)
Omega = 2; //Qualcosa di accettabile
return std::exp(-freq/Omega);
}
double exp_g(double freq, double mean) { //questa che sarebbe? //Sarebbe un'esponenziale decrescente. L'ho messa così a caso
return std::exp(-freq/mean) / mean;
}*/
Oscillator::Oscillator(Distribution dist, sf::Vector2f position) : _position{position} {
//generate random frequency according to the selected distribution
double randomX;
double randomY;
std::random_device seed;
std::uniform_real_distribution<double> xDist(-4,4);
std::uniform_real_distribution<double> yDist(0, dist.max());
do {
randomX = xDist(seed);
randomY = yDist(seed);
} while (randomY > dist.evaluate(randomX));
_freq = randomX;
//generate random phase
std::random_device seedPhase;
std::uniform_real_distribution<double> phaseDist(0, 2*M_PI);
_phase = phaseDist(seedPhase);
}
Oscillator::Oscillator(double freq, sf::Vector2f position) : _freq{freq}, _position{position} {
//generate phase randomly
std::random_device seed;
std::uniform_real_distribution<double> phaseDist(0, 2*M_PI);
_phase = phaseDist(seed);
}
void Oscillator::setPhase(double phase) {
while (phase < 0) {
phase += 2 * M_PI;
}
while (phase >= 2*M_PI) {
phase -= 2 * M_PI;
}
_phase = phase;
}
void Oscillator::update(double dt) {
setPhase(_phase + _freq*2*M_PI*dt); //equals to _phase += _freq*dt + normalize.
}
std::string toString(double num) {
if (num == -1)
return "[random]";
return std::to_string(num);
}
std::string literal(bool b) {
if (b)
return "True";
return "False";
}
/*
std::ostream& operator<<(std::ostream& os, const sf::Vector2f& vector) {
os << '(' << vector.x << ", " << vector.y << ')';
return os;
}
std::ostream& operator<<(std::ostream& os, const sf::Vector2u& vector) {
os << '(' << vector.x << ", " << vector.y << ')';
return os;
}
bool operator>=(sf::Vector2f& lhs, sf::Vector2f& rhs) {
return lhs.x >= rhs.x || lhs.y >= rhs.y;
}
*/