00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <list>
00021 #include <map>
00022 #include <vector>
00023
00024 #include "BDSDetectorConstruction.hh"
00025
00026 #include "BDSAcceleratorModel.hh"
00027 #include "BDSExecOptions.hh"
00028 #include "BDSGlobalConstants.hh"
00029 #include "BDSDebug.hh"
00030
00031 #include "BDSSDManager.hh"
00032
00033 #include "G4UserLimits.hh"
00034 #include "G4Region.hh"
00035 #include "G4ProductionCuts.hh"
00036
00037 #include "G4Box.hh"
00038 #include "G4LogicalVolume.hh"
00039 #include "G4VPhysicalVolume.hh"
00040 #include "G4PVPlacement.hh"
00041 #include "G4UniformMagField.hh"
00042 #include "G4TransportationManager.hh"
00043 #include "G4PropagatorInField.hh"
00044 #include "G4VisAttributes.hh"
00045 #include "G4Colour.hh"
00046 #include "globals.hh"
00047 #include "G4ios.hh"
00048
00049 #include "G4Navigator.hh"
00050 #include "G4UniformMagField.hh"
00051
00052 #include "G4Electron.hh"
00053 #include "G4Positron.hh"
00054 #include "G4Material.hh"
00055
00056 #include "BDSAcceleratorComponent.hh"
00057 #include "BDSBeamline.hh"
00058 #include "BDSEnergyCounterSD.hh"
00059 #include "BDSLine.hh"
00060 #include "BDSMaterials.hh"
00061 #include "BDSTeleporter.hh"
00062 #include "BDSLogicalVolumeInfo.hh"
00063 #include "BDSComponentFactory.hh"
00064
00065 #include "G4MagneticField.hh"
00066 #include "G4VSampler.hh"
00067 #include "G4GeometrySampler.hh"
00068
00069 #include "ggmad.hh"
00070 #include "parser/element.h"
00071 #include "parser/elementlist.h"
00072 #include "parser/enums.h"
00073
00074 #ifdef BDSDEBUG
00075 bool debug = true;
00076 #else
00077 bool debug = false;
00078 #endif
00079
00080 BDSDetectorConstruction::BDSDetectorConstruction():
00081 itsGeometrySampler(NULL),precisionRegion(NULL),gasRegion(NULL),
00082 solidWorld(NULL),logicWorld(NULL),physiWorld(NULL),
00083 magField(NULL),BDSUserLimits(NULL),BDSSensitiveDetector(NULL),
00084 theHitMaker(NULL),theParticleBounds(NULL),_globalRotation(NULL)
00085 {
00086 verbose = BDSExecOptions::Instance()->GetVerbose();
00087
00088
00089 _globalRotation = new G4RotationMatrix();
00090
00091 G4bool gflash = BDSExecOptions::Instance()->GetGFlash();
00092 if (gflash) {
00093 G4double gflashemax = BDSExecOptions::Instance()->GetGFlashEMax();
00094 G4double gflashemin = BDSExecOptions::Instance()->GetGFlashEMin();
00095
00096 theParticleBounds = new GFlashParticleBounds();
00097 theParticleBounds->SetMaxEneToParametrise(*G4Electron::ElectronDefinition(),gflashemax*CLHEP::GeV);
00098 theParticleBounds->SetMinEneToParametrise(*G4Electron::ElectronDefinition(),gflashemin*CLHEP::GeV);
00099 theParticleBounds->SetEneToKill(*G4Electron::ElectronDefinition(),BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00100
00101 theParticleBounds->SetMaxEneToParametrise(*G4Positron::PositronDefinition(),gflashemax*CLHEP::GeV);
00102 theParticleBounds->SetMinEneToParametrise(*G4Positron::PositronDefinition(),gflashemin*CLHEP::GeV);
00103 theParticleBounds->SetEneToKill(*G4Positron::PositronDefinition(),BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00104
00105
00106
00107
00108
00109 #ifdef BDSDEBUG
00110 G4cout << __METHOD_NAME__ << "theParticleBounds - min E - electron: "
00111 << theParticleBounds->GetMinEneToParametrise(*G4Electron::ElectronDefinition())/CLHEP::GeV<< " GeV" << G4endl;
00112 G4cout << __METHOD_NAME__ << "theParticleBounds - max E - electron: "
00113 << theParticleBounds->GetMaxEneToParametrise(*G4Electron::ElectronDefinition())/CLHEP::GeV<< G4endl;
00114 G4cout << __METHOD_NAME__ << "theParticleBounds - kill E - electron: "
00115 << theParticleBounds->GetEneToKill(*G4Electron::ElectronDefinition())/CLHEP::GeV<< G4endl;
00116 G4cout << __METHOD_NAME__ << "theParticleBounds - min E - positron: "
00117 << theParticleBounds->GetMinEneToParametrise(*G4Positron::PositronDefinition())/CLHEP::GeV<< G4endl;
00118 G4cout << __METHOD_NAME__ << "theParticleBounds - max E - positron: "
00119 << theParticleBounds->GetMaxEneToParametrise(*G4Positron::PositronDefinition())/CLHEP::GeV<< G4endl;
00120 G4cout << __METHOD_NAME__ << "theParticleBounds - kill E - positron: "
00121 << theParticleBounds->GetEneToKill(*G4Positron::PositronDefinition())/CLHEP::GeV<< G4endl;
00122 #endif
00123
00124 theHitMaker = new GFlashHitMaker();
00125 }
00126 }
00127
00128 G4VPhysicalVolume* BDSDetectorConstruction::Construct()
00129 {
00130 gasRegion = new G4Region("gasRegion");
00131
00132 G4ProductionCuts* theGasProductionCuts = new G4ProductionCuts();
00133 theGasProductionCuts->SetProductionCut(1*CLHEP::m,G4ProductionCuts::GetIndex("gamma"));
00134 theGasProductionCuts->SetProductionCut(1*CLHEP::m,G4ProductionCuts::GetIndex("e-"));
00135 theGasProductionCuts->SetProductionCut(1*CLHEP::m,G4ProductionCuts::GetIndex("e+"));
00136 gasRegion->SetProductionCuts(theGasProductionCuts);
00137
00138 if (verbose || debug) G4cout << "-->starting BDS construction \n"<<G4endl;
00139
00140 return ConstructBDS(beamline_list);
00141 }
00142
00143 G4VPhysicalVolume* BDSDetectorConstruction::ConstructBDS(ElementList& beamline_list)
00144 {
00145
00146 BDSMaterials::Instance()->PrepareRequiredMaterials();
00147
00148
00149 SetMagField(0.0);
00150
00151
00152 BuildBeamline();
00153
00154
00155 BuildWorld();
00156
00157
00158 int G4precision = G4cout.precision(15);
00159
00160
00161 ComponentPlacement();
00162
00163
00164 std::list<struct Element>::iterator it;
00165 for(it = beamline_list.begin();it!=beamline_list.end();it++) {
00166 delete (*it).lst;
00167 }
00168 beamline_list.clear();
00169
00170 if(verbose || debug) G4cout << __METHOD_NAME__ << "detector Construction done"<<G4endl;
00171
00172 #ifdef BDSDEBUG
00173 G4cout << G4endl << __METHOD_NAME__ << "printing material table" << G4endl;
00174 G4cout << *(G4Material::GetMaterialTable()) << G4endl << G4endl;
00175 #endif
00176
00177 if(verbose || debug) G4cout<<"Finished listing materials, returning physiWorld"<<G4endl;
00178
00179
00180 G4cout.precision(G4precision);
00181
00182 return physiWorld;
00183 }
00184
00185 void BDSDetectorConstruction::SetMagField(const G4double fieldValue){
00186
00187 G4FieldManager* fieldMgr =
00188 G4TransportationManager::GetTransportationManager()->GetFieldManager();
00189 magField = new G4UniformMagField(G4ThreeVector(0.,fieldValue,0.));
00190 fieldMgr->SetDetectorField(magField);
00191 fieldMgr->CreateChordFinder(magField);
00192 }
00193
00194 BDSDetectorConstruction::~BDSDetectorConstruction()
00195 {
00196 delete precisionRegion;
00197 gFlashRegion.clear();
00198
00199 delete _globalRotation;
00200
00201 delete theHitMaker;
00202 delete theParticleBounds;
00203 }
00204
00205 void BDSDetectorConstruction::BuildBeamline()
00206 {
00207 std::list<struct Element>::iterator it;
00208
00209 BDSComponentFactory* theComponentFactory = new BDSComponentFactory();
00210
00211 BDSBeamline* beamline = new BDSBeamline();
00212
00213 if (verbose || debug) G4cout << "parsing the beamline element list..."<< G4endl;
00214 for(it = beamline_list.begin();it!=beamline_list.end();it++)
00215 {
00216 #ifdef BDSDEBUG
00217 G4cout << "BDSDetectorConstruction creating component " << (*it).name << G4endl;
00218 #endif
00219
00220 BDSAcceleratorComponent* temp = theComponentFactory->createComponent(it, beamline_list);
00221 if(temp)
00222 {beamline->AddComponent(temp);}
00223 }
00224
00225
00226
00227
00228 if (BDSExecOptions::Instance()->GetCircular())
00229 {
00230 #ifdef BDSDEBUG
00231 G4cout << __METHOD_NAME__ << "Circular machine - creating terminator & teleporter" << G4endl;
00232 #endif
00233 BDS::CalculateAndSetTeleporterDelta(beamline);
00234 BDSAcceleratorComponent* terminator = theComponentFactory->createTerminator();
00235 if (terminator)
00236 {
00237 terminator->Initialise();
00238 beamline->AddComponent(terminator);
00239 }
00240 BDSAcceleratorComponent* teleporter = theComponentFactory->createTeleporter();
00241 if (teleporter)
00242 {
00243 teleporter->Initialise();
00244 beamline->AddComponent(teleporter);
00245 }
00246 }
00247
00248 delete theComponentFactory;
00249
00250 #ifdef BDSDEBUG
00251 G4cout << __METHOD_NAME__ << "size of the parser beamline element list: "<< beamline_list.size() << G4endl;
00252 #endif
00253 G4cout << __METHOD_NAME__ << "size of the constructed beamline: "<< beamline->size() << G4endl;
00254
00255 if (beamline->size() == 0)
00256 {
00257 G4cout << __METHOD_NAME__ << "beamline empty or no line selected! exiting" << G4endl;
00258 exit(1);
00259 }
00260
00261 BDSAcceleratorModel::Instance()->RegisterFlatBeamline(beamline);
00262 }
00263
00264 void BDSDetectorConstruction::BuildWorld()
00265 {
00266 #ifdef BDSDEBUG
00267 G4cout << __METHOD_NAME__ << G4endl;
00268 #endif
00269 BDSBeamline* beamline = BDSAcceleratorModel::Instance()->GetFlatBeamline();
00270
00271 G4ThreeVector worldR = beamline->GetMaximumExtentAbsolute();
00272 G4ThreeVector maxpositive = beamline->GetMaximumExtentPositive();
00273 G4ThreeVector maxnegative = beamline->GetMaximumExtentNegative();
00274 #ifdef BDSDEBUG
00275 G4cout << __METHOD_NAME__ << "world extent positive: " << maxpositive << G4endl;
00276 G4cout << __METHOD_NAME__ << "world extent negative: " << maxnegative << G4endl;
00277 G4cout << __METHOD_NAME__ << "world extent absolute: " << worldR << G4endl;
00278 #endif
00279 worldR += G4ThreeVector(5000,5000,5000);
00280 #ifdef BDSDEBUG
00281 G4cout << __METHOD_NAME__ << "with 5m margin becomes in all dimensions: " << worldR << G4endl;
00282 #endif
00283
00284 G4String worldName="World";
00285 solidWorld = new G4Box(worldName, worldR.x(), worldR.y(), worldR.z());
00286
00287 G4String emptyMaterialName = BDSGlobalConstants::Instance()->GetEmptyMaterial();
00288 G4Material* emptyMaterial = BDSMaterials::Instance()->GetMaterial(emptyMaterialName);
00289 logicWorld = new G4LogicalVolume(solidWorld,
00290 emptyMaterial,
00291 worldName);
00292
00293
00294
00295 G4LogicalVolume* readOutWorldLV = new G4LogicalVolume(solidWorld,
00296 emptyMaterial,
00297 worldName);
00298
00299
00300 if (BDSExecOptions::Instance()->GetVisDebug())
00301 {
00302
00303 G4VisAttributes* debugWorldVis = new G4VisAttributes(*(BDSGlobalConstants::Instance()->GetVisibleDebugVisAttr()));
00304 debugWorldVis->SetForceWireframe(true);
00305 logicWorld->SetVisAttributes(debugWorldVis);
00306 readOutWorldLV->SetVisAttributes(debugWorldVis);
00307 }
00308 else
00309 {
00310 logicWorld->SetVisAttributes(BDSGlobalConstants::Instance()->GetInvisibleVisAttr());
00311 readOutWorldLV->SetVisAttributes(BDSGlobalConstants::Instance()->GetInvisibleVisAttr());
00312 }
00313
00314
00315 #ifndef NOUSERLIMITS
00316 G4UserLimits* worldUserLimits = new G4UserLimits(*(BDSGlobalConstants::Instance()->GetDefaultUserLimits()));
00317 worldUserLimits->SetMaxAllowedStep(worldR.z()*0.5);
00318 logicWorld->SetUserLimits(worldUserLimits);
00319 readOutWorldLV->SetUserLimits(worldUserLimits);
00320 #endif
00321
00322
00323 #ifdef BDSDEBUG
00324 G4cout<<"Creating regions..."<<G4endl;
00325 #endif
00326 precisionRegion = new G4Region("precisionRegion");
00327 G4ProductionCuts* theProductionCuts = new G4ProductionCuts();
00328 if(BDSGlobalConstants::Instance()->GetProdCutPhotonsP()>0)
00329 theProductionCuts->SetProductionCut(BDSGlobalConstants::Instance()->GetProdCutPhotonsP(),G4ProductionCuts::GetIndex("gamma"));
00330
00331 if(BDSGlobalConstants::Instance()->GetProdCutElectronsP()>0)
00332 theProductionCuts->SetProductionCut(BDSGlobalConstants::Instance()->GetProdCutElectronsP(),G4ProductionCuts::GetIndex("e-"));
00333
00334 if(BDSGlobalConstants::Instance()->GetProdCutPositronsP()>0)
00335 theProductionCuts->SetProductionCut(BDSGlobalConstants::Instance()->GetProdCutPositronsP(),G4ProductionCuts::GetIndex("e+"));
00336
00337 precisionRegion->SetProductionCuts(theProductionCuts);
00338 #ifndef NOUSERLIMITS
00339 precisionRegion->SetUserLimits(worldUserLimits);
00340 #endif
00341
00342
00343 physiWorld = new G4PVPlacement((G4RotationMatrix*)0,
00344 (G4ThreeVector)0,
00345 logicWorld,
00346 worldName,
00347 NULL,
00348 false,
00349 0,
00350 BDSGlobalConstants::Instance()->GetCheckOverlaps());
00351
00352
00353 G4PVPlacement* readOutWorldPV = new G4PVPlacement((G4RotationMatrix*)0,
00354 (G4ThreeVector)0,
00355 readOutWorldLV,
00356 "readoutWorld",
00357 NULL,
00358 false,
00359 0,
00360 BDSGlobalConstants::Instance()->GetCheckOverlaps());
00361
00362 BDSAcceleratorModel::Instance()->RegisterReadOutWorldPV(readOutWorldPV);
00363 BDSAcceleratorModel::Instance()->RegisterReadOutWorldLV(readOutWorldLV);
00364 }
00365
00366 void BDSDetectorConstruction::ComponentPlacement()
00367 {
00368 if (verbose || debug)
00369 {G4cout << G4endl << __METHOD_NAME__ << "- starting placement procedure" << G4endl;}
00370
00371 BDSBeamline* beamline = BDSAcceleratorModel::Instance()->GetFlatBeamline();
00372
00373
00374
00375 G4VPhysicalVolume* readOutWorldPV = BDSAcceleratorModel::Instance()->GetReadOutWorldPV();
00376 G4VSensitiveDetector* energyCounterSDRO = BDSSDManager::Instance()->GetEnergyCounterOnAxisSDRO();
00377 G4bool checkOverlaps = BDSGlobalConstants::Instance()->GetCheckOverlaps();
00378
00379 BDSBeamlineIterator it = beamline->begin();
00380 for(; it != beamline->end(); ++it)
00381 {
00382 BDSAcceleratorComponent* thecurrentitem = (*it)->GetAcceleratorComponent();
00383
00384 if (!thecurrentitem)
00385 {G4cerr << __METHOD_NAME__ << "beamline element does not contain valid BDSAcceleratorComponent" << G4endl; exit(1);}
00386
00387
00388 G4LogicalVolume* elementLV = thecurrentitem->GetContainerLogicalVolume();
00389 if (!elementLV)
00390 {G4cerr << __METHOD_NAME__ << "this accelerator component " << (*it)->GetName() << " has no volume to be placed!" << G4endl; exit(1);}
00391
00392 G4String name = (*it)->GetName();
00393 if (verbose || debug)
00394 {G4cout << __METHOD_NAME__ << "placement of component named: " << name << G4endl;}
00395
00396
00397 G4LogicalVolume* readOutLV = thecurrentitem->GetReadOutLogicalVolume();
00398
00399 if (readOutLV)
00400 {readOutLV->SetSensitiveDetector(energyCounterSDRO);}
00401
00402
00403 G4int precision = thecurrentitem->GetPrecisionRegion();
00404 if(precision < 0)
00405 {
00406 #ifdef BDSDEBUG
00407 G4cout << __METHOD_NAME__ << "element is in the precision region number: " << precision << G4endl;
00408 #endif
00409 elementLV->SetRegion(precisionRegion);
00410 precisionRegion->AddRootLogicalVolume(elementLV);
00411 }
00412
00413 #ifdef BDSDEBUG
00414 G4cout << __METHOD_NAME__ << "setting up sensitive volumes with read out geometry" << G4endl;
00415 #endif
00416
00417
00418 BDSLogicalVolumeInfo* theinfo = new BDSLogicalVolumeInfo(name,
00419 (*it)->GetSPositionMiddle());
00420 if(readOutLV)
00421 {BDSGlobalConstants::Instance()->AddLogicalVolumeInfo(readOutLV,theinfo);}
00422 else
00423 {BDSGlobalConstants::Instance()->AddLogicalVolumeInfo(elementLV,theinfo);}
00424
00425
00426
00427 std::vector<G4LogicalVolume*> allLVs = thecurrentitem->GetAllLogicalVolumes();
00428 std::vector<G4LogicalVolume*>::iterator allLVsIterator = allLVs.begin();
00429 for(;allLVsIterator != allLVs.end(); ++allLVsIterator)
00430 {
00431 BDSGlobalConstants::Instance()->AddLogicalVolumeInfo(*allLVsIterator,
00432 new BDSLogicalVolumeInfo((*allLVsIterator)->GetName(),
00433 thecurrentitem->GetSPos())
00434 );
00435 }
00436
00437
00438
00439
00440
00441 if (!readOutLV)
00442 {
00443 std::vector<G4LogicalVolume*> SensVols = thecurrentitem->GetAllSensitiveVolumes();
00444 std::vector<G4LogicalVolume*>::iterator sensIt= SensVols.begin();
00445 for(;sensIt != SensVols.end(); ++sensIt)
00446 {
00447
00448 (*sensIt)->SetSensitiveDetector(energyCounterSDRO);
00449
00450 BDSLogicalVolumeInfo* theinfo = new BDSLogicalVolumeInfo( (*sensIt)->GetName(),
00451 thecurrentitem->GetSPos() );
00452 BDSGlobalConstants::Instance()->AddLogicalVolumeInfo((*sensIt),theinfo);
00453
00454 G4bool gflash = BDSExecOptions::Instance()->GetGFlash();
00455 if(gflash && ((*sensIt)->GetRegion() != precisionRegion) && (thecurrentitem->GetType()=="element"))
00456 {SetGFlashOnVolume(*sensIt);}
00457 }
00458 }
00459
00460
00461 G4int nCopy = 0;
00462 G4RotationMatrix* r = (*it)->GetRotationMiddle();
00463 G4ThreeVector p = (*it)->GetPositionMiddle();
00464
00465 G4PVPlacement* PhysiComponentPlace = new G4PVPlacement(r,
00466 p,
00467 name + "_pv",
00468 elementLV,
00469 physiWorld,
00470 false,
00471 nCopy,
00472 checkOverlaps);
00473
00474
00475 if(readOutLV)
00476 {
00477
00478 new G4PVPlacement(r,
00479 p,
00480 name + "_ro_ph",
00481 readOutLV,
00482 readOutWorldPV,
00483 false,
00484 nCopy,
00485 checkOverlaps);
00486 }
00487
00488
00489
00490 fPhysicalVolumeVector.push_back(PhysiComponentPlace);
00491 std::vector<G4VPhysicalVolume*> MultiplePhysicalVolumes = thecurrentitem->GetMultiplePhysicalVolumes();
00492 for (unsigned int i=0;i<MultiplePhysicalVolumes.size(); i++)
00493 {fPhysicalVolumeVector.push_back(MultiplePhysicalVolumes.at(i));}
00494
00495
00496
00497
00498 thecurrentitem->PrepareField(PhysiComponentPlace);
00499 }
00500 }
00501
00502 void BDSDetectorConstruction::SetGFlashOnVolume(G4LogicalVolume* volume)
00503 {
00504
00505
00506
00507
00508
00509 #ifdef BDSDEBUG
00510 G4cout << "...adding " << volume->GetName() << " to gFlashRegion" << G4endl;
00511 #endif
00512
00513 G4String rname = "gFlashRegion_" + volume->GetName();
00514 gFlashRegion.push_back(new G4Region(rname.c_str()));
00515 G4String mname = "fastShowerModel" + rname;
00516 #ifdef BDSDEBUG
00517 G4cout << "...making parameterisation..." << G4endl;
00518 #endif
00519 theFastShowerModel.push_back(new BDSShowerModel(mname.c_str(),gFlashRegion.back()));
00520 theParameterisation.push_back(new GFlashHomoShowerParameterisation(BDSMaterials::Instance()->GetMaterial(volume->GetMaterial()->GetName().c_str())));
00521 theFastShowerModel.back()->SetParameterisation(*theParameterisation.back());
00522 theFastShowerModel.back()->SetParticleBounds(*theParticleBounds) ;
00523 theFastShowerModel.back()->SetHitMaker(*theHitMaker);
00524 if(volume->GetMaterial()->GetState()!=kStateGas)
00525 {
00526
00527 theFastShowerModel.back()->SetFlagParamType(1);
00528
00529 theFastShowerModel.back()->SetFlagParticleContainment(1);
00530 }
00531 else
00532 {
00533
00534 theFastShowerModel.back()->SetFlagParamType(0);
00535
00536 theFastShowerModel.back()->SetFlagParticleContainment(0);
00537 }
00538 volume->SetRegion(gFlashRegion.back());
00539 gFlashRegion.back()->AddRootLogicalVolume(volume);
00540
00541
00542
00543 }