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

Last change on this file since 3931 was 3365, checked in by cmv, 18 years ago

1./ grosses modifs de structure pour cmvdefsurv.cc
2./ PoissRandLimit enleve de geneutils.{h,cc} et mis dans srandgen.{h,cc}

cmv 29/10/2007

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