source: JEM-EUSO/esaf_lal/tags/v1_r0/esaf/packages/simulation/radiativetransfer/src/O2_ClearSkyPropagator.cc @ 117

Last change on this file since 117 was 117, checked in by moretto, 11 years ago

ESAF version compilable on mac OS

File size: 15.8 KB
Line 
1// ESAF : Euso Simulation and Analysis Framework
2// $Id: O2_ClearSkyPropagator.cc 2767 2006-11-15 15:50:14Z moreggia $
3// Sylvain Moreggia created Jun,  2 2004
4
5#include "O2_ClearSkyPropagator.hh"
6#include "SinglePhoton.hh"
7#include "BunchOfPhotons.hh"
8#include <math.h>
9#include "EsafRandom.hh"
10#include "ListPhotonsInAtmosphere.hh"
11#include "Config.hh"
12#include "EsafSpectrum.hh"
13#include "RadiativeFactory.hh"
14#include "EConst.hh"
15#include "Atmosphere.hh"
16#include "Clouds.hh"
17#include "LowtranRadiativeProcessesCalculator.hh"
18#include "TestGround.hh"
19#include "TBenchmark.h"
20
21ClassImp(O2_ClearSkyPropagator)
22
23using namespace sou;
24using namespace EConst;
25
26//_____________________________________________________________________________
27O2_ClearSkyPropagator::O2_ClearSkyPropagator() : ClearSkyPropagator() {
28    //
29    // ctor (should not be used)
30    //
31    fOrder = 2;
32    fFinal_medium = NONE;
33}
34
35//_____________________________________________________________________________
36O2_ClearSkyPropagator::O2_ClearSkyPropagator(const Ground* g) : ClearSkyPropagator(g) {
37    //
38    // ctor, copy RadiatvieTransfer ground description
39    //
40    fOrder = 2;
41    fFinal_medium = NONE;
42    fNbSinglesCorrected = 0;
43   
44    ConfigFileParser *pConfig = Config::Get()->GetCF("Atmosphere", "LowtranAtmosphere");
45    fAerosolModel = (Int_t)pConfig->GetNum("LowtranAtmosphere.Ihaze");
46   
47    // if model is outside (0,1,2,4,5), it is not used for scattering simulation : ratio aborption / scattering is currently not known by me
48    if(fAerosolModel != 0 && fAerosolModel != 1 && fAerosolModel != 2 && fAerosolModel != 4 && fAerosolModel != 5) {
49        fAerosolModel = 0;
50        Msg(EsafMsg::Warning) <<"Aerosol model is such that scattering simu cannot be done using BUNCH algorithm" << MsgDispatch;
51        Msg(EsafMsg::Warning) <<"Aerosol model will be used only for last transmission to detector" << MsgDispatch;
52    }
53    // Aerosol case : absorption / extinction ratio treated in a simple way (cause detailled treatment not supported by the current interface with LOWTRAN)
54    // rural    : 95 % scattering, ~independent of wavelength
55    // urban    : 70 % scattering, ~independent of wavelength
56    // maritime : 98 % scattering, ~independent of wavelength
57    if(fAerosolModel == 0)      fAerosol_correction_factor = 0.;
58    else if(fAerosolModel == 1) fAerosol_correction_factor = 0.95;
59    else if(fAerosolModel == 2) fAerosol_correction_factor = 0.95;
60    else if(fAerosolModel == 4) fAerosol_correction_factor = 0.98;
61    else if(fAerosolModel == 5) fAerosol_correction_factor = 0.70;
62}
63
64//_____________________________________________________________________________
65O2_ClearSkyPropagator::~O2_ClearSkyPropagator() {
66    //
67    // dtor
68    //
69}
70
71//_____________________________________________________________________________
72Medium O2_ClearSkyPropagator::Go(BunchOfPhotons& bunch,ListPhotonsInAtmosphere& list) const {
73    //
74    // call methods for propagation
75    // NB: bunch can be modified, its copy b cannot
76    //
77   
78    // to assess backscattering algorithm time consumption
79    #ifdef DEBUG
80    char prt[100];
81    sprintf(prt,"Bunch order2 propagation");
82    TBenchmark bench;
83    bench.Start(prt);
84    #endif
85   
86    // initializations
87    static UInt_t bunch_id = 0; // to know if bunch has already come here (for clouds etc..)
88    Medium rtn = NONE;
89    const BunchOfPhotons& b = bunch;
90    EarthVector impact;
91   
92    // if fluo, not propagated  //TOFIX: fluo propagation should be handled in the future
93    if(b.GetType() == Fluo) {
94        bunch.SetFate(1);
95        return NONE;
96    }
97       
98    // if first treatment for this bunch,
99    // get next impact and next medium encountered
100    //TOFIX : valid algorithm if a SINGLE intermediate medium exists
101    if(bunch_id != b.GetId()) {
102        // bunch preprocessing -> generate a lowtran table along the bunch track
103        BunchPreProcess(bunch);
104        if(fFinal_medium == NONE) return NONE;
105        bunch_id = b.GetId();
106        rtn = GetNextImpact(b,impact);
107        bunch.SetNextImpact(impact);
108        if(impact.Z() == HUGE) Msg(EsafMsg::Warning) << "Bunches should always have an \"impact\"" << MsgDispatch;
109        if(b.GetFinalImpact().Z() == HUGE) Msg(EsafMsg::Warning) << "Bunches should always have an \"impact\"" << MsgDispatch;
110        // if no intermediate medium, go to final impact
111        if((b.GetNextImpact() - b.GetFinalImpact()).Mag() == 0) rtn = fFinal_medium;
112    }
113    // otherwise go to final impact
114    else {
115        bunch.SetNextImpact(b.GetFinalImpact());
116        rtn = fFinal_medium;
117    }
118   
119    // if bunch showerpos is within clouds, switch off the present clear sky propagation
120    if(rtn == CLOUDY && (b.GetNextImpact() - b.GetPos()).Mag() < TOLERANCE) {
121        return rtn;
122    }
123
124    // run propagation algorithms
125    Propagate(bunch,list);
126
127    #ifdef DEBUG
128    bench.Stop(prt);
129    MsgForm(EsafMsg::Debug,"REAL=%6.2f s   CPU=%6.2f s",bench.GetRealTime(prt),bench.GetCpuTime(prt)); 
130    #endif
131   
132    if(rtn == GROUND) bunch.SetFate(4);
133    // in the case impact is out of FoV, rtn set to NONE to stop the propagation (no ground reflexion)
134    if(rtn == CLEARSKY) {
135        rtn = NONE;
136        bunch.SetFate(5);
137    }
138
139    return rtn;
140}
141
142//_____________________________________________________________________________
143void O2_ClearSkyPropagator::Propagate(BunchOfPhotons& bunch,ListPhotonsInAtmosphere& list) const {
144    //
145    // Propagate a BunchOfPhotons in clear sky conditions,
146    // generating SinglePhotons all along the travel -> ListPhotonsInAtmosphere filled
147    // NB: bunch can be modified, its copy b cannot
148    //
149   
150    Int_t status = -100;  // for Atmosphere::InvertGrammage() method
151    const BunchOfPhotons& b = bunch;
152    const EarthVector& impact = b.GetNextImpact();
153    const Atmosphere* atmo = Atmosphere::Get();
154    // initializations
155    Double_t conv = 1.;
156    Int_t nb = b.GetWlSpectrum().GetAxis().GetNbins();
157    vector<Double_t*> coeff;
158    Double_t* TotalTrans = new Double_t[nb];
159    Double_t* RayleighTrans = new Double_t[nb];
160    Double_t* OzoneTrans = new Double_t[nb];
161    Double_t* AerosolTrans = new Double_t[nb];
162    if(!TotalTrans) Msg(EsafMsg::Panic) << "Pb of memory allocation for TotalTrans" << MsgDispatch;
163    if(!RayleighTrans) Msg(EsafMsg::Panic) << "Pb of memory allocation for RayleighTrans" << MsgDispatch;
164    if(!OzoneTrans) Msg(EsafMsg::Panic) << "Pb of memory allocation for OzoneTrans" << MsgDispatch;
165    if(!AerosolTrans) Msg(EsafMsg::Panic) << "Pb of memory allocation for AerosolTrans" << MsgDispatch;
166    coeff.push_back(TotalTrans);
167    coeff.push_back(RayleighTrans);
168    coeff.push_back(OzoneTrans);
169    coeff.push_back(AerosolTrans);
170    Double_t raylScat = 0;
171    Double_t phfunc = 0;
172    Int_t NbRaylBackscat = 0;
173    EarthVector pos, step, entry, exit, dir;
174    Double_t depthstep = Conf()->GetNum("BunchRadiativeTransfer.DepthStep")*g/cm2;
175   
176    entry = b.GetPos() - 0.5*(b.GetParent()->GetShowerPosf() - b.GetParent()->GetShowerPosi());
177    dir = (impact - entry).Unit();
178    status = atmo->InvertGrammage(entry,dir,depthstep,exit);
179   
180#ifdef DEBUG
181    // to get nb of iteration for propagation of this bunch
182    Float_t count = 0;
183#endif
184   
185    while((impact - b.GetPos()).Mag() > TOLERANCE) {
186#ifdef DEBUG
187        count++;
188#endif
189        step = exit - entry;
190        if((impact - b.GetPos()).Mag() < step.Mag()) step = impact - b.GetPos();
191        fCalcul->Trans(b,b.GetPos()+step,coeff);
192        phfunc = fCalcul->RayleighPhaseFunction(b.GetDir(),EUSO() - b.GetPos() - 0.5*step);
193       
194        // position and time of flight incrementation (bunch position is at the step end)
195        bunch.AddToPosTof(step);
196       
197        // cerenkov backscattering (only rayleigh so far) //TOFIX
198        for(Int_t i=0; i<nb; i++) {
199            raylScat = (1 - coeff[1][i]);
200            NbRaylBackscat  = EsafRandom::Get()->Poisson(b.GetWeight(i) * EusoOmega(b.GetPos() - 0.5*step) * raylScat*phfunc);
201            // Singles generation (bunch pos at step end) -- aerosols-ozone absorption also taken into account there
202            if(NbRaylBackscat) GenerateRayleighSingles(i,NbRaylBackscat,raylScat,step,b,list,coeff[3][i],coeff[2][i]);
203        }
204        // convolutions with transmission coefficients
205        conv = bunch.ConvoluteWl(coeff[0]);
206        bunch.Convolute(conv);
207        entry = exit;
208        status = atmo->InvertGrammage(entry,dir,depthstep,exit);
209    }
210    // to have position precisely, for later processes
211    bunch.SetPos(impact);
212   
213#ifdef DEBUG
214    Msg(EsafMsg::Debug) <<"Nb iteration = " <<count << MsgDispatch;
215    Msg(EsafMsg::Debug) <<"after backscat, SinglePhoton list size = "<<list.GetListOfSingle().size() << MsgDispatch;
216#endif
217
218    // cleaning of coeff
219    for(UInt_t m=0; m<coeff.size(); m++) {
220        if(coeff[m]) delete[] coeff[m];
221        coeff[m] = 0;
222    }
223    coeff.clear();
224}
225
226//_____________________________________________________________________________
227void O2_ClearSkyPropagator::GenerateRayleighSingles(Int_t specbin, Int_t nb, Double_t scattrate, const EarthVector& step,
228                                            const BunchOfPhotons& b, ListPhotonsInAtmosphere& list, Double_t Ta,Double_t To) const {
229    //
230    // Generate a SinglePhoton list, coming from Rayleigh scattering process applied to the given BunchOfPhotons
231    // Tuning of scattering position done thanks to additional data : scattrate (rate of scattering),
232    // step (step used for backscattering calculations)
233    // NB : bunch position is at the end of the considered propagation step
234    //
235
236    Double_t wl, date, tof, scatlength;
237    EarthVector showerpos, pos, dir, diff;
238    SinglePhoton* s = 0;
239    TRandom* rndm = EsafRandom::Get();
240   
241    UInt_t bid = b.GetId();
242    PhotonType type = b.GetType();
243   
244    for(Int_t i=0; i<nb; i++) {
245        // corrections for date and showerpos, from BunchOfPhotons mean values, longitudinal and lateral distributions at creation
246        showerpos = b.RandomPosInShower();
247        if(fGround->IsUnderGround(showerpos)) continue;
248        diff = showerpos - b.GetShowerPos();
249        date = b.GetDate() + diff.Dot(b.GetDir().Unit())/Clight();
250       
251        // calculation of the scattering position within the step
252        pos = b.GetPos() - step;    // as if bunch was at the beginning of the step
253        scatlength = (log(1 - rndm->Rndm()*scattrate)/log(1 - scattrate));
254        pos += scatlength *step;
255       
256        // tell if this photon has been really transmitted until the rayleigh scat position (ozone - aerosols)
257        // if not  ->  photon is killed
258        if(rndm->Rndm() > exp(scatlength*log(Ta))) continue;
259        if(rndm->Rndm() > exp(scatlength*log(To))) continue;
260       
261        // position correction, due to angular distributions at creation
262        pos = b.PosRandomAngCorrec(showerpos,pos);
263       
264        // if underground, photon is kept for another try
265        if(fGround->IsUnderGround(pos)) {
266            EarthVector axis, impact;
267            impact = b.GetNextImpact();
268            if(impact.Z() == HUGE) {
269                Msg(EsafMsg::Warning) <<"\nno bunch impact, but singles underground" <<MsgDispatch;
270                continue;
271            }
272            else {
273                EarthVector localvertical(impact);
274                localvertical(2) += EarthRadius();
275                axis = localvertical.Cross(b.GetDir());
276                if(axis.Mag()) {    // if localvertical and bunch dir not colinear
277                    EarthVector v1 = pos - impact;
278                    v1.Rotate(TMath::Pi(),axis);
279                    pos = v1 + impact;
280                }
281                else Msg(EsafMsg::Warning) <<"<GenerateSingles> OK if vertical track" <<MsgDispatch;
282                if(fGround->IsUnderGround(pos)) {
283                    Msg(EsafMsg::Warning) <<"GenerateSingles() -> pos is still underground" <<MsgDispatch;
284                    continue;
285                }
286                fNbSinglesCorrected++;
287            }
288        }
289        tof = b.GetTof() * (showerpos - pos).Mag()/(b.GetPos() - b.GetShowerPos()).Mag();
290        dir = EUSO() - pos;
291        wl = b.GetWlSpectrum().GetLambda(specbin);
292        s = new SinglePhoton(type,date,tof,wl,showerpos,pos,dir,RaylScat,bid,b.GetShowerAge());
293        s->AddInteraction();
294        s->AddHistory(RaylScat);
295        list.Add(s);
296    } 
297}
298
299//_____________________________________________________________________________
300void O2_ClearSkyPropagator::GenerateAerosolSingles(Int_t specbin, Int_t nb, Double_t scattrate, const EarthVector& step,
301                                            const BunchOfPhotons& b, ListPhotonsInAtmosphere& list, Double_t Tr,Double_t To) const {
302    //
303    // Generate a SinglePhoton list, coming from Aerosols Mie scattering process applied to the given BunchOfPhotons
304    // Tuning of scattering position done thanks to additional data : scattrate (rate of scattering),
305    // NB : bunch position is at the end of the considered propagation step
306    //
307
308    Double_t wl, date, tof, scatlength;
309    EarthVector showerpos, pos, dir, diff;
310    SinglePhoton* s = 0;
311    TRandom* rndm = EsafRandom::Get();
312   
313    UInt_t bid = b.GetId();
314    PhotonType type = b.GetType();
315   
316    for(Int_t i=0; i<nb; i++) {
317        // corrections for date and showerpos, from BunchOfPhotons mean values, longitudinal and lateral distributions at creation
318        showerpos = b.RandomPosInShower();
319        if(fGround->IsUnderGround(showerpos)) continue;
320        diff = showerpos - b.GetShowerPos();
321        date = b.GetDate() + diff.Dot(b.GetDir().Unit())/Clight();
322       
323        // calculation of the scattering position within the step
324        pos = b.GetPos() - step;    // as if bunch was at the beginning of the step
325        scatlength = (log(1 - rndm->Rndm()*scattrate)/log(1 - scattrate));
326        pos += scatlength *step;
327       
328        // tell if this photon has been really transmitted until the mie scat position (ozone - molecular)
329        // if not  ->  photon is killed
330        if(rndm->Rndm() > exp(scatlength*log(Tr))) continue;
331        if(rndm->Rndm() > exp(scatlength*log(To))) continue;
332       
333        // position correction, due to angular distributions at creation
334        pos = b.PosRandomAngCorrec(showerpos,pos);
335       
336        // if underground, photon is kept for another try
337        if(fGround->IsUnderGround(pos)) {
338            EarthVector axis, impact;
339            impact = b.GetNextImpact();
340            if(impact.Z() == HUGE) {
341                Msg(EsafMsg::Warning) <<"\nno bunch impact, but singles underground" <<MsgDispatch;
342                continue;
343            }
344            else {
345                EarthVector localvertical(impact);
346                localvertical(2) += EarthRadius();
347                axis = localvertical.Cross(b.GetDir());
348                if(axis.Mag()) {    // if localvertical and bunch dir not colinear
349                    EarthVector v1 = pos - impact;
350                    v1.Rotate(TMath::Pi(),axis);
351                    pos = v1 + impact;
352                }
353                if(fGround->IsUnderGround(pos)) {
354                    Msg(EsafMsg::Warning) <<"GenerateSingles() -> pos is still underground" <<MsgDispatch;
355                    continue;
356                }
357            }
358        }
359        tof = b.GetTof() * (showerpos - pos).Mag()/(b.GetPos() - b.GetShowerPos()).Mag();
360        dir = EUSO() - pos;
361        wl = b.GetWlSpectrum().GetLambda(specbin);
362        s = new SinglePhoton(type,date,tof,wl,showerpos,pos,dir,AeroScat,bid,b.GetShowerAge());
363        s->AddInteraction();
364        s->AddHistory(AeroScat);
365        list.Add(s);
366    } 
367}
368
369//_____________________________________________________________________________
370Medium O2_ClearSkyPropagator::BunchPreProcess(BunchOfPhotons& b) const {
371    //
372    // Preprocess run once for each bunch before propagation
373    // Call RadiativeProcessesCalculator::BunchPreProcess
374    // Get the Medium of final impact
375    //
376#ifdef DEBUG
377    Msg(EsafMsg::Debug) <<"IN O2_ClearSkyPropagator::bunchPreProcess" << MsgDispatch;
378#endif
379    const BunchOfPhotons& bunch = b;
380    EarthVector finalimpact;
381   
382    // assess the next impact
383    fFinal_medium = GetFinalImpact(bunch,finalimpact);
384    b.SetFinalImpact(finalimpact);
385    if(finalimpact.Z() == HUGE) Msg(EsafMsg::Warning) << "Bunches should always have an \"impact\"" << MsgDispatch;
386   
387    // if bunch is underground, its simulation is stopped now
388    if(fFinal_medium == NONE) {
389        b.SetFate(3);
390        return fFinal_medium;
391    }
392   
393    // run Calculator BunchPreProcessing
394    if(fCalcul->GetName() == "lowtran") {
395        LowtranRadiativeProcessesCalculator* calcul = (LowtranRadiativeProcessesCalculator*) fCalcul;
396        calcul->PreProcess(bunch);
397    }
398   
399    return fFinal_medium;
400}
401
402//_____________________________________________________________________________
403void O2_ClearSkyPropagator::Reset() {
404    //
405    // reset imbricated objects
406    //
407    fCalcul->Reset();
408    fFinal_medium = NONE;
409    fNbSinglesCorrected = 0;
410}
Note: See TracBrowser for help on using the repository browser.