1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
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
26 #include "Riostream.h"
31 #include "TFlukaMCGeometry.h"
32 #include "TFlukaConfigOption.h"
33 #include "TGeoManager.h"
34 #include "TGeoVolume.h"
35 #include "TObjString.h"
38 #include "Fstepsz.h" //(STEPSZ) fluka common
41 # define idnrwr idnrwr_
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_
51 # define magfld magfld_
52 # define nrmlwr nrmlwr_
53 # define rgrpwr rgrpwr_
54 # define isvhwr isvhwr_
58 # define idnrwr IDNRWR
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
68 # define magfld MAGFLD
69 # define nrmlwr NRMLWR
70 # define rgrpwr RGRPWR
71 # define isvhwr ISVHWR
75 //____________________________________________________________________________
79 // Prototypes for FLUKA navigation methods
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*/);
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*/);
117 // TFluka global pointer
119 TFlukaMCGeometry *gMCGeom = 0;
122 ClassImp(TFlukaMCGeometry)
124 TFlukaMCGeometry* TFlukaMCGeometry::fgInstance= NULL;
126 //_____________________________________________________________________________
127 TFlukaMCGeometry::TFlukaMCGeometry(const char *name, const char *title)
128 :TNamed(name, title),
138 fMatList(new TObjArray(256)),
139 fMatNames(new TObjArray(256))
142 // Standard constructor
144 gFluka = (TFluka*)gMC;
149 //_____________________________________________________________________________
150 TFlukaMCGeometry::TFlukaMCGeometry()
166 // Default constructor
168 gFluka = (TFluka*)gMC;
173 //_____________________________________________________________________________
174 TFlukaMCGeometry::~TFlukaMCGeometry()
180 if (fRegionList) delete [] fRegionList;
181 if (fMatList) delete fMatList;
182 if (fMatNames) {fMatNames->Delete(); delete fMatNames;}
183 if (gGeoManager) delete gGeoManager;
190 //_____________________________________________________________________________
191 Double_t* TFlukaMCGeometry::CreateDoubleArray(Float_t* array, Int_t size) const
193 // Converts Float_t* array to Double_t*,
194 // !! The new array has to be deleted by user.
197 Double_t* doubleArray;
199 doubleArray = new Double_t[size];
200 for (Int_t i=0; i<size; i++) doubleArray[i] = array[i];
204 doubleArray = new Double_t[1];
212 //_____________________________________________________________________________
213 Int_t TFlukaMCGeometry::GetMedium() const
215 // Get current medium number
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);
224 //_____________________________________________________________________________
225 Int_t TFlukaMCGeometry::GetFlukaMaterial(Int_t imed) const
227 // Returns FLUKA material index for medium IMED
228 TGeoMedium *med = (TGeoMedium*)gGeoManager->GetListOfMedia()->At(imed-1);
230 Error("GetFlukaMaterial", "MEDIUM %i nor found", imed);
233 TGeoMaterial* mat = med->GetMaterial();
234 if (!mat->IsUsed()) return -1;
235 Int_t imatfl = med->GetMaterial()->GetIndex();
239 //_____________________________________________________________________________
240 Int_t *TFlukaMCGeometry::GetRegionList(Int_t imed, Int_t &nreg)
242 // Get an ordered list of regions matching a given medium number
244 if (!fRegionList) fRegionList = new Int_t[NofVolumes()+1];
245 TIter next(gGeoManager->GetListOfUVolumes());
248 while ((vol = (TGeoVolume*)next())) {
250 if ((med = vol->GetMedium()) == 0) continue;
251 imedium = med->GetId();
252 if (imedium == imed) {
253 ireg = vol->GetNumber();
254 fRegionList[nreg++] = ireg;
260 //_____________________________________________________________________________
261 Int_t *TFlukaMCGeometry::GetMaterialList(Int_t imat, Int_t &nreg)
263 // Get an ordered list of regions matching a given medium number
265 if (!fRegionList) fRegionList = new Int_t[NofVolumes()+1];
266 TIter next(gGeoManager->GetListOfUVolumes());
268 Int_t imaterial, ireg;
269 while ((vol = (TGeoVolume*)next())) {
271 if ((med = vol->GetMedium()) == 0) continue;
272 imaterial = med->GetMaterial()->GetIndex();
273 if (imaterial == imat) {
274 ireg = vol->GetNumber();
275 fRegionList[nreg++] = ireg;
281 //_____________________________________________________________________________
282 Int_t TFlukaMCGeometry::NofVolumes() const
285 // Return total number of volumes in the geometry
288 return gGeoManager->GetListOfUVolumes()->GetEntriesFast()-1;
291 //_____________________________________________________________________________
292 TGeoMaterial * TFlukaMCGeometry::GetMakeWrongMaterial(Double_t z)
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};
301 for (ind=0; ind<23; ind++) {
302 dz = TMath::Abs(z-kz[ind]);
306 printf("Cannot patch material with Z=%g\n", z);
309 TGeoMixture *mix = 0;
310 TGeoElement *element;
311 TGeoElementTable *table = gGeoManager->GetElementTable();
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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.);
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.);
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.);
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.);
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.);
566 printf("Patched with mixture %s\n", mix->GetName());
570 //_____________________________________________________________________________
571 void TFlukaMCGeometry::CreateFlukaMatFile(const char *fname)
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.
583 gGeoManager->Export("flgeom.root");
584 if (fname) sname = fname;
585 else sname = "flukaMat.inp";
587 out.open(sname.Data(), ios::out);
589 Fatal("CreateFlukaMatFile", "could not open file %s for writing", sname.Data());
592 PrintHeader(out, "MATERIALS AND COMPOUNDS");
593 PrintHeader(out, "MATERIALS");
595 Int_t counttothree, nelem;
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();
610 Int_t nmater = matlist->GetSize();
613 TGeoMixture *mix = 0;
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);
625 mat = new TGeoMaterial(matname, element->A(), element->Z(), rho);
626 mat->SetIndex(nfmater+3);
629 objstr = new TObjString(matname.Data());
630 fMatNames->Add(objstr);
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;
642 rho = mat->GetDensity();
643 if (mat->GetZ()<0.001) {
644 mat->SetIndex(2); // vacuum, built-in inside FLUKA
647 matname = mat->GetName();
648 FlukaMatName(matname);
650 mat->SetIndex(nfmater+3);
651 objstr = new TObjString(matname.Data());
653 fMatNames->Add(objstr);
657 // Dump all elements with MATERIAL cards
658 for (i=0; i<nfmater; i++) {
659 mat = (TGeoMaterial*)fMatList->At(i);
660 // mat->SetUsed(kFALSE);
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();
668 rho = mat->GetDensity();
669 if (mat->IsMixture()) {
670 out << setw(10) << " ";
671 out << setw(10) << " ";
672 mix = (TGeoMixture*)mat;
674 out << setw(10) << setiosflags(ios::fixed) << setprecision(1) << z;
675 out << setw(10) << setprecision(3) << a;
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;
685 // add LOW-MAT card for NEON to associate with ARGON neutron xsec
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;
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;
720 out << setw(8) << elename.Data() << endl;
721 // out << setw(8) << " " << endl;
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);
743 if (counttothree == 3) {
744 out << matname.Data();
746 if ( (j+1) != nelem) out << setw(10) << "COMPOUND ";
751 for (j=0; j<(3-(nelem%3)); j++)
752 out << setw(10) << " " << setw(10) << " ";
753 out << matname.Data();
757 Int_t nvols = gGeoManager->GetListOfUVolumes()->GetEntriesFast()-1;
759 // Now print the material assignments
760 Double_t flagfield = 0.;
761 printf("#############################################################\n");
762 if (gFluka->IsFieldEnabled()) {
764 printf("Magnetic field enabled\n");
765 } else printf("Magnetic field disabled\n");
766 printf("#############################################################\n");
768 PrintHeader(out, "TGEO MATERIAL ASSIGNMENTS");
769 for (i=1; i<=nvols; i++) {
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);
780 Float_t hasfield = (vol->GetMedium()->GetParam(1) > 0) ? flagfield : 0.;
781 out << "* Assigning material: " << vol->GetMedium()->GetMaterial()->GetName() << " to Volume: " << vol->GetName();
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";
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;
807 fLastMaterial = nfmater+2;
810 void TFlukaMCGeometry::CreatePemfFile()
813 // Steering routine to write and process peg files producing the pemf input
816 Int_t countMatOK = 0;
817 Int_t countElemError = 0;
818 Int_t countNoStern = 0;
819 Int_t countMixError = 0;
821 Int_t countPemfError = 0;
823 TGeoMaterial* mat = 0x0;
826 for (i = fIndmat; i < fLastMaterial - 2; i++) {
827 printf("Write Peg Files %d\n", i);
829 mat = (TGeoMaterial*)fMatList->At(i);
830 if (!mat->IsUsed()) continue;
832 sprintf(number, "%d", i);
833 sname.Append(number);
836 cout << "******************************************************************************" << endl;
837 cout << "******************************************************************************" << endl;
839 WritePegFile(i, &countNoStern, &countElemError, &countMixError, &countGas);
840 sname.Prepend("$FLUPRO/pemf/rpemf peg/");
841 gSystem->Exec(sname.Data());
843 // check if the pemf file was created
844 TString sname = Form("peg/mat%d.pemf", i);
845 ifstream in( sname.Data() );
850 cout << "ERROR Fail to create the pemf file " << sname << endl;
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;
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());
869 //_____________________________________________________________________________
870 void TFlukaMCGeometry::WritePegFile(Int_t imat, Int_t *NoStern, Int_t *ElemError,
871 Int_t *MixError, Int_t *countGas) const
873 // Write the .peg file for one material
875 TGeoMaterial *mat = (TGeoMaterial*)fMatList->At(imat);
876 TString name = ((TObjString*)fMatNames->At(imat))->GetString();
879 TGeoElement *elem = mat->GetElement();
881 TString sname = "mat";
882 sprintf(number, "%d", imat);
883 sname.Append(number);
884 sname.Append(".peg");
885 sname.Prepend("peg/");
887 out.open(sname.Data(), ios::out);
888 if (!out.good()) return;
889 Double_t dens = mat->GetDensity();
890 TGeoMixture *mix = 0;
893 if (mat->IsMixture()) {
894 mix = (TGeoMixture*)mat;
895 nel = mix->GetNelements();
899 cout << "( Element ) " << name << " Z=" << mat->GetZ() << " Rho " << mat->GetDensity() << endl;
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;
909 out << "ELEM" << endl;
910 out << " &INP IRAYL=1, RHO=" << dens << ", " << endl;
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];
922 cout << "WARNING: Strange element, Sternheimer parameters not found" << endl;
928 out << " GASP=1." << endl;
931 out << " &END" << endl;
932 out << name.Data() << endl;
933 out << elem->GetName() << endl;
938 cout << "( Mixture ) " << name << " Rho " << dens << " nElem " << nel << endl;
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;
949 // just continue since the mixtures are not patch,
950 // but the final release should include the return
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 = ""; }
963 out << " RHO=" << mat->GetDensity() << ", ";
964 line += Form(" RHO=%g, ", mat->GetDensity());
965 if( line.Length() > 60 ) { out << endl; line = ""; }
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 = ""; }
989 cout << "Sternheimer parameters not found" << endl;
995 out << " GASP=1." << endl;
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() << " ";
1012 Double_t ue = 3000000.; // [MeV]
1013 Double_t up = 3000000.; // [MeV]
1018 TObjArray* cutList = ((TFluka*) gMC)->GetListOfUserConfigs();
1019 TIter next(cutList);
1020 TFlukaConfigOption* proc;
1022 while((proc = (TFlukaConfigOption*)next()))
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);
1033 if (ap == -1.) ap = TFlukaConfigOption::DefaultCut(kCUTGAM);
1034 if (ae == -1.) ae = TFlukaConfigOption::DefaultCut(kCUTELE);
1036 ap *= 1000.; // [MeV]
1037 ae = (ae + 0.00051099906) * 1000.; // [MeV]
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;
1050 Double_t * TFlukaMCGeometry::GetISSB(Double_t rho, Int_t nElem, Double_t *zelem, Double_t *welem ) const
1052 // Read the density effect parameters
1053 // from R.M. Sternheimer et al. Atomic Data
1054 // and Nuclear Data Tables, Vol. 30 No. 2
1056 // return the parameters if the element/mixture match with one of the list
1057 // otherwise returns the parameters set to 0
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
1070 Double_t afact; // AFACT
1072 Double_t delta0; // DELTA0
1075 longname(""), nelems(0), density(0), iev(0), cbar(0),
1076 x0(0), x1(0), afact(0), sk(0), delta0(0) {}
1084 static Double_t parameters[7];
1085 memset( parameters, 0, sizeof(Double_t) );
1087 static sternheimerData sternDataArray[300];
1088 static Bool_t isFileRead = kFALSE;
1090 // Read the data file if is needed
1091 if( isFileRead == kFALSE ) {
1092 TString sSternheimerInp = getenv("ALICE_ROOT");
1093 sSternheimerInp +="/TFluka/input/Sternheimer.data";
1095 ifstream in(sSternheimerInp);
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);
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];
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;
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;
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;
1154 // check for mixture
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 )
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;
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;
1191 //_____________________________________________________________________________
1192 void TFlukaMCGeometry::PrintHeader(ofstream &out, const char *text) const
1194 // Print a FLUKA header.
1195 out << "*\n" << "*\n" << "*\n";
1196 out << "********************* " << text << " *********************\n"
1198 out << "*...+....1....+....2....+....3....+....4....+....5....+....6....+....7..."
1203 //_____________________________________________________________________________
1204 Int_t TFlukaMCGeometry::RegionId() const
1206 // Returns current region id <-> TGeo node id
1207 if (gGeoManager->IsOutside()) return 0;
1208 return gGeoManager->GetCurrentNode()->GetUniqueID();
1211 //_____________________________________________________________________________
1212 Int_t TFlukaMCGeometry::GetElementIndex(Int_t z) const
1214 // Get index of a material having a given Z element.
1215 TIter next(fMatList);
1218 while ((mat=(TGeoMaterial*)next())) {
1219 if (mat->IsMixture()) continue;
1220 if (mat->GetElement()->Z() == z) return mat->GetIndex();
1225 //_____________________________________________________________________________
1226 void TFlukaMCGeometry::SetMreg(Int_t mreg, Int_t lttc)
1228 // Update if needed next history;
1229 // if (gFluka->GetDummyBoundary()==2) {
1230 // gGeoManager->CdNode(fNextLattice-1);
1233 if (lttc == TFlukaMCGeometry::kLttcOutside) {
1234 fCurrentRegion = NofVolumes()+2;
1235 fCurrentLattice = lttc;
1236 gGeoManager->CdTop();
1237 gGeoManager->SetOutside(kTRUE);
1239 if (lttc == TFlukaMCGeometry::kLttcVirtual) return;
1241 Error("TFlukaMCGeometry::SetMreg","Invalide lattice %i",lttc);
1244 fCurrentRegion = mreg;
1245 fCurrentLattice = lttc;
1247 Int_t crtlttc = gGeoManager->GetCurrentNodeId()+1;
1248 if (crtlttc == lttc) return;
1249 gGeoManager->CdNode(lttc-1);
1252 //_____________________________________________________________________________
1253 void TFlukaMCGeometry::SetCurrentRegion(Int_t mreg, Int_t latt)
1255 // Set index/history for next entered region
1256 fCurrentRegion = mreg;
1257 fCurrentLattice = latt;
1260 //_____________________________________________________________________________
1261 void TFlukaMCGeometry::SetNextRegion(Int_t mreg, Int_t latt)
1263 // Set index/history for next entered region
1265 fNextLattice = latt;
1268 //_____________________________________________________________________________
1269 void TFlukaMCGeometry::ToFlukaString(TString &str) const
1271 // ToFlukaString converts an string to something usefull in FLUKA:
1272 // * Capital letters
1274 // * Replace ' ' by '_'
1275 if (str.Length()<8) {
1280 for (ilast=7; ilast>0; ilast--) if (str(ilast)!=' ') break;
1282 for (Int_t pos=0; pos<ilast; pos++)
1283 if (str(pos)==' ') str.Replace(pos,1,"_",1);
1287 //_____________________________________________________________________________
1288 void TFlukaMCGeometry::FlukaMatName(TString &str) const
1290 // Strip the detector name
1292 TObjArray * tokens = str.Tokenize("_");
1293 Int_t ntok = tokens->GetEntries();
1295 TString head = ((TObjString*) tokens->At(0))->GetString();
1296 Int_t nhead = head.Length();
1297 str = str.Remove(0, nhead + 1);
1302 // Convert a name to upper case 8 chars.
1305 for (ilast=7; ilast>0; ilast--) if (str(ilast)!=' ') break;
1306 if (ilast>5) ilast = 5;
1308 TIter next(fMatNames);
1312 while ((objstr=(TObjString*)next())) {
1313 matname = objstr->GetString();
1314 if (matname == str) {
1318 sprintf(&number[1], "%d", index);
1319 } else if (index<100) {
1320 sprintf(number, "%d", index);
1322 Error("FlukaMatName", "Too many materials %s", str.Data());
1325 str.Replace(ilast+1, 2, number);
1331 //______________________________________________________________________________
1332 void TFlukaMCGeometry::Vname(const char *name, char *vname) const
1335 // convert name to upper case. Make vname at least 4 chars
1337 Int_t l = strlen(name);
1340 for (i=0;i<l;i++) vname[i] = toupper(name[i]);
1341 for (i=l;i<4;i++) vname[i] = ' ';
1346 //______________________________________________________________________________
1347 Int_t TFlukaMCGeometry::GetNstep()
1349 // return gNstep for debug propose
1353 // FLUKA GEOMETRY WRAPPERS - to replace FLUGG wrappers
1355 //_____________________________________________________________________________
1356 Int_t idnrwr(const Int_t & /*nreg*/, const Int_t & /*mlat*/)
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");
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 <tcFlag,
1374 Double_t *sLt, Int_t *jrLt)
1377 // Initialize FLUKa point and direction;
1378 static Int_t ierr = 0;
1380 // gMCGeom->SetDebugMode(kTRUE);
1386 Int_t olttc = oldLttc;
1388 gGeoManager->FindNode(pSx,pSy,pSz);
1389 olttc = gGeoManager->GetCurrentNodeId()+1;
1390 oldReg = gGeoManager->GetCurrentVolume()->GetNumber();
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;
1401 Int_t ccreg=0,cclat=0;
1402 gMCGeom->GetCurrentRegion(ccreg,cclat);
1403 Bool_t crossed = (ccreg==oldReg && cclat==olttc)?kFALSE:kTRUE;
1405 gMCGeom->SetCurrentRegion(oldReg, olttc);
1406 // Initialize default return values
1408 jrLt[lttcFlag] = olttc;
1409 sLt[lttcFlag] = propStep;
1410 jrLt[lttcFlag+1] = -1;
1411 sLt[lttcFlag+1] = 0.;
1414 Bool_t crossedDummy = (oldReg == gFluka->GetDummyRegion())?kTRUE:kFALSE;
1415 Int_t curLttc, curReg;
1417 // FLUKA crossed the dummy boundary - update new region/history
1418 retStep = TGeoShape::Tolerance();
1420 gMCGeom->GetNextRegion(newReg, newLttc);
1421 gMCGeom->SetMreg(newReg, newLttc);
1422 sLt[lttcFlag] = TGeoShape::Tolerance(); // null step in current region
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);
1432 // Reset outside flag
1433 gGeoManager->SetOutside(kFALSE);
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();
1444 // Now the current TGeo state reflects the FLUKA state
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;
1453 gGeoManager->MasterToLocal(pt,local);
1454 gGeoManager->MasterToLocalVect(pV,ldir);
1456 Bool_t valid = gGeoManager->GetCurrentVolume()->Contains(local);
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());
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();
1473 gGeoManager->FindNextBoundaryAndStep(pstep);
1474 snext = gGeoManager->GetStep();
1476 if (snext <= TGeoShape::Tolerance()) {
1477 // printf("FLUKA crossed boundary but snext=%g\n", snext);
1481 snext += TGeoShape::Tolerance();
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");
1494 snext += TGeoShape::Tolerance();
1501 // printf("%d snext=%g\n", ierr, snext);
1504 // printf("Too many null steps - sending error code -33...\n");
1505 newReg = -33; // Error code
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;
1519 sLt[lttcFlag] = propStep;
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);
1528 // We really crossed the boundary, but is it the same region ?
1529 gMCGeom->SetNextRegion(newReg, newLttc);
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);
1539 sLt[lttcFlag] = snext;
1541 jrLt[lttcFlag] = newLttc;
1542 sLt[lttcFlag] = snext;
1543 jrLt[lttcFlag+1] = -1;
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]);
1554 //_____________________________________________________________________________
1558 if (gMCGeom->IsDebugging()) printf("========== Dummy G1RTWR\n");
1561 //_____________________________________________________________________________
1562 void conhwr(Int_t & intHist, Int_t & incrCount)
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);
1570 // intHist = gGeoManager->GetCurrentNodeId()+1;
1573 //_____________________________________________________________________________
1574 void inihwr(Int_t &intHist)
1576 if (gMCGeom->IsDebugging())
1577 printf("========== Inside INIHWR -> reinitializing history: %i \n", intHist);
1578 if (gGeoManager->IsOutside()) gGeoManager->CdTop();
1580 // printf("=== wrong history number\n");
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");
1591 //_____________________________________________________________________________
1592 void jomiwr(const Int_t & /*nge*/, const Int_t & /*lin*/, const Int_t & /*lou*/,
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);
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)
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);
1613 lkwr(pSx,pSy,pSz,pV,oldReg,oldLttc,flagErr,newReg,newLttc);
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)
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);
1626 lkwr(pSx,pSy,pSz,pV,oldReg,oldLttc,flagErr,newReg,newLttc);
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)
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);
1639 lkwr(pSx,pSy,pSz,pV,oldReg,oldLttc,flagErr,newReg,newLttc);
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)
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);
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);
1662 gGeoManager->SetOutside(kFALSE);
1663 newReg = node->GetVolume()->GetNumber();
1664 newLttc = gGeoManager->GetCurrentNodeId()+1;
1665 if (oldLttc==TFlukaMCGeometry::kLttcOutside || oldLttc==0) return;
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) {
1673 newLttc = TFlukaMCGeometry::kLttcVirtual;
1675 if (gMCGeom->IsDebugging()) printf(" virtual boundary (oldReg==dummy) !! newReg=%i newLttc=%i\n", newReg, newLttc);
1680 if (oldReg==newReg && oldLttc!=newLttc) {
1682 newLttc = TFlukaMCGeometry::kLttcVirtual;
1683 if (gMCGeom->IsDebugging()) printf(" virtual boundary!! newReg=%i newLttc=%i\n", newReg, newLttc);
1686 if( oldReg!=newReg && oldLttc==newLttc ) {
1687 // this should not happen!! ??? Ernesto
1688 // cout << " lkwr oldReg!=newReg ("<< oldReg <<"!="<< newReg
1689 // << ") && oldLttc==newLttc ("<< newLttc <<") !!!!!!!!!!!!!!!!!" << endl;
1691 newLttc = TFlukaMCGeometry::kLttcVirtual;
1695 if (gMCGeom->IsDebugging()) {
1696 printf(" LKWR: newReg=%i newLttc=%i\n", newReg, newLttc);
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)
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);
1711 gGeoManager->SetCurrentPoint(NORLAT.xn[0], NORLAT.xn[1], NORLAT.xn[2]);
1712 gGeoManager->SetCurrentDirection(pVx, pVy, pVz);
1713 Double_t *dnorm = gGeoManager->FindNormalFast();
1716 printf(" ERROR: Cannot compute fast normal\n");
1722 norml[0] = -dnorm[0];
1723 norml[1] = -dnorm[1];
1724 norml[2] = -dnorm[2];
1727 if (gMCGeom->IsDebugging()) {
1728 printf(" normal to boundary: (%g, %g, %g)\n", norml[0], norml[1], norml[2]);
1729 printf("<= NRMLWR\n");
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*/)
1738 if (gMCGeom->IsDebugging()) printf("=> Dummy RGRPWR\n");
1741 //_____________________________________________________________________________
1742 Int_t isvhwr(const Int_t &check, const Int_t & intHist)
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.
1755 // For TGeo, just return the current node ID. No copy need to be made.
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());