-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchevalier.cpp
246 lines (202 loc) · 5.4 KB
/
chevalier.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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#include "chevalier.hpp"
gsl_root_fsolver *grsolve;
const gsl_root_fsolver_type *grsolve_T;
Chevalier::Chevalier(void)
{
//constant
parsec_in_cm = 3.085678e+18; //parsec in cm
parsec_in_km = 3.085678e+13; //parsec in km
msun_in_g = 1.988920e+33; //msun in g
year_in_sec = 3.155760e+07; //year in s
//define the GSL root solver to use
grsolve_T = gsl_root_fsolver_brent;
grsolve = gsl_root_fsolver_alloc(grsolve_T);
//set a default model
double M_dot_in = 1.0; //Mass input in Msun/yr
double E_dot_in = 43.0; //log E in erg / s
double gamma_in = 5./3.; //gamma = 5/3
double R_in = 200.; //parsec
//set the mode parameters
SetChevalier(M_dot_in, E_dot_in, gamma_in, R_in);
}
void Chevalier::SetChevalier(double M_dot_in, double E_dot_in, double gamma_in, double R_in)
{
//set model parameters
M_dot = M_dot_in;
E_dot = pow(10.,E_dot_in);
gamma = gamma_in;
R = R_in;
V = (4.*M_PI/3. * R*R*R); //volume in pc^3
//compute input density rate
q = M_dot / V; //msun / yr / pc^3
//compute input energy density rate
//msun/yr (km/s)^2 / pc^3
Q = (E_dot/msun_in_g*year_in_sec / 1.0e10) / V;
}
double Chevalier::u_star(double r)
{
double u = WindVelocity(r);
double u_prime = sqrt(E_dot)/sqrt(M_dot*msun_in_g/year_in_sec)/1.0e5;
//dimensionless wind velocity
return u/u_prime;
}
double Chevalier::rho_star(double r)
{
double rho = Density(r); //g cm^-3
double M_dot_prime = M_dot * msun_in_g/year_in_sec; // g/s
double R_prime = R * parsec_in_cm; //cm
double rho_prime = pow(M_dot_prime,1.5)/(sqrt(E_dot)*R_prime*R_prime);
//dimensionless density
return rho/rho_prime;
}
double Chevalier::P_star(double r)
{
double P = Pressure(r); //dyn cm^-2
double M_dot_prime = M_dot * msun_in_g/year_in_sec; // g/s
double R_prime = R * parsec_in_cm; //cm
double P_prime = sqrt(M_dot_prime)*sqrt(E_dot)/(R_prime*R_prime);
//dimensionless pressure
return P/P_prime;
}
double Chevalier::Pressure(double r)
{
//pressure in dyn cm^-2
double P;
double Mach = MachNumber(r); //mach number
double u = WindVelocity(r); //km/s
double c = u/Mach * 1.0e5; //sound speed in cm/s
u *= year_in_sec / parsec_in_km; //to pc/yr
double rho = MomentumDensity(r)/u; //Msun / pc^3
rho *= msun_in_g; //g / pc^3
rho /= pow(parsec_in_cm, 3); //g / cm^3
P = c*c*rho/gamma; //pressure in cgs
return P; //in dyn cm^-2
}
double Chevalier::Density(double r)
{
//density in g cm^-3
double rho;
double u = WindVelocity(r); //km/s
u *= year_in_sec / parsec_in_km; //to pc/yr
rho = MomentumDensity(r)/u; //Msun/pc^3
rho *= msun_in_g; //g / pc^3
rho /= pow(parsec_in_cm, 3); //g / cm^3
return rho; // density in g/cm^3
}
double Chevalier::WindVelocity(double r)
{
//wind velocity in km/s
//depends only on ration Qint/rhou
//doesn't know about geometry
double Qint; //msun/yr (km/s)^2 / pc^3
double rhou; //momentum density in msun/pc^3 *km/s
double Mach; //Mach number
double usq;
double fac;
//First, find integrated energy input density
Qint = EnergyIntegral(r); //msun/yr (km/s)^2 / pc^3
//Second, find momentum density
rhou = MomentumDensity(r); //msun/yr/pc^2
//find sq of velocity (modulo gamma + Mach correction)
usq = Qint/rhou; //1/2 u^2 + (gamma/(gamma-1))*P/rho
//1/2 u^2 + c^2 / (gamma-1)
//1/2 u^2 + u^2 / (M^2 (gamma-1))
//u^2 * ( 1/2 + 1/(M^2 (gamma-1)) )
//get the mach number
Mach = MachNumber(r);
//find the adjustment factor
fac = (0.5 + 1./(Mach*Mach*(gamma-1.)));
usq /= fac;
//return the wind velocity
return sqrt(usq); //km/s
}
double Chevalier::EnergyIntegral(double r)
{
double Qint;
if(r<R)
{
Qint = 1.0/3.*Q*r;
}else{
Qint = 1.0/3.*Q*R*R*R/(r*r);
}
//msun/yr (km/s)^2 / pc^3
return Qint;
}
double Chevalier::MomentumDensity(double r)
{
double rhou;
if(r<R)
{
rhou = 1.0/3.*q*r;
}else{
rhou = 1.0/3.*q*R*R*R/(r*r);
}
//rhou is in Msun/yr/pc^2
return rhou;
}
double Chevalier::MachNumber(double r)
{
double Mx;
double x = r/R;
gsl_function func;
int status;
int iter = 0;
int max_iter = 100;
double M_lo = 1.0e-5;
double M_hi = 5.;
double answer;
double fp[2];
fp[0] = gamma;
fp[1] = x;
//choose which solution to use
if(x<=1.0)
{
M_lo = 1.0e-5;
M_hi = 1.0;
func.function = &mach_crossing_A;
}else{
M_lo = 1.0;
M_hi = 100.0;
func.function = &mach_crossing_B;
}
func.params = &fp[0];
gsl_root_fsolver_set(grsolve, &func, M_lo, M_hi);
do{
iter++;
status = gsl_root_fsolver_iterate(grsolve);
Mx = gsl_root_fsolver_root(grsolve);
M_lo = gsl_root_fsolver_x_lower(grsolve);
M_hi = gsl_root_fsolver_x_upper(grsolve);
status = gsl_root_test_interval(M_lo,M_hi,0,1.0e-5);
if(status==GSL_SUCCESS)
{
answer = Mx;
}
}
while(status==GSL_CONTINUE && iter<max_iter);
//return the answer
return answer;
}
double mach_crossing_A(double M, void *fp)
{
double *g = (double *) fp;
double gamma = g[0];
double x = g[1];
double alpha = -1.*(3.*gamma+1.)/(5.*gamma+1.);
double beta = (gamma+1.)/(2.*(5.*gamma+1.));
double A = pow( (3.*gamma + 1./(M*M))/(1.+3.*gamma), alpha);
double B = pow( (gamma-1.+2./(M*M))/(1.+gamma), beta);
double answer = A*B - x;
return answer;
}
double mach_crossing_B(double M, void *fp)
{
double *g = (double *) fp;
double gamma = g[0];
double x = g[1];
double alpha = 2./(gamma-1.);
double beta = (gamma+1.)/(2.*(gamma-1.));
double A = pow( M, alpha);
double B = pow( (gamma-1.+2./(M*M))/(1.+gamma), beta);
return A*B - x*x;
}