source: Sophya/trunk/Cosmo/SimLSS/schechter.cc@ 3322

Last change on this file since 3322 was 3320, checked in by cmv, 18 years ago

intro SchechterMassDist pour accelerer la simulations cmv 05/09/2007

File size: 13.2 KB
RevLine 
[3115]1#include "sopnamsp.h"
2#include "machdefs.h"
3#include <iostream>
4#include <stdlib.h>
5#include <stdio.h>
6#include <string.h>
7#include <math.h>
8
9#include "pexceptions.h"
[3320]10#include "histos.h"
11#include "perandom.h"
12#include "tvector.h"
13#include "fioarr.h"
[3115]14
15#include "constcosmo.h"
[3320]16#include "geneutils.h"
[3115]17#include "schechter.h"
18
19///////////////////////////////////////////////////////////
20//***************** Schechter Functions *****************//
21///////////////////////////////////////////////////////////
22
23// HI mass function:
24// see M.Zwaan astroph-0502257 (MNRAS Letters, Volume 359, Issue 1, pp. L30-L34.)
25// see M.Zwaan astroph-9707109 (ApJ, Volume 509, Issue 2, pp. 687-702.)
26
27Schechter::Schechter(double nstar,double mstar,double alpha)
28 : nstar_(nstar) , mstar_(mstar) , alpha_(alpha) , outvalue_(0)
29{
30}
31
32Schechter::Schechter(Schechter& f)
33 : nstar_(f.nstar_) , mstar_(f.mstar_) , alpha_(f.alpha_) , outvalue_(f.outvalue_)
34{
35}
36
[3320]37Schechter::Schechter(void)
38 : nstar_(0.) , mstar_(0.) , alpha_(0.) , outvalue_(0)
39{
40}
41
[3115]42Schechter::~Schechter(void)
43{
44}
45
46void Schechter::SetOutValue(unsigned short outvalue)
47// outvalue = 0 : give dn/dm
48// = 1 : give m*dn/dm
49{
50 if(outvalue>1) {
51 cout<<"Schechter::SetOutValue: Error bad outvalue: "<<outvalue<<endl;
52 throw ParmError("Schechter::SetOutValue: Error bad outvalue");
53 }
54 outvalue_ = outvalue;
55}
56
[3320]57unsigned short Schechter::GetOutValue(void)
58{
59 return outvalue_;
60}
61
62void Schechter::SetParam(double nstar,double mstar,double alpha)
63{
64 nstar_ = nstar; mstar_ = mstar; alpha_ = alpha;
65}
66
67void Schechter::GetParam(double& nstar,double& mstar,double& alpha)
68{
69 nstar = nstar_; mstar = mstar_; alpha = alpha_;
70}
71
[3115]72double Schechter::operator() (double m)
73// Return : "dn/dm = f(m)" or "m*dn/dm = f(m)"
74{
75 double x = m/mstar_;
76 double dndm = nstar_/mstar_ * pow(x,alpha_) * exp(-x);
77 if(outvalue_) dndm *= m; // on veut m*dn/dm
78 return dndm;
79}
80
[3320]81
82double Schechter::Integrate(double massmin,double massmax,int npt)
83// Integrate from massmin to massmax with at least npt points log10 spaced
84{
85 if(massmin<=0. || massmax<=0. || massmax<=massmin) return 0.;
86 if(npt<1) npt = 100;
87 double lmassmin = log10(massmin), lmassmax = log10(massmax);
88 double perc=0.01, dlxinc=(lmassmax-lmassmin)/npt, dlxmax=10.*dlxinc; unsigned short glorder=4;
89 double sum = IntegrateFuncLog(*this,lmassmin,lmassmax,perc,dlxinc,dlxmax,glorder);
90 return sum;
91}
92
[3193]93void Schechter::Print(void)
94{
95 cout<<"Schechter::Print: nstar="<<nstar_<<" Mpc^-3"
96 <<" mstar="<<mstar_<<" MSol"
97 <<" alpha="<<alpha_
98 <<" (outvalue="<<outvalue_<<" -> return ";
99 if(outvalue_) cout<<"m*dn/dm)"; else cout<<"dn/dm)";
100 cout<<endl;
101}
102
[3115]103///////////////////////////////////////////////////////////
[3320]104//******* Les facilites pour tirer sur Schechter ********//
105///////////////////////////////////////////////////////////
106
107SchechterMassDist::SchechterMassDist(Schechter sch,double massmin,double massmax,int nbinmass)
108// On veut une fonction de tirage aleatoire de la masse de N galaxies sur une Schechter
109// Pour optimiser on cree (eventuellement) des histos de tirage
110// ATTENTION: on donne les limites en masses pour les histos mais leurs abscisses
111// sont en log10(masse): histo [log10(massmin),log10(massmax)] avec nbinmass bins
112// Si nbinmass<0 alors c'est le nombre de points par decade
113 : sch_(sch) , sch_outvalue_(sch.GetOutValue())
114 , massmin_(massmin) , massmax_(massmax) , nbinmass_(nbinmass)
115 , ngalmin_(0) , ngalmax_(0) , nvalngal_(0)
116 , ntrial_dir(0) , ntrial_tab(0)
117 , hmdndm_(NULL) , tirhmdndm_(NULL)
118{
119 if(massmin_>massmax_ || massmin_<=0. || massmax_<=0.|| nbinmass_==0) {
120 cout<<"SchechterMassDist::SchechterMassDist: error in input values"<<endl;
121 throw ParmError("SchechterMassDist::SchechterMassDist: error in input values");
122 }
123
124 // Creation du tirage aleatoire sur la Schechter
125 sch_outvalue_ = sch.GetOutValue(); // on sauve la configuration de la schechter
126 sch.SetOutValue(1); // on veut m*dN/dm
127 double lnx1 = log10(massmin_), lnx2 = log10(massmax_); // Binning en log10 de la masse
128 if(nbinmass_<0) nbinmass_ = int((-nbinmass_)*(lnx2-lnx1+1.));
129 hmdndm_ = new Histo(lnx1,lnx2,nbinmass_); hmdndm_->ReCenterBin();
130 FuncToHisto(sch,*hmdndm_,true); // true -> bin en log10(x)
131 tirhmdndm_ = new FunRan(*hmdndm_,true); // true -> histo est pdf
132 sch.SetOutValue(sch_outvalue_); // on remet a la valeur initiale
133}
134
135SchechterMassDist::SchechterMassDist(void)
136 : sch_outvalue_(0)
137 , massmin_(0.) , massmax_(0.) , nbinmass_(0)
138 , ngalmin_(0) , ngalmax_(0) , nvalngal_(0)
139 , ntrial_dir(0) , ntrial_tab(0)
140 , hmdndm_(NULL) , tirhmdndm_(NULL)
141{
142}
143
144SchechterMassDist::~SchechterMassDist(void)
145{
146 Delete();
147}
148
149void SchechterMassDist::Delete(void)
150{
151 if(hmdndm_) delete hmdndm_;
152 if(tirhmdndm_) delete tirhmdndm_;
153 hmass_.resize(0);
154 tmass_.resize(0);
155 ntrial_dir = ntrial_tab = 0;
156}
157
158int SchechterMassDist::GetMassLim(double& massmin,double& massmax)
159{
160 massmin = massmin_;
161 massmax = massmax_;
162 return nbinmass_;
163}
164
165int SchechterMassDist::SetNgalLim(int ngalmax,int ngalmin,unsigned long nalea)
166// Creation des Histos de tirage pour ngalmin a ngalmax galaxies
167{
168 int lp=2;
169 ngalmin_=ngalmax_=nvalngal_=0;
170 if(ngalmin<=0) ngalmin=1;
171 if(ngalmax<ngalmin || ngalmax==1) return 0;
172 ngalmin_ = ngalmin;
173 ngalmax_ = ngalmax;
174 nvalngal_ = ngalmax-ngalmin+1;
175
176 if(nalea<1) nalea = 100000;
177
178 if(lp>0) cout<<"SchechterMassDist::SetNgalLim: ngal=["
179 <<ngalmin_<<","<<ngalmax_<<"] n="<<nvalngal_
180 <<" filling with "<<nalea<<" trials"<<endl;
181
182 //------- Construct histo
183 double lnx1 = log10(massmin_), lnx2 = log10(massmax_);
184 if(lp>0) cout<<"> Creating "<<nvalngal_<<" histos ["<<lnx1<<","<<lnx2<<"] n="<<nbinmass_<<endl;
185 for(int i=ngalmin_;i<=ngalmax_;i++) {
186 Histo h(*hmdndm_); h.Zero();
187 hmass_.push_back(h);
188 }
189 if(lp>1) cout<<"...number of histos is "<<hmass_.size()<<endl;
190
191 //------- Remplissage random
192 sch_.SetOutValue(1); // on veut m*dN/dm
193 int lpmod = nalea/20; if(lpmod<=0) lpmod=1;
194 double s1=0., sc1=0.; unsigned long ns1=0;
195 double sax=0., scax=0.; unsigned long nsax=0;
196 for(unsigned long ia=0;ia<nalea;ia++) {
197 if(lp>1 && ia%lpmod==0) cout<<"...tirage "<<ia<<endl;
198 double sum = 0.;
199 for(int i=1;i<=ngalmax_;i++) {
200 //double l10m = tirhmdndm_->Random();
201 double l10m = tirhmdndm_->RandomInterp();
202 double m = pow(10.,l10m);
203 sum += m;
204 s1 += m; sc1 += m*m; ns1++;
205 int ipo = i-ngalmin_;
206 if(ipo<0) continue;
207 // ATTENTION: l'histo de tirage stoque le log10(moyenne=somme_masses/ngal).
208 // Ca permet d'avoir le meme binning quelque soit ngal
209 double v = log10(sum/(double)i);
210 hmass_[ipo].Add(v);
211 if(i==ngalmax) {sax += sum/(double)i; scax += sum/(double)i*sum/(double)i; nsax++;}
212 }
213 }
214 sch_.SetOutValue(sch_outvalue_); // on remet a la valeur initiale
215
216 if(ns1>1) {
217 s1 /= ns1; sc1 = sc1/ns1 - s1*s1;
218 cout<<"...Mean mass for ngal=1: "<<s1<<" ("<<log10(fabs(s1))<<")"
219 <<" s="<<sqrt(fabs(sc1))<<" (ntrials "<<ns1<<")"<<endl;
220 }
221 if(nsax>1) {
222 sax /= nsax; scax = scax/nsax - sax*sax;
223 cout<<"...Mean mass for ngal="<<ngalmax_<<": "<<sax<<" ("<<log10(fabs(sax))<<")"
224 <<" s="<<sqrt(fabs(scax))<<" (ntrials "<<nsax<<")"<<endl;
225 }
226
227 //------- Generation des classes de tirage aleatoire et des histos de verif
228 if(lp>0) cout<<"> Creating "<<nvalngal_<<" FunRan"<<endl;
229 for(unsigned int i=0;i<hmass_.size();i++) {
230 FunRan t(hmass_[i],true);
231 tmass_.push_back(t);
232 }
233 if(lp>1) cout<<"...number of funran is "<<tmass_.size()<<endl;
234
235 return nvalngal_;
236}
237
238int SchechterMassDist::GetNgalLim(int& ngalmax,int& ngalmin)
239{
240 ngalmax = ngalmax_;
241 ngalmin = ngalmin_;
242 return nvalngal_;
243}
244
245Histo SchechterMassDist::GetHmDnDm(void) const
246{
247 return *hmdndm_;
248}
249
250FunRan SchechterMassDist::GetTmDnDm(void) const
251{
252 return *tirhmdndm_;
253}
254
255Histo SchechterMassDist::GetHisto(int i) const
256{
257 if(i<0 || i>=nvalngal_) {
258 cout<<"SchechterMassDist::GetHisto: error in input values"<<endl;
259 throw ParmError("SchechterMassDist::GetHisto: error in input values");
260 }
261 return hmass_[i];
262}
263
264FunRan SchechterMassDist::GetFunRan(int i) const
265{
266 if(i<0 || i>=nvalngal_) {
267 cout<<"SchechterMassDist::GetFunRan: error in input values"<<endl;
268 throw ParmError("SchechterMassDist::GetFunRan: error in input values");
269 }
270 return tmass_[i];
271}
272
273double SchechterMassDist::TirMass(int ngal)
274{
275 if(ngal<1) return 0.;
276
277 int ipo = IndexFrNGal(ngal);
278 double masse_des_ngal = 0.;
279 if(ipo<0) { // Pas d'histos de tirage pour ce nombre de galaxies
280 for(long i=0;i<ngal;i++) { // On tire donc ngal fois sur la Schechter
281 // double lm = tirhmdndm_->Random();
282 double lm = tirhmdndm_->RandomInterp();
283 masse_des_ngal += pow(10.,lm); // ATTENTION abscisse en log10(masse)
284 }
285 ntrial_dir++;
286 } else {
287 // ATTENTION l'histo de tirage stoque le log10(moyenne=somme_masses/ngal)
288 //double lmngal = tmass_[ipo].Random();
289 double lmngal = tmass_[ipo].RandomInterp();
290 masse_des_ngal = pow(10.,lmngal) * ngal;
291 ntrial_tab++;
292 }
293
294 return masse_des_ngal;
295}
296
297void SchechterMassDist::Print(void)
298{
299 cout<<"SchechterMassDist::Print: mass=["<<massmin_<<","<<massmax_<<"] n="<<nbinmass_<<endl
300 <<" ngal=["<<ngalmin_<<","<<ngalmax_<<"] n="<<nvalngal_<<endl;
301 sch_.Print();
302}
303
304void SchechterMassDist::PrintStatus(void)
305{
306 cout<<"SchechterMassDist::PrintStatus: number of trials: direct="<<ntrial_dir
307 <<" tabulated="<<ntrial_tab<<endl;
308}
309
310void SchechterMassDist::WritePPF(string ppfname)
311{
312 char str[64];
313 cout<<"SchechterMassDist::WritePPF into "<<ppfname<<endl;
314 POutPersist pos(ppfname.c_str());
315
316 double nstar,mstar,alpha;
317 sch_.GetParam(nstar,mstar,alpha);
318 TVector<r_8> tdum(20); tdum = 0.;
319 tdum(0) = nstar;
320 tdum(1) = mstar;
321 tdum(2) = alpha;
322 tdum(3) = sch_outvalue_;
323 tdum(4) = massmin_;
324 tdum(5) = massmax_;
325 tdum(6) = nbinmass_;
326 tdum(7) = ngalmin_;
327 tdum(8) = ngalmax_;
328 tdum(9) = nvalngal_;
329 tdum(10) = hmass_.size();
330 tdum(11) = tmass_.size();
331 pos << PPFNameTag("SMDparam") << tdum;
332
333 pos << PPFNameTag("SMDhmdndm") << *hmdndm_;
334 pos << PPFNameTag("SMDtirhmdndm") << *tirhmdndm_;
335
336 if(hmass_.size()>0) {
337 for(unsigned int i=0;i<hmass_.size();i++) {
338 sprintf(str,"SMDh%d",NGalFrIndex(i));
339 pos << PPFNameTag(str) << hmass_[i];
340 }
341 }
342
343 if(tmass_.size()>0) {
344 for(unsigned int i=0;i<tmass_.size();i++) {
345 sprintf(str,"SMDt%d",NGalFrIndex(i));
346 Histo hdum(tmass_[i]);
347 pos << PPFNameTag(str) << hdum;
348 }
349 }
350
351}
352
353void SchechterMassDist::ReadPPF(string ppfname)
354{
355 Delete(); // On des-alloue si deja remplit!
356
357 char str[64];
358 cout<<"SchechterMassDist::ReadPPF from "<<ppfname<<endl;
359 PInPersist pis(ppfname.c_str());
360
361 TVector<r_8> tdum;
362 pis >> PPFNameTag("SMDparam") >> tdum;
363 sch_.SetParam(tdum(0),tdum(1),tdum(2));
364 sch_.SetOutValue((unsigned short)(tdum(3)+0.1));
365 massmin_ = tdum(4);
366 massmax_ = tdum(5);
367 nbinmass_ = int(tdum(6)+0.1);
368 ngalmin_ = int(tdum(7)+0.1);
369 ngalmax_ = int(tdum(8)+0.1);
370 nvalngal_ = int(tdum(9)+0.1);
371 unsigned int nhmass = (unsigned int)(tdum(10)+0.1);
372 unsigned int ntmass = (unsigned int)(tdum(11)+0.1);
373
374 {
375 Histo hdum;
376 pis >> PPFNameTag("SMDhmdndm") >> hdum;
377 hmdndm_ = new Histo(hdum);
378 pis >> PPFNameTag("SMDtirhmdndm") >> hdum;
379 tirhmdndm_ = new FunRan(hdum,false);
380 }
381
382 if(nhmass>0) {
383 for(unsigned int i=0;i<nhmass;i++) {
384 sprintf(str,"SMDh%d",NGalFrIndex(i));
385 Histo hdum;
386 pis >> PPFNameTag(str) >> hdum;
387 hmass_.push_back(hdum);
388 }
389 }
390
391 if(ntmass>0) {
392 for(unsigned int i=0;i<ntmass;i++) {
393 sprintf(str,"SMDt%d",NGalFrIndex(i));
394 Histo hdum;
395 pis >> PPFNameTag(str) >> hdum;
396 FunRan fdum(hdum,false);
397 tmass_.push_back(fdum);
398 }
399 }
400
401}
402
403
404///////////////////////////////////////////////////////////
405//***************** Fonctions de Check ******************//
406///////////////////////////////////////////////////////////
407
408bool IsCompatible(Schechter& sch1,Schechter& sch2,double eps)
409// on compare les differences a eps pres
410{
411 if(eps<=0.) eps=1.e-4;
412 double nstar1,mstar1,alpha1;
413 sch1.GetParam(nstar1,mstar1,alpha1);
414 double nstar2,mstar2,alpha2;
415 sch2.GetParam(nstar2,mstar2,alpha2);
416
417 if(fabs(nstar1-nstar2)>fabs(nstar1+nstar2)/2.*eps) return false;
418 if(fabs(mstar1-mstar2)>fabs(mstar1+mstar2)/2.*eps) return false;
419 if(fabs(alpha1-alpha2)>fabs(alpha1+alpha2)/2.*eps) return false;
420 return true;
421}
422
423
424///////////////////////////////////////////////////////////
[3115]425//******************* Le Flux a 21cm ********************//
426///////////////////////////////////////////////////////////
427
[3196]428double Msol2FluxHI(double m,double d)
[3115]429// Input:
430// m : masse de HI en "Msol"
431// d : distance en "Mpc" (si cosmo d=DLum(z))
432// Return:
433// le flux total emis a 21 cm en W/m^2
[3193]434// Ref:
435// -- Binney & Merrifield, Galactic Astronomy p474 (ed:1998)
436// S(W/m^2) = 1e-26 * Nu_21cm(Hz) * m(en masse solaire) /(2.35e5 * C(km/s) * Dlum^2)
437// = 2.0e-28 * m / Dlum^2
438// -- J.Peterson & K.Bandura, astroph-0606104 (eq 7)
439// F.Abdalla & Rawlings, astroph-0411342 (eq 7 mais pb de d'unites?)
440// (A_21cm = 2.86888e-15 s^-1)
441// S(W/m^2) = 3/4 * h(J.s) * Nu_21cm(Hz) * A_21cm(s^-1) * Msol(kg)/m_proton(kg)
442// / (4 Pi) / (Dlum(Mpc) * 3.0857e22(m/Mpc))^2
443// = 2.0e-28 * m / Dlum^2
444//-------------
[3115]445{
[3193]446 return 2.0e-28 * m / (d*d);
[3115]447}
[3196]448
449double FluxHI2Msol(double f,double d)
450// Input:
451// f : flux total emis a 21 cm en W/m^2
452// d : distance en "Mpc" (si cosmo d=DLum(z))
453// Return:
454// m : masse de HI en "Msol"
455{
456 return f *d*d / 2.0e-28;
457}
[3320]458
Note: See TracBrowser for help on using the repository browser.