44
44
PageThorneDisk::PageThorneDisk() :
45
45
ThinDisk("PageThorneDisk"), aa_(0.), aa2_(0.),
46
x0_(0.), x1_(0.), x2_(0.), x3_(0.), rednoise_(0),
46
x0_(0.), x1_(0.), x2_(0.), x3_(0.), blackbody_(0), mdot_(0),
47
uniflux_(0), spectrumBB_(NULL)
49
49
if (debug()) cerr << "DEBUG: PageThorneDisk Construction" << endl;
50
spectrumBB_ = new Spectrum::BlackBody();
52
53
PageThorneDisk::PageThorneDisk(const PageThorneDisk& o) :
53
54
ThinDisk(o), aa_(o.aa_), aa2_(o.aa2_),
54
55
x0_(o.x0_), x1_(o.x1_), x2_(o.x2_), x3_(o.x3_),
55
rednoise_(o.rednoise_), uniflux_(o.uniflux_)
56
blackbody_(o.blackbody_), mdot_(0), uniflux_(o.uniflux_),
59
if (o.spectrumBB_()) spectrumBB_=o.spectrumBB_->clone();
57
60
if (o.gg_()) gg_=o.gg_->clone();
69
72
void PageThorneDisk::updateSpin() {
71
switch (gg_->getCoordKind()) {
74
switch (gg_->coordKind()) {
72
75
case GYOTO_COORDKIND_SPHERICAL:
73
aa_ = static_cast<SmartPointer<Metric::KerrBL> >(gg_) -> getSpin();
76
aa_ = static_cast<SmartPointer<Metric::KerrBL> >(gg_) -> spin();
75
78
case GYOTO_COORDKIND_CARTESIAN:
76
aa_ = static_cast<SmartPointer<Metric::KerrKS> >(gg_) -> getSpin();
79
aa_ = static_cast<SmartPointer<Metric::KerrKS> >(gg_) -> spin();
79
82
throwError("PageThorneDisk::getSpin(): unknown COORDKIND");
88
91
x2_ = 2.*cos(acosaao3 + M_PI/3.);
89
92
x3_ = -2.*cos(acosaao3);
91
rin_=(3.+z2-sqrt((3.-z1)*(3.+z1+2.*z2)));
94
if (rin_==0.) rin_=(3.+z2-sqrt((3.-z1)*(3.+z1+2.*z2)));
94
void PageThorneDisk::setMetric(SmartPointer<Metric::Generic> gg) {
97
void PageThorneDisk::metric(SmartPointer<Metric::Generic> gg) {
95
98
if (gg_) gg_->unhook(this);
96
string kind = gg->getKind();
97
if (kind != "KerrBL" && kind != "KerrKS" && kind != "ChernSimons")
99
string kin = gg->kind();
100
if (kin != "KerrBL" && kin != "KerrKS" && kin != "ChernSimons")
99
("PageThorneDisk::setMetric(): metric must be KerrBL or KerrKS");
100
ThinDisk::setMetric(gg);
102
("PageThorneDisk::metric(): metric must be KerrBL or KerrKS");
103
ThinDisk::metric(gg);
105
108
double PageThorneDisk::emission(double nu_em, double dsem,
107
110
double coord_obj[8]) const{
108
throwError("not implemented");
112
throwError("In PageThorneDisk::emission: "
113
"blackbody is necessary to compute emission, "
114
"else, use bolometricEmission");
117
double Ibolo=bolometricEmission(nu_em,dsem,coord_obj);
119
From Ibolo, find T, then Bnu(T)
121
double mass=gg_->mass()*1e3; // in cgs
122
double c6=GYOTO_C_CGS*GYOTO_C_CGS*GYOTO_C_CGS
123
*GYOTO_C_CGS*GYOTO_C_CGS*GYOTO_C_CGS;
124
double g2m2=GYOTO_G_CGS*GYOTO_G_CGS*mass*mass;
125
Ibolo*=mdot_*c6/g2m2; // Ibolo in cgs
126
//F = sigma * T^4 (and F=pi*I)
127
double TT=pow(Ibolo*M_PI/GYOTO_STEFANBOLTZMANN_CGS,0.25);
128
spectrumBB_->temperature(TT);
129
double Iem=(*spectrumBB_)(nu_em);
130
//cout << "r T nu Iem = " << coord_obj[1] << " " << TT << " " << nu_em << " " << Iem << endl;
131
if (Iem < 0.) throwError("In PageThorneDisk::emission"
132
" blackbody emission is negative!");
111
136
Quantity_t PageThorneDisk::getDefaultQuantities() {
112
137
return GYOTO_QUANTITY_USER4;
115
double PageThorneDisk::bolometricEmission(double dsem,
140
double PageThorneDisk::bolometricEmission(double /* nuem */, double dsem,
116
141
double coord_obj[8]) const{
117
142
//See Page & Thorne 74 Eqs. 11b, 14, 15. This is F(r).
118
143
// Important remark: this emision function gives I(r),
119
144
// not I_nu(r). And I(r)/nu^4 is conserved.
120
145
// cout << "r hit= " << coord_obj[1] << endl;
121
146
if (uniflux_) return 1;
124
switch (gg_->getCoordKind()) {
148
switch (gg_->coordKind()) {
125
149
case GYOTO_COORDKIND_SPHERICAL:
126
150
xx=sqrt(coord_obj[1]);
163
187
if (flag_radtransf_) Iem *= dsem;
164
188
GYOTO_DEBUG_EXPR(Iem);
167
double rr=coord_obj[1],
170
cst_aa=0.1*sqrt(6), // amplitude cst
171
cst_tt=1.; // period cst
173
double random = double(rand() % 100)/100. ;
174
Iem*=1.+cst_aa*random*pow(rr,-0.5)*sin(cst_tt*1./r32*tt);
175
if (Iem < 0.) throwError("In PageThorneDisk::bolometricEmission"
176
" rednoised emission is negative!");
194
205
(see below) ; this freqObs is used to transform the null
195
206
worldline parameter dlambda (see below)
197
double freqObs=ph->getFreqObs(); // this is a useless quantity, always 1
208
double freqObs=ph->freqObs(); // this is a useless quantity, always 1
209
SmartPointer<Spectrometer::Generic> spr = ph -> spectrometer();
210
size_t nbnuobs = spr() ? spr -> nSamples() : 0 ;
211
double const * const nuobs = nbnuobs ? spr -> getMidpoints() : NULL;
198
212
double dlambda = dt/coord_ph_hit[4]; //dlambda = dt/tdot
199
213
double ggredm1 = -gg_->ScalarProd(coord_ph_hit,coord_obj_hit+4,
200
214
coord_ph_hit+4);// / 1.;
232
246
<< ") = " << dlambda << ", dsem=" << dsem << endl;
234
248
if (data->intensity) throwError("unimplemented");
235
else if (data->user4) {
236
inc = (bolometricEmission(dsem, coord_obj_hit))
250
inc = (bolometricEmission(freqObs*ggredm1, dsem, coord_obj_hit))
237
251
* (ph -> getTransmission(size_t(-1)))
238
252
* ggred*ggred*ggred*ggred; // I/nu^4 invariant
239
253
*data->user4 += inc;
245
259
if (data->binspectrum) throwError("unimplemented");
246
if (data->spectrum) throwError("unimplemented");
260
if (data->spectrum) {
262
throwError("In PageThorneDisk::process: "
263
"blackbody is necessary to compute spectrum");
265
for (size_t ii=0; ii<nbnuobs; ++ii) {
266
double nuem=nuobs[ii]*ggredm1;
268
inc = (emission(nuem, dsem, tmp, coord_obj_hit))
269
* (ph -> getTransmission(size_t(-1)))
270
* ggred*ggred*ggred; // Inu/nu^3 invariant
271
data->spectrum[ii*data->offset] += inc;
272
//cout << "in spec stored= " << ggred << " " << inc << endl;
247
275
/* update photon's transmission */
248
276
ph -> transmit(size_t(-1),
249
277
transmission(freqObs*ggredm1, dsem,coord_ph_hit));
257
285
void PageThorneDisk::tell(Hook::Teller* msg) {
286
if (msg==gg_) updateSpin();
261
289
int PageThorneDisk::setParameter(std::string name,
262
290
std::string content,
263
291
std::string unit) {
264
292
char* tc = const_cast<char*>(content.c_str());
265
if (name=="RedNoise") rednoise_=1;
293
if (name=="BlackbodyMdot") {
266
297
if (name=="UniFlux") uniflux_=1;
267
298
else return ThinDisk::setParameter(name, content, unit);