Updated buspatch and DDL numbers for station 345 and started buspatch at 1
[u/mrichter/AliRoot.git] / TFluka / TFlukaMCGeometry.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17
18 // Class TFlukaMCGeometry
19 // --------------------
20 // Implementation of the TVirtualMCGeometry interface
21 // for defining and using TGeo geometry with FLUKA.
22 // This allows the FLUKA MonteCarlo to run with the TGeo 
23 // geometrical modeller
24 // Author: Andrei Gheata 10/07/2003
25
26 #include "Riostream.h"
27 #include "TList.h"
28 #include "TCallf77.h"
29 #include "TFluka.h"
30 #include "TSystem.h"
31 #include "TFlukaMCGeometry.h"
32 #include "TFlukaConfigOption.h"
33 #include "TGeoManager.h" 
34 #include "TGeoVolume.h" 
35 #include "TObjString.h"
36 #include "Fsourcm.h"
37 #include "Ftrackr.h"
38 #include "Fstepsz.h"       //(STEPSZ) fluka common
39
40 #ifndef WIN32 
41 # define idnrwr idnrwr_
42 # define g1wr   g1wr_
43 # define g1rtwr g1rtwr_
44 # define conhwr conhwr_
45 # define inihwr inihwr_
46 # define jomiwr jomiwr_
47 # define lkdbwr lkdbwr_
48 # define lkfxwr lkfxwr_
49 # define lkmgwr lkmgwr_
50 # define lkwr lkwr_
51 # define magfld magfld_
52 # define nrmlwr nrmlwr_
53 # define rgrpwr rgrpwr_
54 # define isvhwr isvhwr_
55
56 #else
57
58 # define idnrwr IDNRWR
59 # define g1wr   G1WR
60 # define g1rtwr G1RTWR
61 # define conhwr CONHWR
62 # define inihwr INIHWR
63 # define jomiwr JOMIWR
64 # define lkdbwr LKDBWR
65 # define lkfxwr LKFXWR
66 # define lkmgwr LKMGWR
67 # define lkwr   LKWR
68 # define magfld MAGFLD
69 # define nrmlwr NRMLWR
70 # define rgrpwr RGRPWR
71 # define isvhwr ISVHWR
72
73 #endif
74
75 //____________________________________________________________________________ 
76 extern "C" 
77 {
78    //
79    // Prototypes for FLUKA navigation methods
80    //
81    Int_t type_of_call idnrwr(const Int_t & /*nreg*/, const Int_t & /*mlat*/);
82    void  type_of_call   g1wr(Double_t & /*pSx*/, Double_t & /*pSy*/, Double_t & /*pSz*/, 
83                              Double_t * /*pV*/,  Int_t & /*oldReg*/ , const Int_t & /*oldLttc*/, Double_t & /*propStep*/,
84                              Int_t & /*nascFlag*/, Double_t & /*retStep*/, Int_t & /*newReg*/,
85                                   Double_t & /*saf*/, Int_t & /*newLttc*/, Int_t & /*LttcFlag*/,
86                              Double_t *s /*Lt*/, Int_t * /*jrLt*/);
87    
88    void  type_of_call g1rtwr();
89    void  type_of_call conhwr(Int_t & /*intHist*/, Int_t & /*incrCount*/);
90    void  type_of_call inihwr(Int_t & /*intHist*/);
91    void  type_of_call jomiwr(const Int_t & /*nge*/, const Int_t & /*lin*/, const Int_t & /*lou*/,
92                              Int_t & /*flukaReg*/);
93    void  type_of_call lkdbwr(Double_t & /*pSx*/, Double_t & /*pSy*/, Double_t & /*pSz*/,
94                              Double_t * /*pV*/, const Int_t & /*oldReg*/, const Int_t & /*oldLttc*/,
95                              Int_t & /*flagErr*/, Int_t & /*newReg*/, Int_t & /*newLttc*/);
96    void  type_of_call lkfxwr(Double_t & /*pSx*/, Double_t & /*pSy*/, Double_t & /*pSz*/,
97                              Double_t * /*pV*/, const Int_t & /*oldReg*/, const Int_t & /*oldLttc*/,
98                              Int_t & /*flagErr*/, Int_t & /*newReg*/, Int_t & /*newLttc*/);
99    void  type_of_call lkmgwr(Double_t & /*pSx*/, Double_t & /*pSy*/, Double_t & /*pSz*/,
100                              Double_t * /*pV*/, const Int_t & /*oldReg*/, const Int_t & /*oldLttc*/,
101                                        Int_t & /*flagErr*/, Int_t & /*newReg*/, Int_t & /*newLttc*/);
102    void  type_of_call   lkwr(Double_t & /*pSx*/, Double_t & /*pSy*/, Double_t & /*pSz*/,
103                              Double_t * /*pV*/, const Int_t & /*oldReg*/, const Int_t & /*oldLttc*/,
104                                   Int_t & /*flagErr*/, Int_t & /*newReg*/, Int_t & /*newLttc*/);
105 //   void  type_of_call magfld(const Double_t & /*pX*/, const Double_t & /*pY*/, const Double_t & /*pZ*/,
106 //                             Double_t & /*cosBx*/, Double_t & /*cosBy*/, Double_t & /*cosBz*/, 
107 //                             Double_t & /*Bmag*/, Int_t & /*reg*/, Int_t & /*idiscflag*/);        
108    void  type_of_call nrmlwr(Double_t & /*pSx*/, Double_t & /*pSy*/, Double_t & /*pSz*/,
109                              Double_t & /*pVx*/, Double_t & /*pVy*/, Double_t & /*pVz*/,
110                                   Double_t * /*norml*/, const Int_t & /*oldReg*/,
111                                   const Int_t & /*newReg*/, Int_t & /*flagErr*/);
112    void  type_of_call rgrpwr(const Int_t & /*flukaReg*/, const Int_t & /*ptrLttc*/, Int_t & /*g4Reg*/,
113                              Int_t * /*indMother*/, Int_t * /*repMother*/, Int_t & /*depthFluka*/);
114    Int_t type_of_call isvhwr(const Int_t & /*fCheck*/, const Int_t & /*intHist*/);
115 }
116    
117 // TFluka global pointer
118 TFluka *gFluka = 0;
119 TFlukaMCGeometry *gMCGeom = 0;
120 Int_t gNstep = 0;
121
122 ClassImp(TFlukaMCGeometry)
123
124 TFlukaMCGeometry* TFlukaMCGeometry::fgInstance= NULL;
125
126 //_____________________________________________________________________________
127 TFlukaMCGeometry::TFlukaMCGeometry(const char *name, const char *title) 
128    :TNamed(name, title), 
129    fDebug(kFALSE),
130    fLastMaterial(0),
131    fDummyRegion(0),
132    fCurrentRegion(0),
133    fCurrentLattice(0),
134    fNextRegion(0),
135    fNextLattice(0),
136    fRegionList(0),
137    fIndmat(0),
138    fMatList(new TObjArray(256)),
139    fMatNames(new TObjArray(256))
140 {
141   //
142   // Standard constructor
143   //
144   gFluka = (TFluka*)gMC;
145   gMCGeom = this;
146   gNstep = 0;
147 }
148
149 //_____________________________________________________________________________
150 TFlukaMCGeometry::TFlukaMCGeometry()
151   :TNamed(),
152    fDebug(kFALSE),
153    fLastMaterial(0),
154    fDummyRegion(0),
155    fCurrentRegion(0),
156    fCurrentLattice(0),
157    fNextRegion(0),
158    fNextLattice(0),
159    fRegionList(0),
160    fIndmat(0),
161    fMatList(0),
162    fMatNames(0)
163
164 {
165   //
166   // Default constructor
167   //
168   gFluka = (TFluka*)gMC;
169   gMCGeom = this;
170   gNstep = 0;
171 }
172
173 //_____________________________________________________________________________
174 TFlukaMCGeometry::~TFlukaMCGeometry() 
175 {
176   //
177   // Destructor
178   //
179   fgInstance=0;
180   if (fRegionList) delete [] fRegionList;
181   if (fMatList) delete fMatList;
182   if (fMatNames) {fMatNames->Delete(); delete fMatNames;}
183   if (gGeoManager) delete gGeoManager;
184 }
185
186 //
187 // private methods
188 //
189
190 //_____________________________________________________________________________
191 Double_t* TFlukaMCGeometry::CreateDoubleArray(Float_t* array, Int_t size) const
192 {
193 // Converts Float_t* array to Double_t*,
194 // !! The new array has to be deleted by user.
195 // ---
196
197   Double_t* doubleArray;
198   if (size>0) {
199     doubleArray = new Double_t[size]; 
200     for (Int_t i=0; i<size; i++) doubleArray[i] = array[i];
201   }
202   else {
203     //doubleArray = 0; 
204     doubleArray = new Double_t[1]; 
205   }  
206   return doubleArray;
207 }
208 //
209 // public methods
210
211
212 //_____________________________________________________________________________
213 Int_t TFlukaMCGeometry::GetMedium() const
214 {
215 // Get current medium number
216    Int_t imed = 0;
217    TGeoNode *node = gGeoManager->GetCurrentNode();
218    if (!node) imed = gGeoManager->GetTopNode()->GetVolume()->GetMedium()->GetId();
219    else       imed = node->GetVolume()->GetMedium()->GetId();
220    if (fDebug) printf("GetMedium=%i\n", imed);
221    return imed;
222 }
223
224 //_____________________________________________________________________________
225 Int_t TFlukaMCGeometry::GetFlukaMaterial(Int_t imed) const
226 {
227 // Returns FLUKA material index for medium IMED
228      TGeoMedium *med = (TGeoMedium*)gGeoManager->GetListOfMedia()->At(imed-1);
229    if (!med) {
230       Error("GetFlukaMaterial", "MEDIUM %i nor found", imed);
231       return -1;
232    }
233    TGeoMaterial* mat = med->GetMaterial();
234    if (!mat->IsUsed()) return -1;
235    Int_t imatfl = med->GetMaterial()->GetIndex();
236    return imatfl;   
237 }
238
239 //_____________________________________________________________________________
240 Int_t *TFlukaMCGeometry::GetRegionList(Int_t imed, Int_t &nreg)
241 {
242 // Get an ordered list of regions matching a given medium number
243    nreg = 0;
244    if (!fRegionList) fRegionList = new Int_t[NofVolumes()+1];
245    TIter next(gGeoManager->GetListOfUVolumes());
246    TGeoVolume *vol;
247    Int_t imedium, ireg;
248    while ((vol = (TGeoVolume*)next())) {
249        TGeoMedium* med;
250        if ((med = vol->GetMedium()) == 0) continue;
251        imedium = med->GetId();
252        if (imedium == imed) {
253            ireg = vol->GetNumber();
254            fRegionList[nreg++] = ireg;
255        }
256    }
257    return fRegionList;
258 }
259
260 //_____________________________________________________________________________
261 Int_t *TFlukaMCGeometry::GetMaterialList(Int_t imat, Int_t &nreg)
262 {
263 // Get an ordered list of regions matching a given medium number
264    nreg = 0;
265    if (!fRegionList) fRegionList = new Int_t[NofVolumes()+1];
266    TIter next(gGeoManager->GetListOfUVolumes());
267    TGeoVolume *vol;
268    Int_t imaterial, ireg;
269    while ((vol = (TGeoVolume*)next())) {
270        TGeoMedium* med;
271        if ((med = vol->GetMedium()) == 0) continue;
272        imaterial = med->GetMaterial()->GetIndex();
273        if (imaterial == imat) {
274            ireg = vol->GetNumber();
275            fRegionList[nreg++] = ireg;
276        }
277    }
278    return fRegionList;
279 }
280  
281 //_____________________________________________________________________________
282 Int_t TFlukaMCGeometry::NofVolumes() const 
283 {
284   //
285   // Return total number of volumes in the geometry
286   //
287
288   return gGeoManager->GetListOfUVolumes()->GetEntriesFast()-1;
289 }
290   
291 //_____________________________________________________________________________
292 TGeoMaterial * TFlukaMCGeometry::GetMakeWrongMaterial(Double_t z)
293 {
294 // Try to replace a wrongly-defined material
295    static Double_t kz[23] = {7.3, 17.8184, 7.2167, 10.856, 8.875, 8.9, 7.177,
296       25.72, 6.2363, 7.1315, 47.7056, 10.6467, 7.8598, 2.10853, 10.6001, 9.1193, 
297       15.3383, 4.55,   9.6502, 6.4561, 21.7963, 29.8246, 15.4021};
298
299    Int_t ind;
300    Double_t dz;
301    for (ind=0; ind<23; ind++) {
302       dz = TMath::Abs(z-kz[ind]);
303       if (dz<1E-4) break;
304    }
305    if (ind>22) {
306       printf("Cannot patch material with Z=%g\n", z);
307       return 0;
308    }
309    TGeoMixture *mix = 0;
310    TGeoElement *element;
311    TGeoElementTable *table = gGeoManager->GetElementTable();
312    switch (ind) {
313       case 0: // AIR
314          mix = new TGeoMixture("TPC_AIR", 4, 0.001205);
315          element = table->GetElement(6); // C
316          mix->DefineElement(0, element, 0.000124);
317          element = table->GetElement(7); // N
318          mix->DefineElement(1, element, 0.755267);
319          element = table->GetElement(8); // O
320          mix->DefineElement(2, element, 0.231781);
321          element = table->GetElement(18); // AR
322          mix->DefineElement(3, element, 0.012827);
323          break;
324       case 1: //SDD SI CHIP
325          mix = new TGeoMixture("ITS_SDD_SI", 6, 2.4485);
326          element = table->GetElement(1);
327          mix->DefineElement(0, element, 0.004367771);
328          element = table->GetElement(6);
329          mix->DefineElement(1, element, 0.039730642);
330          element = table->GetElement(7);
331          mix->DefineElement(2, element, 0.001396798);
332          element = table->GetElement(8);
333          mix->DefineElement(3, element, 0.01169634);
334          element = table->GetElement(14);
335          mix->DefineElement(4, element, 0.844665);
336          element = table->GetElement(47);
337          mix->DefineElement(5, element, 0.09814344903);
338          break;
339       case 2:  // WATER
340          mix = new TGeoMixture("ITS_WATER", 2, 1.0);
341          element = table->GetElement(1);
342          mix->DefineElement(0, element, 0.111898344);
343          element = table->GetElement(8);
344          mix->DefineElement(1, element, 0.888101656);
345          break;
346       case 3: // CERAMICS
347          mix = new TGeoMixture("ITS_CERAMICS", 5, 3.6);
348          element = table->GetElement(8);
349          mix->DefineElement(0, element, 0.59956);
350          element = table->GetElement(13);
351          mix->DefineElement(1, element, 0.3776);
352          element = table->GetElement(14);
353          mix->DefineElement(2, element, 0.00933);
354          element = table->GetElement(24);
355          mix->DefineElement(3, element, 0.002);
356          element = table->GetElement(25);
357          mix->DefineElement(4, element, 0.0115);
358          break;
359       case 4: // EPOXY
360          mix = new TGeoMixture("MUON_G10FR4", 4, 1.8);
361          element = table->GetElement(1);
362          mix->DefineElement(0, element, 0.19);
363          element = table->GetElement(6);
364          mix->DefineElement(1, element, 0.18);
365          element = table->GetElement(8);
366          mix->DefineElement(2, element, 0.35);
367          element = table->GetElement(14);
368          mix->DefineElement(3, element, 0.28);
369          break;
370       case 5: // EPOXY
371          mix = new TGeoMixture("G10FR4", 4, 1.8);
372          element = table->GetElement(1);
373          mix->DefineElement(0, element, 0.19);
374          element = table->GetElement(6);
375          mix->DefineElement(1, element, 0.18);
376          element = table->GetElement(8);
377          mix->DefineElement(2, element, 0.35);
378          element = table->GetElement(14);
379          mix->DefineElement(3, element, 0.28);
380          break;
381       case 6: // KAPTON
382          mix = new TGeoMixture("ITS_KAPTON", 4, 1.3);
383          element = table->GetElement(1);
384          mix->DefineElement(0, element, 0.026363415);
385          element = table->GetElement(6);
386          mix->DefineElement(1, element, 0.6911272);
387          element = table->GetElement(7);
388          mix->DefineElement(2, element, 0.073271325);
389          element = table->GetElement(8);
390          mix->DefineElement(3, element, 0.209238060);
391          break;
392       case 7: // INOX
393          mix = new TGeoMixture("ITS_INOX", 9, 7.9);
394          element = table->GetElement(6);
395          mix->DefineElement(0, element, 0.0003);
396          element = table->GetElement(14);
397          mix->DefineElement(1, element, 0.01);          
398          element = table->GetElement(15);
399          mix->DefineElement(2, element, 0.00045);
400          element = table->GetElement(16);
401          mix->DefineElement(3, element, 0.0003);
402          element = table->GetElement(24);
403          mix->DefineElement(4, element, 0.17);
404          element = table->GetElement(25);
405          mix->DefineElement(5, element, 0.02);
406          element = table->GetElement(26);
407          mix->DefineElement(6, element, 0.654);
408          element = table->GetElement(28);
409          mix->DefineElement(7, element, 0.12);
410          element = table->GetElement(42);
411          mix->DefineElement(8, element, 0.025);
412          break;
413       case 8: // ROHACELL
414          mix = new TGeoMixture("ROHACELL", 4, 0.05);
415          element = table->GetElement(1);
416          mix->DefineElement(0, element, 0.07836617);
417          element = table->GetElement(6);
418          mix->DefineElement(1, element, 0.64648941);
419          element = table->GetElement(7);
420          mix->DefineElement(2, element, 0.08376983);
421          element = table->GetElement(8);
422          mix->DefineElement(3, element, 0.19137459);
423          break;
424       case 9: // SDD-C-AL
425          mix = new TGeoMixture("ITS_SDD-C-AL", 5, 1.9837);
426          element = table->GetElement(1);
427          mix->DefineElement(0, element, 0.022632);
428          element = table->GetElement(6);
429          mix->DefineElement(1, element, 0.8176579);
430          element = table->GetElement(7);
431          mix->DefineElement(2, element, 0.0093488);
432          element = table->GetElement(8);
433          mix->DefineElement(3, element, 0.0503618);
434          element = table->GetElement(13);
435          mix->DefineElement(4, element, 0.1);
436          break;
437       case 10: // X7R-CAP
438          mix = new TGeoMixture("ITS_X7R-CAP", 7, 6.72);
439          element = table->GetElement(8);
440          mix->DefineElement(0, element, 0.085975822);
441          element = table->GetElement(22);
442          mix->DefineElement(1, element, 0.084755042);
443          element = table->GetElement(28);
444          mix->DefineElement(2, element, 0.038244751);
445          element = table->GetElement(29);
446          mix->DefineElement(3, element, 0.009471271);
447          element = table->GetElement(50);
448          mix->DefineElement(4, element, 0.321736471);
449          element = table->GetElement(56);
450          mix->DefineElement(5, element, 0.251639432);
451          element = table->GetElement(82);
452          mix->DefineElement(6, element, 0.2081768);
453          break;
454       case 11: // SDD ruby sph. Al2O3
455          mix = new TGeoMixture("ITS_AL2O3", 2, 3.97);
456          element = table->GetElement(8);
457          mix->DefineElement(0, element, 0.5293);
458          element = table->GetElement(13);
459          mix->DefineElement(1, element, 0.4707);
460          break;
461       case 12: // SDD HV microcable
462          mix = new TGeoMixture("ITS_HV-CABLE", 5, 1.6087);
463          element = table->GetElement(1);
464          mix->DefineElement(0, element, 0.01983871336);
465          element = table->GetElement(6);
466          mix->DefineElement(1, element, 0.520088819984);
467          element = table->GetElement(7);
468          mix->DefineElement(2, element, 0.0551367996);
469          element = table->GetElement(8);
470          mix->DefineElement(3, element, 0.157399667056);
471          element = table->GetElement(13);
472          mix->DefineElement(4, element, 0.247536);
473          break;
474       case 13: //SDD LV+signal cable
475          mix = new TGeoMixture("ITS_LV-CABLE", 5, 2.1035);
476          element = table->GetElement(1);
477          mix->DefineElement(0, element, 0.0082859922);
478          element = table->GetElement(6);
479          mix->DefineElement(1, element, 0.21722436468);
480          element = table->GetElement(7);
481          mix->DefineElement(2, element, 0.023028867);
482          element = table->GetElement(8);
483          mix->DefineElement(3, element, 0.06574077612);
484          element = table->GetElement(13);
485          mix->DefineElement(4, element, 0.68572);
486          break;
487       case 14: //SDD hybrid microcab
488          mix = new TGeoMixture("ITS_HYB-CAB", 5, 2.0502);
489          element = table->GetElement(1);
490          mix->DefineElement(0, element, 0.00926228815);
491          element = table->GetElement(6);
492          mix->DefineElement(1, element, 0.24281879711);
493          element = table->GetElement(7);
494          mix->DefineElement(2, element, 0.02574224025);
495          element = table->GetElement(8);
496          mix->DefineElement(3, element, 0.07348667449);
497          element = table->GetElement(13);
498          mix->DefineElement(4, element, 0.64869);
499          break;
500       case 15: //SDD anode microcab
501          mix = new TGeoMixture("ITS_ANOD-CAB", 5, 1.7854);
502          element = table->GetElement(1);
503          mix->DefineElement(0, element, 0.0128595919215);
504          element = table->GetElement(6);
505          mix->DefineElement(1, element, 0.392653705471);
506          element = table->GetElement(7);
507          mix->DefineElement(2, element, 0.041626868025);
508          element = table->GetElement(8);
509          mix->DefineElement(3, element, 0.118832707289);
510          element = table->GetElement(13);
511          mix->DefineElement(4, element, 0.431909);
512          break;
513       case 16: // inox/alum
514          mix = new TGeoMixture("ITS_INOX-AL", 5, 3.0705);
515          element = table->GetElement(13);
516          mix->DefineElement(0, element, 0.816164);
517          element = table->GetElement(14);
518          mix->DefineElement(1, element, 0.000919182);
519          element = table->GetElement(24);
520          mix->DefineElement(2, element, 0.0330906);
521          element = table->GetElement(26);
522          mix->DefineElement(3, element, 0.131443);
523          element = table->GetElement(28);
524          mix->DefineElement(4, element, 0.0183836);
525       case 17: // MYLAR
526          mix = new TGeoMixture("TPC_MYLAR", 3, 1.39);
527          element = table->GetElement(1);
528          mix->DefineElement(0, element, 0.0416667);
529          element = table->GetElement(6);
530          mix->DefineElement(1, element, 0.625);
531          element = table->GetElement(8);
532          mix->DefineElement(2, element, 0.333333);
533          break;
534       case 18: // SPDBUS(AL+KPT+EPOX)   - unknown composition
535          mix = new TGeoMixture("ITS_SPDBUS", 1, 1.906);
536          element = table->GetElement(9);
537          mix->DefineElement(0, element, 1.);
538          z = element->Z();
539          break;
540       case 19: // SDD/SSD rings   - unknown composition
541          mix = new TGeoMixture("ITS_SDDRINGS", 1, 1.8097);
542          element = table->GetElement(6);
543          mix->DefineElement(0, element, 1.);
544          z = element->Z();
545          break;
546       case 20: // SPD end ladder   - unknown composition
547          mix = new TGeoMixture("ITS_SPDEL", 1, 3.6374);
548          element = table->GetElement(22);
549          mix->DefineElement(0, element, 1.);
550          z = element->Z();
551          break;
552       case 21: // SDD end ladder   - unknown composition
553          mix = new TGeoMixture("ITS_SDDEL", 1, 0.3824);
554          element = table->GetElement(30);
555          mix->DefineElement(0, element, 1.);
556          z = element->Z();
557          break;
558       case 22: // SSD end ladder   - unknown composition
559          mix = new TGeoMixture("ITS_SSDEL", 1, 0.68);
560          element = table->GetElement(16);
561          mix->DefineElement(0, element, 1.);
562          z = element->Z();
563          break;
564    }
565    mix->SetZ(z);      
566    printf("Patched with mixture %s\n", mix->GetName());
567    return mix;
568 }   
569
570 //_____________________________________________________________________________
571 void TFlukaMCGeometry::CreateFlukaMatFile(const char *fname)
572 {
573   // ==== from FLUGG ====
574   // NAMES OF ELEMENTS AND COMPOUNDS: the names must be written in upper case,
575   // according to the fluka standard. In addition,. they must be equal to the
576   // names of the fluka materials - see fluka manual - in order that the 
577   // program load the right cross sections, and equal to the names included in
578   // the .pemf. Otherwise the user must define the LOW-MAT CARDS, and make his
579   // own .pemf, in order to get the right cross sections loaded in memory.
580
581
582    TString sname;
583    gGeoManager->Export("flgeom.root");
584    if (fname) sname = fname;
585    else       sname = "flukaMat.inp";
586    ofstream out;
587    out.open(sname.Data(), ios::out);
588    if (!out.good()) {
589       Fatal("CreateFlukaMatFile", "could not open file %s for writing", sname.Data());
590       return;
591    }
592    PrintHeader(out, "MATERIALS AND COMPOUNDS");
593    PrintHeader(out, "MATERIALS");   
594    Int_t i,j,idmat;
595    Int_t counttothree, nelem;
596    Double_t a,z,rho, w;
597    TGeoElementTable *table = gGeoManager->GetElementTable();
598    TGeoElement *element;
599    element = table->GetElement(13);
600    element->SetTitle("ALUMINUM"); // this is how FLUKA likes it ...
601    element = table->GetElement(15);
602    element->SetTitle("PHOSPHO");  // same story ...
603 //   element = table->GetElement(10);
604 //   element->SetTitle("ARGON");  // NEON not in neutron xsec table
605    Int_t nelements = table->GetNelements();
606    TList *matlist = gGeoManager->GetListOfMaterials();
607 //   TList *medlist = gGeoManager->GetListOfMedia();
608 //   Int_t nmed = medlist->GetSize();
609    TIter next(matlist);
610    Int_t nmater = matlist->GetSize();
611    Int_t nfmater = 0;
612    TGeoMaterial *mat;
613    TGeoMixture *mix = 0;
614    TString matname;
615    TObjString *objstr;
616    // Create all needed elements
617    for (Int_t i=1; i<nelements; i++) {
618       element = table->GetElement(i);
619       // skip elements which are not defined
620       if (!element->IsUsed() && !element->IsDefined()) continue;
621       matname = element->GetTitle();
622       ToFlukaString(matname);
623       rho = 0.999;
624
625       mat = new TGeoMaterial(matname, element->A(), element->Z(), rho);
626       mat->SetIndex(nfmater+3);
627       mat->SetUsed(kTRUE);
628       fMatList->Add(mat);
629       objstr = new TObjString(matname.Data());
630       fMatNames->Add(objstr);
631       nfmater++;
632    }
633    
634    fIndmat = nfmater;
635 //   TGeoMedium *med;
636    // Adjust material names and add them to FLUKA list
637    for (i=0; i<nmater; i++) {
638       mat = (TGeoMaterial*)matlist->At(i);
639       if (!mat->IsUsed()) continue;
640       z = mat->GetZ();
641       a = mat->GetA();
642       rho = mat->GetDensity();
643       if (mat->GetZ()<0.001) {
644          mat->SetIndex(2); // vacuum, built-in inside FLUKA
645          continue;
646       } 
647       matname = mat->GetName();
648       FlukaMatName(matname);
649
650       mat->SetIndex(nfmater+3);
651       objstr = new TObjString(matname.Data());
652       fMatList->Add(mat);
653       fMatNames->Add(objstr);
654       nfmater++;
655    }   
656
657    // Dump all elements with MATERIAL cards         
658    for (i=0; i<nfmater; i++) {
659       mat = (TGeoMaterial*)fMatList->At(i);
660 //      mat->SetUsed(kFALSE);
661       mix = 0;
662       out << setw(10) << "MATERIAL  ";
663       out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
664       objstr = (TObjString*)fMatNames->At(i);
665       matname = objstr->GetString();
666       z = mat->GetZ();
667       a = mat->GetA();
668       rho = mat->GetDensity();
669       if (mat->IsMixture()) {
670          out << setw(10) << " ";
671          out << setw(10) << " ";
672          mix = (TGeoMixture*)mat;
673       } else {   
674          out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << z;
675          out << setw(10) << setprecision(3) << a;
676       }
677       out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
678       out << setw(10) << setiosflags(ios::scientific) << setprecision(3) << rho;
679       out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
680       out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << Double_t(mat->GetIndex());   
681       out << setw(10) << " ";
682       out << setw(10) << " ";
683       out << setw(8) << matname.Data() << endl;
684       if (!mix) {
685          // add LOW-MAT card for NEON to associate with ARGON neutron xsec
686          if (z==10) {
687             out << setw(10) << "LOW-MAT   ";
688             out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
689             out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << Double_t(mat->GetIndex());
690             out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << 18.;
691             out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << -2.;
692             out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << 293.;
693             out << setw(10) << " ";
694             out << setw(10) << " ";
695 //            out << setw(8) << matname.Data() << endl;
696             out << setw(8) << " " << endl;
697          } 
698          else { 
699             element = table->GetElement((int)z);
700             TString elename = element->GetTitle();
701             ToFlukaString(elename);
702             if( matname.CompareTo( elename ) != 0 ) {
703                out << setw(10) << "LOW-MAT   ";
704                out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
705                out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << Double_t(mat->GetIndex());
706                out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << z;
707                out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << " ";
708                out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << " ";
709                out << setw(10) << " ";
710                out << setw(10) << " ";
711                // missing material at Low Energy Cross Section Table
712                if( (int)z==10 || (int)z==21 || (int)z==34 || (int)z==37 || (int)z==39 || (int)z==44 ||
713                    (int)z==45 || (int)z==46 || (int)z==52 || (int)z==57 || (int)z==59 || (int)z==60 ||
714                    (int)z==61 || (int)z==65 || (int)z==66 || (int)z==67 || (int)z==68 || (int)z==69 ||
715                    (int)z==70 || (int)z==71 || (int)z==72 || (int)z==76 || (int)z==77 || (int)z==78 ||
716                    (int)z==81 || (int)z==84 || (int)z==85 || (int)z==86 || (int)z==87 || (int)z==88 ||
717                    (int)z==89 || (int)z==91 )
718                   out << setw(8) << "UNKNOWN " << endl;
719                else
720                   out << setw(8) << elename.Data() << endl;
721    //               out << setw(8) << " " << endl;
722             }
723          }
724          continue;
725       }   
726       counttothree = 0;
727       out << setw(10) << "COMPOUND  ";
728       nelem = mix->GetNelements();
729       objstr = (TObjString*)fMatNames->At(i);
730       matname = objstr->GetString();
731       for (j=0; j<nelem; j++) {
732          w = (mix->GetWmixt())[j];
733          if (w<0.00001) w=0.00001;
734          z = (mix->GetZmixt())[j];       
735          a = (mix->GetAmixt())[j];
736          idmat = GetElementIndex(Int_t(z));
737          if (!idmat) Error("CreateFlukaMatFile", "element with Z=%f not found", z);
738          out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
739          out << setw(10) << setiosflags(ios::fixed) << setprecision(6) << -w;   
740          out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
741          out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << Double_t(idmat);
742          counttothree++;
743          if (counttothree == 3) {
744             out << matname.Data();
745             out << endl;
746             if ( (j+1) != nelem) out << setw(10) << "COMPOUND  ";
747             counttothree = 0;
748          } 
749       }               
750       if (nelem%3) {
751          for (j=0; j<(3-(nelem%3)); j++)
752             out << setw(10) << " " << setw(10) << " ";
753          out << matname.Data();
754          out << endl;
755       } 
756    }     
757    Int_t nvols = gGeoManager->GetListOfUVolumes()->GetEntriesFast()-1;
758    TGeoVolume *vol;
759    // Now print the material assignments
760    Double_t flagfield = 0.;
761    printf("#############################################################\n");
762    if (gFluka->IsFieldEnabled()) {
763       flagfield = 1.;
764       printf("Magnetic field enabled\n");
765    } else printf("Magnetic field disabled\n");   
766    printf("#############################################################\n");
767    
768    PrintHeader(out, "TGEO MATERIAL ASSIGNMENTS");   
769    for (i=1; i<=nvols; i++) {
770       TGeoMedium* med;
771       vol = gGeoManager->GetVolume(i);
772       if ((med = vol->GetMedium()) == 0) continue;
773       mat = med->GetMaterial();
774       idmat = mat->GetIndex();
775       for (Int_t j=0; j<nfmater; j++) {
776          mat = (TGeoMaterial*)fMatList->At(j);
777          if (mat->GetIndex() == idmat) mat->SetUsed(kTRUE);
778       }   
779
780       Float_t hasfield  = (vol->GetMedium()->GetParam(1) > 0) ? flagfield : 0.;
781       out << "* Assigning material:   " << vol->GetMedium()->GetMaterial()->GetName() << "   to Volume: " << vol->GetName();
782       out << endl;
783
784       out << setw(10) << "ASSIGNMAT ";
785       out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
786       out << setw(10) << setiosflags(ios::fixed) << Double_t(idmat);
787       out << setw(10) << setiosflags(ios::fixed) << Double_t(i);
788       out << setw(10) << "0.0";
789       out << setw(10) << "0.0";
790       out << setw(10) << setiosflags(ios::fixed) <<  hasfield;
791       out << setw(10) << "0.0";
792       out << endl;
793    }
794    // dummy region
795    idmat = 2; // vacuum
796    fDummyRegion = nvols+1;
797    out << "* Dummy region:   " << endl;
798    out << setw(10) << "ASSIGNMAT ";
799    out.setf(static_cast<std::ios::fmtflags>(0),std::ios::floatfield);
800    out << setw(10) << setiosflags(ios::fixed) << idmat;
801    out << setw(10) << setiosflags(ios::fixed) << fDummyRegion;
802    out << setw(10) << "0.0";
803    out << setw(10) << "0.0";
804    out << setw(10) << "0.0";
805    out << setw(10) << "0.0" << endl;
806    out.close();
807    fLastMaterial = nfmater+2;
808 }
809
810 void TFlukaMCGeometry::CreatePemfFile()
811 {
812     //
813     // Steering routine to write and process peg files producing the pemf input 
814     //
815     char number[20];
816     Int_t countMatOK     = 0;
817     Int_t countElemError = 0;
818     Int_t countNoStern   = 0;
819     Int_t countMixError  = 0;
820     Int_t countGas       = 0;
821     Int_t countPemfError = 0;
822     Int_t i;
823     TGeoMaterial* mat = 0x0;
824     TString sname;
825     
826     for (i = fIndmat; i < fLastMaterial - 2; i++) {
827         printf("Write Peg Files %d\n", i);
828         
829         mat = (TGeoMaterial*)fMatList->At(i);
830         if (!mat->IsUsed()) continue;
831         sname = "mat";
832         sprintf(number, "%d", i);
833         sname.Append(number);
834         cout << endl;
835         cout << endl;
836         cout << "******************************************************************************" << endl;
837         cout << "******************************************************************************" << endl;
838         cout << endl;
839         WritePegFile(i, &countNoStern, &countElemError, &countMixError, &countGas);
840         sname.Prepend("$FLUPRO/pemf/rpemf peg/");
841         gSystem->Exec(sname.Data());
842         
843         // check if the pemf file was created
844         TString sname = Form("peg/mat%d.pemf", i);
845         ifstream in( sname.Data() );
846         if ( in ) {
847             countMatOK++;
848             in.close();
849         } else {
850             cout << "ERROR Fail to create the pemf file " << sname << endl;
851             countPemfError++;
852         }
853     }
854     cout << "Materials (pemf created)   " << countMatOK         << endl;
855     cout << "Not Sternheimer par. found  " << countNoStern   << endl;
856     cout << "Elements with error definitions (Z not integer)  " << countElemError      << endl;
857     cout << "Mixtures with error definitions (Z not integer) " << countMixError  << endl;
858     cout << "Posible Gas (rho < 0.01) " << countGas           << endl;
859     // cout << "Posible Gas (without pressure information) " << countGasError           << endl;
860     cout << "Pemf files Error    " << countPemfError     << endl;
861     cout << endl << endl;
862     
863     sname = "cat peg/*.pemf > peg/FlukaVmc.pemf";         
864     gSystem->Exec(sname.Data());
865     sname = "mv peg/FlukaVmc.pemf FlukaVmc.pemf";
866     gSystem->Exec(sname.Data());
867 }
868
869 //_____________________________________________________________________________
870 void TFlukaMCGeometry::WritePegFile(Int_t imat, Int_t *NoStern, Int_t *ElemError,
871                        Int_t *MixError, Int_t *countGas) const
872 {
873    // Write the .peg file for one material
874    
875    TGeoMaterial *mat = (TGeoMaterial*)fMatList->At(imat);
876    TString name = ((TObjString*)fMatNames->At(imat))->GetString();
877    TString line;
878    char number[20];
879    TGeoElement *elem = mat->GetElement();
880    name = name.Strip();
881    TString sname = "mat";
882    sprintf(number, "%d", imat);
883    sname.Append(number);
884    sname.Append(".peg");
885    sname.Prepend("peg/");
886    ofstream out;
887    out.open(sname.Data(), ios::out);
888    if (!out.good()) return;
889    Double_t dens = mat->GetDensity();
890    TGeoMixture *mix = 0;
891    Int_t nel = 1;
892    Int_t i;
893    if (mat->IsMixture()) {
894       mix = (TGeoMixture*)mat;
895       nel = mix->GetNelements();
896    } 
897      
898    if (nel==1) {
899       cout  << "( Element ) " << name << "  Z=" << mat->GetZ() << " Rho " << mat->GetDensity() << endl;
900
901       Double_t zel = mat->GetZ();
902       if( (zel-Int_t(zel))>0.001 || zel < 1 ) {
903          cout << " ERROR: A Element with not integer Z=" << zel << endl;
904          cout << endl;
905          (*ElemError)++;
906          return;
907       }
908       
909       out << "ELEM" << endl;
910       out << " &INP IRAYL=1, RHO=" << dens << ", " << endl;
911       
912       // check for the Sternheimer parameters
913       Double_t *issb_parm = GetISSB( mat->GetDensity(), 1, &zel, 0 );
914       if( issb_parm[0] > 0 && issb_parm[1] > 0 ) {
915          cout << "Sternheimer parameters found" << endl;
916          out << ", ISSB=1, IEV=" << issb_parm[0] << ", CBAR=" << issb_parm[1]
917              << ", X0=" << issb_parm[2] << "," << endl;
918          out << "X1=" <<issb_parm[3] <<", AFACT="<<issb_parm[4] <<", SK="
919              << issb_parm[5] << ", DELTA0=" << issb_parm[6];
920       } 
921       else {
922          cout << "WARNING: Strange element, Sternheimer parameters  not found" << endl;
923         (*NoStern)++;
924       }
925
926       if (dens<0.01) {
927         (*countGas)++;
928         out << " GASP=1." << endl;
929       }
930       
931       out << " &END" <<  endl;
932       out << name.Data() << endl;
933       out << elem->GetName() << endl;
934       
935    } 
936    else {
937    
938       cout  << "( Mixture )  " << name << "  Rho " << dens << " nElem " << nel << endl;
939     
940       Double_t *zt = new Double_t[nel];
941       Double_t *wt = new Double_t[nel];
942       for (int j=0; j<nel; j++) {
943          zt[j] = (mix->GetZmixt())[j];
944          wt[j] = (mix->GetWmixt())[j];
945          if( (zt[j]-Int_t(zt[j])) > 0.001 || zt[j] < 1 ) {
946             cout << "ERROR Mixture " << name << " with an element with not integer Z=" << zt[j] << endl;
947             cout << endl;
948             (*MixError)++;
949             // just continue since the mixtures are not patch, 
950             // but the final release should include the return   
951             //  return;         
952          }
953       }
954       Double_t *issb_parm = GetISSB( mat->GetDensity(), nel, zt, wt );
955       out << "MIXT" << endl;
956       out << " &INP IRAYL=1, NE=" << nel << ", RHOZ=" << wt[0] << ",";
957       line = Form(" &INP IRAYL=1, NE=%d RHOZ=%g", nel, wt[0]);
958       for(int j=1; j<nel; j++) {
959          out << " " << wt[j] << ",";
960          line += Form(" %g,", wt[j] );
961          if( line.Length() > 60 ) { out << endl; line = ""; }
962       }
963       out << " RHO=" << mat->GetDensity() << ", ";
964       line += Form(" RHO=%g, ", mat->GetDensity());
965       if( line.Length() > 60 ) { out << endl; line = ""; }
966       
967       if( issb_parm[0] > 0 && issb_parm[1] > 0 ) {
968          cout << "Sternheimer parameters found" << endl;
969          out << " ISSB=1, IEV=" << issb_parm[0] << ",";
970          line += Form(" ISSB=1, IEV=%g,", issb_parm[0]);
971          if( line.Length() > 60 ) { out << endl; line = "";  }
972          out << " CBAR=" << issb_parm[1] << ",";
973          line += Form(" CBAR=%g,",issb_parm[1]);
974          if( line.Length() > 60 ) { out << endl; line = "";  }
975          out << " X0=" << issb_parm[2] << ",";
976          line += Form(" X0=%g,", issb_parm[2]);
977          if( line.Length() > 60 ) { out << endl; line = "";  }
978          out << " X1=" << issb_parm[3] << ",";
979          line += Form(" X1=%g,", issb_parm[3]);
980          if( line.Length() > 60 ) { out << endl; line = "";  }
981          out << " AFACT="<< issb_parm[4] << ",";
982          line += Form(" AFACT=%g,", issb_parm[4]);
983          if( line.Length() > 60 ) { out << endl; line = "";  }
984          out << " SK=" << issb_parm[5] << ",";
985          line += Form(" SK=%g,", issb_parm[5]);
986          if( line.Length() > 60 ) { out << endl; line = "";  }
987       }
988       else {
989          cout << "Sternheimer parameters  not found" << endl;
990          (*NoStern)++;
991       }
992       
993       if (dens<0.01){
994          (*countGas)++;
995          out << " GASP=1." << endl;
996       }
997       
998       out << " &END" <<  endl;
999       out << name.Data() << endl;
1000       for (i=0; i<nel; i++) {
1001          elem = mix->GetElement(i);
1002          line = elem->GetName();
1003          if (line.Length()==1) line.Append(" ");
1004          out << line.Data() << " ";
1005       }
1006       out << endl;
1007       
1008       delete [] zt;
1009       delete [] wt;
1010    }
1011    
1012    Double_t ue = 3000000.; // [MeV]
1013    Double_t up = 3000000.; // [MeV]
1014    Double_t ae = -1.;
1015    Double_t ap = -1.;
1016    
1017    
1018    TObjArray* cutList = ((TFluka*) gMC)->GetListOfUserConfigs();
1019    TIter next(cutList);
1020    TFlukaConfigOption* proc;
1021    
1022    while((proc = (TFlukaConfigOption*)next()))
1023    { 
1024        if (proc->Medium() == mat->GetIndex()) {
1025            ap = proc->Cut(kCUTGAM);
1026            ae = proc->Cut(kCUTELE);
1027            if (ap == -1.) ap =  TFlukaConfigOption::DefaultCut(kCUTGAM);
1028            if (ae == -1.) ae =  TFlukaConfigOption::DefaultCut(kCUTELE);
1029            break;
1030        }
1031    }
1032
1033    if (ap == -1.) ap =  TFlukaConfigOption::DefaultCut(kCUTGAM);
1034    if (ae == -1.) ae =  TFlukaConfigOption::DefaultCut(kCUTELE);
1035
1036    ap *= 1000.;                         // [MeV]
1037    ae  = (ae + 0.00051099906) * 1000.;  // [MeV]
1038    
1039    out << "ENER" << endl;
1040    out << " $INP AE=" << ae << ", UE=" << ue <<", AP=" << ap << ", UP=" << up << " $END" << endl;
1041    out << "PWLF" << endl;
1042    out << " $INP NALE=300, NALG=400, NALR=100 $END" << endl;
1043    out << "DECK" << endl;
1044    out << " $INP $END" << endl;
1045    out << "TEST" << endl;
1046    out << " $INP $END" << endl;
1047    out.close();
1048 }
1049
1050 Double_t * TFlukaMCGeometry::GetISSB(Double_t rho, Int_t nElem, Double_t *zelem, Double_t *welem ) const
1051 {
1052    // Read the density effect parameters
1053    // from R.M. Sternheimer et al. Atomic Data
1054    // and Nuclear Data Tables, Vol. 30 No. 2
1055    //
1056    // return the parameters if the element/mixture match with one of the list
1057    // otherwise returns the parameters set to 0
1058    
1059    struct sternheimerData {
1060       TString     longname;           // element/mixture name
1061       Int_t       nelems;             // number of constituents N
1062       Int_t       Z[20];              //[nelems] Z
1063       Double_t    wt[20];             //[nelems] weight fraction
1064       Double_t    density;            // g/cm3
1065       Double_t    iev;                // Average Ion potential (eV)
1066                                       // ****   Sternheimer parameters  ****
1067       Double_t    cbar;               // CBAR
1068       Double_t    x0;                 // X0
1069       Double_t    x1;                 // X1
1070       Double_t    afact;              // AFACT
1071       Double_t    sk;                 // SK
1072       Double_t    delta0;             // DELTA0
1073
1074       sternheimerData():
1075          longname(""), nelems(0), density(0), iev(0), cbar(0),
1076          x0(0), x1(0), afact(0), sk(0), delta0(0) {}
1077    };
1078    
1079    TString     shortname;
1080    TString     formula;
1081    Int_t       num;
1082    char        state;
1083    
1084    static Double_t parameters[7];
1085    memset( parameters, 0, sizeof(Double_t) );
1086
1087    static sternheimerData sternDataArray[300];
1088    static Bool_t isFileRead = kFALSE;
1089    
1090    // Read the data file if is needed
1091    if( isFileRead == kFALSE ) {
1092       TString sSternheimerInp = getenv("ALICE_ROOT");
1093       sSternheimerInp +="/TFluka/input/Sternheimer.data";
1094    
1095       ifstream in(sSternheimerInp);
1096       char line[100];
1097       in.getline(line, 100);   
1098       in.getline(line, 100);   
1099       in.getline(line, 100);   
1100       in.getline(line, 100);   
1101       in.getline(line, 100);   
1102       in.getline(line, 100);   
1103       
1104       
1105       Int_t is = 0;
1106       while( !in.eof() ) {
1107          in >> shortname >> num     >> sternDataArray[is].nelems 
1108             >> sternDataArray[is].longname  >> formula >> state;
1109          if( in.eof() ) break;
1110          for(int i=0; i<sternDataArray[is].nelems; i++) {
1111             in >> sternDataArray[is].Z[i] >> sternDataArray[is].wt[i]; 
1112          }
1113          in >> sternDataArray[is].density; 
1114          in >> sternDataArray[is].iev; 
1115          in >> sternDataArray[is].cbar; 
1116          in >> sternDataArray[is].x0; 
1117          in >> sternDataArray[is].x1; 
1118          in >> sternDataArray[is].afact; 
1119          in >> sternDataArray[is].sk;
1120          if( sternDataArray[is].nelems == 1 ) in >> sternDataArray[is].delta0;
1121          is++;
1122       }
1123       isFileRead = kTRUE;
1124       in.close();
1125    }   
1126    
1127    Int_t is = 0;
1128    while( is < 280 ) {
1129    
1130       // check for elements
1131       if( sternDataArray[is].nelems == 1 && nElem == 1
1132           && sternDataArray[is].Z[0] == Int_t(*zelem)
1133           && TMath::Abs( (sternDataArray[is].density - rho)/sternDataArray[is].density ) < 0.1 ) {
1134          cout << sternDataArray[is].longname << "   #elems:" <<  sternDataArray[is].nelems << "  Rho:" 
1135               << sternDataArray[is].density << endl;
1136          cout << sternDataArray[is].iev   << " " 
1137               << sternDataArray[is].cbar  << " " 
1138               << sternDataArray[is].x0    << " " 
1139               << sternDataArray[is].x1    << " " 
1140               << sternDataArray[is].afact << " " 
1141               << sternDataArray[is].sk    << " " 
1142               << sternDataArray[is].delta0 << endl;
1143          
1144          parameters[0] = sternDataArray[is].iev;
1145          parameters[1] = sternDataArray[is].cbar;
1146          parameters[2] = sternDataArray[is].x0;
1147          parameters[3] = sternDataArray[is].x1;
1148          parameters[4] = sternDataArray[is].afact;
1149          parameters[5] = sternDataArray[is].sk;
1150          parameters[6] = sternDataArray[is].delta0;
1151          return parameters;        
1152       }
1153       
1154       // check for mixture
1155       int nmatch = 0;
1156       if( sternDataArray[is].nelems > 1 && sternDataArray[is].nelems == nElem ) {
1157          for(int j=0; j<sternDataArray[is].nelems; j++) {
1158             if( sternDataArray[is].Z[j] == Int_t(zelem[j]) && 
1159                TMath::Abs( (sternDataArray[is].wt[j] - welem[j])/sternDataArray[is].wt[j] ) < 0.1 )
1160             nmatch++;            
1161          }
1162       }
1163
1164       if( sternDataArray[is].nelems > 1 && 
1165           TMath::Abs( (sternDataArray[is].density - rho)/sternDataArray[is].density ) < 0.1 
1166           && nmatch == sternDataArray[is].nelems ) {
1167          cout << sternDataArray[is].longname << "   #elem:" <<  sternDataArray[is].nelems << "  Rho:" 
1168               << sternDataArray[is].density << endl;
1169          cout << sternDataArray[is].iev   << " " 
1170               << sternDataArray[is].cbar  << " " 
1171               << sternDataArray[is].x0    << " " 
1172               << sternDataArray[is].x1    << " " 
1173               << sternDataArray[is].afact << " " 
1174               << sternDataArray[is].sk    << " " 
1175               << sternDataArray[is].delta0 << endl;
1176
1177          parameters[0] = sternDataArray[is].iev;
1178          parameters[1] = sternDataArray[is].cbar;
1179          parameters[2] = sternDataArray[is].x0;
1180          parameters[3] = sternDataArray[is].x1;
1181          parameters[4] = sternDataArray[is].afact;
1182          parameters[5] = sternDataArray[is].sk;
1183          parameters[6] = 0;
1184          return parameters;        
1185       }
1186       is++; 
1187    }   
1188    return parameters;        
1189 }
1190
1191 //_____________________________________________________________________________
1192 void TFlukaMCGeometry::PrintHeader(ofstream &out, const char *text) const
1193 {
1194 // Print a FLUKA header.
1195   out << "*\n" << "*\n" << "*\n";
1196   out << "*********************  " << text << " *********************\n"
1197      << "*\n";
1198   out << "*...+....1....+....2....+....3....+....4....+....5....+....6....+....7..."
1199      << endl;
1200   out << "*" << endl;
1201 }
1202
1203 //_____________________________________________________________________________
1204 Int_t TFlukaMCGeometry::RegionId() const
1205 {
1206 // Returns current region id <-> TGeo node id
1207    if (gGeoManager->IsOutside()) return 0;
1208    return gGeoManager->GetCurrentNode()->GetUniqueID();
1209 }
1210
1211 //_____________________________________________________________________________
1212 Int_t TFlukaMCGeometry::GetElementIndex(Int_t z) const
1213 {
1214 // Get index of a material having a given Z element.
1215    TIter next(fMatList);
1216    TGeoMaterial *mat;
1217    Int_t index = 0;
1218    while ((mat=(TGeoMaterial*)next())) {
1219       if (mat->IsMixture()) continue;
1220       if (mat->GetElement()->Z() == z) return mat->GetIndex();
1221    }
1222    return index;   
1223 }
1224
1225 //_____________________________________________________________________________
1226 void TFlukaMCGeometry::SetMreg(Int_t mreg, Int_t lttc)
1227 {
1228 // Update if needed next history;
1229 //   if (gFluka->GetDummyBoundary()==2) {
1230 //      gGeoManager->CdNode(fNextLattice-1);
1231 //      return;
1232 //   }   
1233    if (lttc == TFlukaMCGeometry::kLttcOutside) {
1234       fCurrentRegion = NofVolumes()+2;
1235       fCurrentLattice = lttc;
1236       gGeoManager->CdTop();
1237       gGeoManager->SetOutside(kTRUE);
1238    }
1239    if (lttc == TFlukaMCGeometry::kLttcVirtual) return;
1240    if (lttc <=0) {
1241       Error("TFlukaMCGeometry::SetMreg","Invalide lattice %i",lttc);
1242       return;
1243    }      
1244    fCurrentRegion = mreg;
1245    fCurrentLattice = lttc;
1246    
1247    Int_t crtlttc = gGeoManager->GetCurrentNodeId()+1;
1248    if (crtlttc == lttc) return;
1249    gGeoManager->CdNode(lttc-1);
1250 }
1251
1252 //_____________________________________________________________________________
1253 void TFlukaMCGeometry::SetCurrentRegion(Int_t mreg, Int_t latt)
1254 {
1255 // Set index/history for next entered region
1256    fCurrentRegion = mreg;
1257    fCurrentLattice = latt;
1258 }   
1259
1260 //_____________________________________________________________________________
1261 void TFlukaMCGeometry::SetNextRegion(Int_t mreg, Int_t latt)
1262 {
1263 // Set index/history for next entered region
1264    fNextRegion = mreg;
1265    fNextLattice = latt;
1266 }   
1267
1268 //_____________________________________________________________________________
1269 void TFlukaMCGeometry::ToFlukaString(TString &str) const
1270 {
1271 // ToFlukaString converts an string to something usefull in FLUKA:
1272 // * Capital letters
1273 // * Only 8 letters
1274 // * Replace ' ' by '_'
1275    if (str.Length()<8) {
1276       str += "        ";
1277    }   
1278    str.Remove(8);
1279    Int_t ilast;
1280    for (ilast=7; ilast>0; ilast--) if (str(ilast)!=' ') break;
1281    str.ToUpper();
1282    for (Int_t pos=0; pos<ilast; pos++)
1283       if (str(pos)==' ') str.Replace(pos,1,"_",1);
1284    return;
1285 }   
1286
1287 //_____________________________________________________________________________
1288 void TFlukaMCGeometry::FlukaMatName(TString &str) const
1289 {
1290 // Strip the detector name
1291      
1292     TObjArray * tokens = str.Tokenize("_");
1293     Int_t ntok = tokens->GetEntries();
1294     if (ntok > 0) {
1295         TString head = ((TObjString*) tokens->At(0))->GetString();
1296         Int_t nhead = head.Length();
1297         str = str.Remove(0, nhead + 1);
1298     }
1299     tokens->Clear();
1300     delete tokens;
1301
1302 // Convert a name to upper case 8 chars.
1303    ToFlukaString(str);
1304    Int_t ilast;
1305    for (ilast=7; ilast>0; ilast--) if (str(ilast)!=' ') break;
1306    if (ilast>5) ilast = 5;
1307    char number[3];
1308    TIter next(fMatNames);
1309    TObjString *objstr;
1310    TString matname;
1311    Int_t index = 0;
1312    while ((objstr=(TObjString*)next())) {
1313       matname = objstr->GetString();
1314       if (matname == str) {
1315          index++;
1316          if (index<10) {
1317             number[0] = '0';
1318             sprintf(&number[1], "%d", index);
1319          } else if (index<100) {
1320             sprintf(number, "%d", index);            
1321          } else {
1322             Error("FlukaMatName", "Too many materials %s", str.Data());
1323             return;
1324          }
1325          str.Replace(ilast+1, 2, number);
1326          str.Remove(8);
1327       }   
1328    }   
1329 }   
1330
1331 //______________________________________________________________________________
1332 void TFlukaMCGeometry::Vname(const char *name, char *vname) const
1333 {
1334   //
1335   //  convert name to upper case. Make vname at least 4 chars
1336   //
1337   Int_t l = strlen(name);
1338   Int_t i;
1339   l = l < 4 ? l : 4;
1340   for (i=0;i<l;i++) vname[i] = toupper(name[i]);
1341   for (i=l;i<4;i++) vname[i] = ' ';
1342   vname[4] = 0;      
1343 }
1344
1345
1346 //______________________________________________________________________________
1347 Int_t TFlukaMCGeometry::GetNstep()
1348 {
1349    // return gNstep for debug propose
1350    return gNstep;
1351 }
1352
1353 // FLUKA GEOMETRY WRAPPERS - to replace FLUGG wrappers
1354
1355 //_____________________________________________________________________________
1356 Int_t idnrwr(const Int_t & /*nreg*/, const Int_t & /*mlat*/)
1357 {
1358 //   from FLUGG:
1359 // Wrapper for setting DNEAR option on fluka side. Must return 0 
1360 // if user doesn't want Fluka to use DNEAR to compute the 
1361 // step (the same effect is obtained with the GLOBAL (WHAT(3)=-1)
1362 // card in fluka input), returns 1 if user wants Fluka always to 
1363 // use DNEAR (in this case, be sure that GEANT4 DNEAR is unique, 
1364 // coming from all directions!!!)
1365    if (gMCGeom->IsDebugging()) printf("========== Dummy IDNRWR\n");
1366    return 0;
1367 }
1368
1369 //_____________________________________________________________________________
1370 void g1wr(Double_t &pSx, Double_t &pSy, Double_t &pSz, 
1371           Double_t *pV,  Int_t &oldReg , const Int_t &oldLttc, Double_t &propStep,
1372           Int_t &/*nascFlag*/, Double_t &retStep, Int_t &newReg,
1373           Double_t &saf, Int_t &newLttc, Int_t &lttcFlag,
1374           Double_t *sLt, Int_t *jrLt)
1375
1376 {
1377    // Initialize FLUKa point and direction;
1378    static Int_t ierr = 0;
1379    gNstep++;
1380 //      gMCGeom->SetDebugMode(kTRUE);
1381    
1382    NORLAT.xn[0] = pSx;
1383    NORLAT.xn[1] = pSy;
1384    NORLAT.xn[2] = pSz;
1385
1386    Int_t olttc = oldLttc;
1387    if (oldLttc<=0) {
1388       gGeoManager->FindNode(pSx,pSy,pSz);
1389       olttc = gGeoManager->GetCurrentNodeId()+1;
1390       oldReg = gGeoManager->GetCurrentVolume()->GetNumber();
1391    }
1392
1393    if (gMCGeom->IsDebugging()) {
1394       cout << "g1wr gNstep=" << gNstep << " oldReg="<< oldReg <<" olttc="<< olttc
1395            << " track=" << TRACKR.ispusr[mkbmx2-1] << endl;
1396       cout << " point: (" << pSx << ", " << pSy << ", " << pSz << ")  dir: ("
1397            << pV[0] << ", " << pV[1] << ", " << pV[2] << ")" << endl;
1398    }        
1399            
1400
1401    Int_t ccreg=0,cclat=0;
1402    gMCGeom->GetCurrentRegion(ccreg,cclat);
1403    Bool_t crossed = (ccreg==oldReg && cclat==olttc)?kFALSE:kTRUE;
1404
1405    gMCGeom->SetCurrentRegion(oldReg, olttc);
1406    // Initialize default return values
1407    lttcFlag = 0;
1408    jrLt[lttcFlag] = olttc;
1409    sLt[lttcFlag] = propStep;
1410    jrLt[lttcFlag+1] = -1;
1411    sLt[lttcFlag+1] = 0.;
1412    newReg = oldReg;
1413    newLttc = olttc;
1414    Bool_t crossedDummy = (oldReg == gFluka->GetDummyRegion())?kTRUE:kFALSE;
1415    Int_t curLttc, curReg;
1416    if (crossedDummy) {
1417    // FLUKA crossed the dummy boundary - update new region/history
1418       retStep = TGeoShape::Tolerance();
1419       saf = 0.;
1420       gMCGeom->GetNextRegion(newReg, newLttc);
1421       gMCGeom->SetMreg(newReg, newLttc);
1422       sLt[lttcFlag] = TGeoShape::Tolerance(); // null step in current region
1423       lttcFlag++;
1424       jrLt[lttcFlag] = newLttc;
1425       sLt[lttcFlag] = TGeoShape::Tolerance(); // null step in next region
1426       jrLt[lttcFlag+1] = -1;
1427       sLt[lttcFlag+1] = 0.; // null step in next region;
1428       if (gMCGeom->IsDebugging()) printf("=> crossed dummy!! newReg=%i newLttc=%i\n", newReg, newLttc);
1429       return;
1430    }
1431
1432    // Reset outside flag
1433    gGeoManager->SetOutside(kFALSE);
1434
1435    curLttc = gGeoManager->GetCurrentNodeId()+1;
1436    curReg = gGeoManager->GetCurrentVolume()->GetNumber();
1437    if (olttc != curLttc) {
1438       // FLUKA crossed the boundary : we trust that the given point is really there,
1439       // so we just update TGeo state
1440       gGeoManager->CdNode(olttc-1);
1441       curLttc = gGeoManager->GetCurrentNodeId()+1;
1442       curReg  = gGeoManager->GetCurrentVolume()->GetNumber();
1443    }
1444    // Now the current TGeo state reflects the FLUKA state 
1445
1446    gGeoManager->SetCurrentPoint(pSx, pSy, pSz);
1447    gGeoManager->SetCurrentDirection(pV);
1448    Double_t pt[3], local[3], ldir[3];
1449    Int_t pid = TRACKR.jtrack;
1450    pt[0] = pSx;
1451    pt[1] = pSy;
1452    pt[2] = pSz;
1453    gGeoManager->MasterToLocal(pt,local);
1454    gGeoManager->MasterToLocalVect(pV,ldir);
1455 /*
1456    Bool_t valid = gGeoManager->GetCurrentVolume()->Contains(local);
1457    if (!valid) {
1458       printf("location not valid in %s pid=%i\n", gGeoManager->GetPath(),pid);
1459       printf("local:(%f, %f, %f)  ldir:(%f, %f, %f)\n", local[0],local[1],local[2],ldir[0],ldir[1],ldir[2]);
1460 //      gGeoManager->FindNode();
1461 //      printf("   -> actual location: %s\n", gGeoManager->GetPath());
1462    }   
1463 */
1464    Double_t pstep = propStep;
1465    Double_t snext = propStep;
1466    const Double_t epsil = 0.9999999 * TGeoShape::Tolerance();
1467    // This should never happen !!!
1468    if (pstep<TGeoShape::Tolerance()) {
1469       printf("Proposed step is 0 !!!\n");
1470       pstep = 2.*TGeoShape::Tolerance();
1471    }   
1472    if (crossed) {
1473       gGeoManager->FindNextBoundaryAndStep(pstep);
1474       snext = gGeoManager->GetStep();
1475       saf = 0.;
1476       if (snext <= TGeoShape::Tolerance()) {
1477 //         printf("FLUKA crossed boundary but snext=%g\n", snext);
1478          ierr++;
1479          snext = epsil;
1480       } else {
1481          snext += TGeoShape::Tolerance();
1482          ierr = 0;
1483       }     
1484    } else {
1485       gGeoManager->FindNextBoundaryAndStep(pstep, kTRUE);
1486       snext = gGeoManager->GetStep();
1487       saf = gGeoManager->GetSafeDistance();
1488       if (snext <= TGeoShape::Tolerance()) {
1489 //         printf("FLUKA put particle on bondary without crossing\n");
1490          ierr++;
1491          snext = epsil;
1492          saf = 0.;
1493       } else {
1494          snext += TGeoShape::Tolerance();
1495          ierr = 0;
1496       }      
1497       if (saf<0) saf=0.;
1498       saf -= saf*3.0e-09;
1499    }
1500 //   if (ierr>1) {
1501 //      printf("%d snext=%g\n", ierr, snext);
1502 //   }   
1503    if (ierr == 10) {
1504 //      printf("Too many null steps - sending error code -33...\n");
1505       newReg = -33;   // Error code
1506       ierr = 0;
1507       return;
1508    }   
1509    
1510    PAREM.dist = snext;
1511    NORLAT.distn = snext;
1512    NORLAT.xn[0] += snext*pV[0];
1513    NORLAT.xn[1] += snext*pV[1];
1514    NORLAT.xn[2] += snext*pV[2];
1515    if (!gGeoManager->IsOnBoundary()) {
1516    // Next boundary further than proposed step, which is approved
1517       if (saf>propStep) saf = propStep;
1518       retStep = propStep;
1519       sLt[lttcFlag] = propStep;
1520       return;
1521    }
1522    if (saf>snext) saf = snext; // Safety should be less than the proposed step if a boundary will be crossed
1523    gGeoManager->SetCurrentPoint(pSx,pSy,pSz);
1524    newLttc = (gGeoManager->IsOutside())?(TFlukaMCGeometry::kLttcOutside):gGeoManager->GetCurrentNodeId()+1;
1525    newReg = (gGeoManager->IsOutside())?(gMCGeom->NofVolumes()+2):gGeoManager->GetCurrentVolume()->GetNumber();
1526    if (gMCGeom->IsDebugging()) printf("=> newReg=%i newLttc=%i\n", newReg, newLttc);
1527
1528    // We really crossed the boundary, but is it the same region ?
1529    gMCGeom->SetNextRegion(newReg, newLttc);
1530
1531    if ( ((newReg==oldReg && newLttc!=olttc) || (oldReg!=newReg && olttc==newLttc) ) && pid!=-1) {
1532       // Virtual boundary between replicants
1533       newReg  = gFluka->GetDummyRegion();
1534       newLttc = TFlukaMCGeometry::kLttcVirtual;
1535       if (gMCGeom->IsDebugging()) printf("=> virtual boundary!! newReg=%i newLttc=%i\n", newReg, newLttc);
1536    }
1537
1538    retStep = snext;
1539    sLt[lttcFlag] = snext;
1540    lttcFlag++;
1541    jrLt[lttcFlag] = newLttc;
1542    sLt[lttcFlag] = snext;
1543    jrLt[lttcFlag+1] = -1;
1544
1545    sLt[lttcFlag+1] = 0.;
1546    gGeoManager->SetOutside(kFALSE);
1547    gGeoManager->CdNode(olttc-1);
1548    if (gMCGeom->IsDebugging()) {
1549       printf("=> snext=%g safe=%g\n", snext, saf);
1550       for (Int_t i=0; i<lttcFlag+1; i++) printf("   jrLt[%i]=%i  sLt[%i]=%g\n", i,jrLt[i],i,sLt[i]);
1551    }
1552 }
1553
1554 //_____________________________________________________________________________
1555 void g1rtwr()
1556 {
1557
1558    if (gMCGeom->IsDebugging()) printf("========== Dummy G1RTWR\n");
1559
1560
1561 //_____________________________________________________________________________
1562 void conhwr(Int_t & intHist, Int_t & incrCount)
1563 {
1564    if (gMCGeom->IsDebugging()) printf("========== Dummy CONHWR intHist=%d incrCount=%d currentNodeId=%d\n",
1565                                        intHist, incrCount, gGeoManager->GetCurrentNodeId()+1 );
1566 //   if( incrCount != -1 ) {
1567 //      if (intHist==0) gGeoManager->CdTop();
1568 //      else gGeoManager->CdNode(intHist-1);
1569 //   }
1570 //   intHist = gGeoManager->GetCurrentNodeId()+1;
1571 }
1572
1573 //_____________________________________________________________________________
1574 void inihwr(Int_t &intHist)
1575 {
1576    if (gMCGeom->IsDebugging())
1577       printf("========== Inside INIHWR -> reinitializing history: %i \n", intHist);
1578    if (gGeoManager->IsOutside()) gGeoManager->CdTop();
1579    if (intHist<0) {
1580 //      printf("=== wrong history number\n");
1581       return;
1582    }
1583    if (intHist==0) gGeoManager->CdTop();
1584    else gGeoManager->CdNode(intHist-1);
1585    if (gMCGeom->IsDebugging()) {
1586       printf(" --- current path: %s\n", gGeoManager->GetPath());
1587       printf("<= INIHWR\n");
1588    }
1589 }
1590
1591 //_____________________________________________________________________________
1592 void  jomiwr(const Int_t & /*nge*/, const Int_t & /*lin*/, const Int_t & /*lou*/,
1593              Int_t &flukaReg)
1594 {
1595 // Geometry initialization wrapper called by FLUKAM. Provides to FLUKA the
1596 // number of regions (volumes in TGeo)
1597    // build application geometry
1598    if (gMCGeom->IsDebugging()) printf("========== Inside JOMIWR\n");
1599    flukaReg = gGeoManager->GetListOfUVolumes()->GetEntriesFast()+1;
1600    if (gMCGeom->IsDebugging()) printf("<= JOMIWR: last region=%i\n", flukaReg);
1601 }   
1602
1603 //_____________________________________________________________________________
1604 void lkdbwr(Double_t &pSx, Double_t &pSy, Double_t &pSz,
1605             Double_t *pV, const Int_t &oldReg, const Int_t &oldLttc,
1606             Int_t &flagErr, Int_t &newReg, Int_t &newLttc)             
1607 {
1608    if (gMCGeom->IsDebugging()) {
1609       printf("========== Inside LKDBWR (%f, %f, %f)\n",pSx, pSy, pSz);
1610       printf("   in: pV=(%f, %f, %f)\n", pV[0], pV[1], pV[2]);
1611       printf("   in: oldReg=%i oldLttc=%i\n", oldReg, oldLttc);
1612    }   
1613    lkwr(pSx,pSy,pSz,pV,oldReg,oldLttc,flagErr,newReg,newLttc);
1614 }
1615
1616 //_____________________________________________________________________________
1617 void lkfxwr(Double_t &pSx, Double_t &pSy, Double_t &pSz,
1618             Double_t *pV, const Int_t &oldReg, const Int_t &oldLttc,
1619             Int_t &flagErr, Int_t &newReg, Int_t &newLttc)
1620 {
1621    if (gMCGeom->IsDebugging()) {
1622       printf("========== Inside LKFXWR (%f, %f, %f)\n",pSx, pSy, pSz);
1623       printf("   in: pV=(%f, %f, %f)\n", pV[0], pV[1], pV[2]);
1624       printf("   in: oldReg=%i oldLttc=%i\n", oldReg, oldLttc);
1625    }   
1626    lkwr(pSx,pSy,pSz,pV,oldReg,oldLttc,flagErr,newReg,newLttc);
1627 }
1628
1629 //_____________________________________________________________________________
1630 void lkmgwr(Double_t &pSx, Double_t &pSy, Double_t &pSz,
1631             Double_t *pV, const Int_t &oldReg, const Int_t &oldLttc,
1632             Int_t &flagErr, Int_t &newReg, Int_t &newLttc)
1633 {
1634    if (gMCGeom->IsDebugging()) {
1635       printf("========== Inside LKMGWR (%f, %f, %f)\n",pSx, pSy, pSz);
1636       printf("   in: pV=(%f, %f, %f)\n", pV[0], pV[1], pV[2]);
1637       printf("   in: oldReg=%i oldLttc=%i\n", oldReg, oldLttc);
1638    }   
1639    lkwr(pSx,pSy,pSz,pV,oldReg,oldLttc,flagErr,newReg,newLttc);
1640 }
1641
1642 //_____________________________________________________________________________
1643 void lkwr(Double_t &pSx, Double_t &pSy, Double_t &pSz,
1644           Double_t *pV, const Int_t &oldReg, const Int_t &oldLttc,
1645           Int_t &flagErr, Int_t &newReg, Int_t &newLttc)
1646 {
1647    if (gMCGeom->IsDebugging()) {
1648       printf("========== Inside LKWR (%f, %f, %f)\n",pSx, pSy, pSz);
1649       printf("   in: pV=(%f, %f, %f)\n", pV[0], pV[1], pV[2]);
1650       printf("   in: oldReg=%i oldLttc=%i\n", oldReg, oldLttc);
1651    }   
1652    flagErr = 0;
1653    Double_t epsil = 1000.*TGeoShape::Tolerance();
1654    TGeoNode *node = gGeoManager->FindNode(pSx+epsil*pV[0], pSy+epsil*pV[1], pSz+epsil*pV[2]);
1655    if (gGeoManager->IsOutside()) {
1656       newReg = gMCGeom->NofVolumes()+2;
1657       newLttc = TFlukaMCGeometry::kLttcOutside;
1658       gGeoManager->SetOutside(kFALSE);
1659       if (oldLttc>0 && oldLttc<newLttc) gGeoManager->CdNode(oldLttc-1);
1660       return;
1661    } 
1662    gGeoManager->SetOutside(kFALSE);
1663    newReg = node->GetVolume()->GetNumber();
1664    newLttc = gGeoManager->GetCurrentNodeId()+1;
1665    if (oldLttc==TFlukaMCGeometry::kLttcOutside || oldLttc==0) return;
1666
1667    Int_t dummy = gFluka->GetDummyRegion();
1668    if (oldReg==dummy) {
1669       Int_t newreg1, newlttc1;
1670       gMCGeom->GetNextRegion(newreg1, newlttc1);
1671       if (newreg1==newReg && newlttc1==newLttc) {
1672          newReg = dummy;
1673          newLttc = TFlukaMCGeometry::kLttcVirtual;
1674          flagErr = newReg;
1675          if (gMCGeom->IsDebugging()) printf("  virtual boundary (oldReg==dummy) !! newReg=%i newLttc=%i\n", newReg, newLttc);
1676       }
1677       return;
1678    }
1679
1680    if (oldReg==newReg && oldLttc!=newLttc) {
1681       newReg  = dummy;
1682       newLttc = TFlukaMCGeometry::kLttcVirtual;
1683       if (gMCGeom->IsDebugging()) printf("  virtual boundary!! newReg=%i newLttc=%i\n", newReg, newLttc);
1684    }
1685
1686    if( oldReg!=newReg && oldLttc==newLttc ) {
1687       // this should not happen!! ??? Ernesto
1688 //       cout << "  lkwr      oldReg!=newReg ("<< oldReg <<"!="<< newReg
1689 //            << ") && oldLttc==newLttc ("<< newLttc <<") !!!!!!!!!!!!!!!!!" << endl;
1690       newReg  = dummy;
1691       newLttc = TFlukaMCGeometry::kLttcVirtual;
1692       flagErr = newReg;
1693    }
1694
1695    if (gMCGeom->IsDebugging()) {
1696       printf("  LKWR: newReg=%i newLttc=%i\n", newReg, newLttc);
1697    }   
1698 }
1699
1700 //_____________________________________________________________________________
1701 void nrmlwr(Double_t &pSx, Double_t &pSy, Double_t &pSz,
1702             Double_t &pVx, Double_t &pVy, Double_t &pVz,
1703             Double_t *norml, const Int_t &oldReg,
1704             const Int_t &newReg, Int_t &flagErr)
1705 {
1706    if (gMCGeom->IsDebugging()) {
1707       printf("========== Inside NRMLWR (%g, %g, %g, %g, %g, %g)\n", pSx,pSy,pSz,pVx,pVy,pVz);
1708       printf("                         (%g, %g, %g)\n", NORLAT.xn[0], NORLAT.xn[1], NORLAT.xn[2]);
1709       printf("   oldReg=%i, newReg=%i\n", oldReg,newReg);
1710    }   
1711    gGeoManager->SetCurrentPoint(NORLAT.xn[0], NORLAT.xn[1], NORLAT.xn[2]);
1712    gGeoManager->SetCurrentDirection(pVx, pVy, pVz);
1713    Double_t *dnorm = gGeoManager->FindNormalFast();
1714    flagErr = 0;
1715    if (!dnorm) {
1716       printf("   ERROR: Cannot compute fast normal\n");
1717       flagErr = 1;
1718       norml[0] = -pVx;   
1719       norml[1] = -pVy;   
1720       norml[2] = -pVz; 
1721    } else {
1722       norml[0] = -dnorm[0];
1723       norml[1] = -dnorm[1];
1724       norml[2] = -dnorm[2];
1725    }  
1726
1727    if (gMCGeom->IsDebugging()) {
1728       printf("   normal to boundary: (%g, %g, %g)\n", norml[0], norml[1], norml[2]);  
1729       printf("<= NRMLWR\n");
1730    }
1731
1732 }
1733
1734 //_____________________________________________________________________________
1735 void rgrpwr(const Int_t & /*flukaReg*/, const Int_t & /*ptrLttc*/, Int_t & /*g4Reg*/,
1736             Int_t * /*indMother*/, Int_t * /*repMother*/, Int_t & /*depthFluka*/)
1737 {
1738    if (gMCGeom->IsDebugging()) printf("=> Dummy RGRPWR\n");
1739 }
1740
1741 //_____________________________________________________________________________
1742 Int_t isvhwr(const Int_t &check, const Int_t & intHist)
1743 {
1744 //   from FLUGG:
1745 // Wrapper for saving current navigation history (fCheck=default) 
1746 // and returning its pointer. If fCheck=-1 copy of history pointed 
1747 // by intHist is made in NavHistWithCount object, and its pointer 
1748 // is returned. fCheck=1 and fCheck=2 cases are only in debugging 
1749 // version: an array is created by means of FGeometryInit functions
1750 // (but could be a static int * ptrArray = new int[10000] with 
1751 // file scope as well) that stores a flag for deleted/undeleted 
1752 // histories and at the end of event is checked to verify that 
1753 // all saved history objects have been deleted.
1754
1755 // For TGeo, just return the current node ID. No copy need to be made.
1756
1757    if (gMCGeom->IsDebugging()) printf("=> Inside ISVHWR check=%d intHist=%d\n", check, intHist);
1758    if (check<0) return intHist;
1759    Int_t histInt = gGeoManager->GetCurrentNodeId()+1;
1760    if (gMCGeom->IsDebugging()) printf("<= ISVHWR: history is: %i in: %s\n", histInt, gGeoManager->GetPath());
1761    return histInt;
1762 }
1763
1764
1765
1766