Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4VUserDetectorConstruction implementation << 27 // 26 // 28 // Original author: M.Asai, 1999 << 27 // $Id: G4VUserDetectorConstruction.cc 77002 2013-11-20 11:22:35Z gcosmo $ 29 // ------------------------------------------- << 28 // 30 29 31 #include "G4VUserDetectorConstruction.hh" 30 #include "G4VUserDetectorConstruction.hh" 32 << 31 #include "G4VPhysicalVolume.hh" 33 #include "G4FieldManager.hh" << 32 #include "G4VUserParallelWorld.hh" 34 #include "G4LogicalVolume.hh" 33 #include "G4LogicalVolume.hh" 35 #include "G4LogicalVolumeStore.hh" 34 #include "G4LogicalVolumeStore.hh" 36 #include "G4MultiSensitiveDetector.hh" << 37 #include "G4RunManager.hh" << 38 #include "G4SDManager.hh" << 39 #include "G4VPhysicalVolume.hh" << 40 #include "G4VSensitiveDetector.hh" 35 #include "G4VSensitiveDetector.hh" 41 #include "G4VUserParallelWorld.hh" << 36 #include "G4FieldManager.hh" >> 37 #include "G4SDManager.hh" >> 38 #include <assert.h> 42 39 43 #include <cassert> << 40 G4VUserDetectorConstruction::G4VUserDetectorConstruction() 44 #include <map> << 41 {;} 45 #include <sstream> << 42 >> 43 G4VUserDetectorConstruction::~G4VUserDetectorConstruction() >> 44 {;} 46 45 47 // ------------------------------------------- << 48 void G4VUserDetectorConstruction::RegisterPara 46 void G4VUserDetectorConstruction::RegisterParallelWorld(G4VUserParallelWorld* aPW) 49 { 47 { 50 auto pwItr = std::find(parallelWorld.cbegin( << 48 std::vector<G4VUserParallelWorld*>::iterator pwItr; 51 if (pwItr != parallelWorld.cend()) { << 49 for(pwItr=parallelWorld.begin();pwItr!=parallelWorld.end();pwItr++) 52 G4String eM = "A parallel world <"; << 50 { 53 eM += aPW->GetName(); << 51 if((*pwItr)->GetName()==aPW->GetName()) 54 eM += "> is already registered to the user << 52 { 55 G4Exception("G4VUserDetectorConstruction:: << 53 G4String eM = "A parallel world <"; 56 FatalErrorInArgument, eM); << 54 eM += aPW->GetName(); >> 55 eM += "> is already registered to the user detector construction."; >> 56 G4Exception("G4VUserDetectorConstruction::RegisterParallelWorld", >> 57 "Run0051",FatalErrorInArgument,eM); >> 58 } 57 } 59 } 58 parallelWorld.push_back(aPW); 60 parallelWorld.push_back(aPW); 59 } 61 } 60 62 61 // ------------------------------------------- << 62 G4int G4VUserDetectorConstruction::ConstructPa 63 G4int G4VUserDetectorConstruction::ConstructParallelGeometries() 63 { 64 { 64 G4int nP = 0; 65 G4int nP = 0; 65 for (const auto& pwItr : parallelWorld) { << 66 std::vector<G4VUserParallelWorld*>::iterator pwItr; 66 pwItr->Construct(); << 67 for(pwItr=parallelWorld.begin();pwItr!=parallelWorld.end();pwItr++) 67 ++nP; << 68 { >> 69 (*pwItr)->Construct(); >> 70 nP++; 68 } 71 } 69 return nP; 72 return nP; 70 } 73 } 71 74 72 // ------------------------------------------- << 73 void G4VUserDetectorConstruction::ConstructPar 75 void G4VUserDetectorConstruction::ConstructParallelSD() 74 { 76 { 75 for (const auto& pwItr : parallelWorld) { << 77 std::vector<G4VUserParallelWorld*>::iterator pwItr; 76 pwItr->ConstructSD(); << 78 for(pwItr=parallelWorld.begin();pwItr!=parallelWorld.end();pwItr++) 77 } << 79 { (*pwItr)->ConstructSD(); } 78 } 80 } 79 81 80 // ------------------------------------------- << 81 G4int G4VUserDetectorConstruction::GetNumberOf 82 G4int G4VUserDetectorConstruction::GetNumberOfParallelWorld() const 82 { << 83 { return parallelWorld.size(); } 83 return (G4int)parallelWorld.size(); << 84 } << 85 84 86 // ------------------------------------------- << 87 G4VUserParallelWorld* G4VUserDetectorConstruct 85 G4VUserParallelWorld* G4VUserDetectorConstruction::GetParallelWorld(G4int i) const 88 { 86 { 89 if (i < 0 || i >= GetNumberOfParallelWorld() << 87 if(i<0||i>=GetNumberOfParallelWorld()) return 0; 90 return parallelWorld[i]; 88 return parallelWorld[i]; 91 } 89 } 92 90 93 // ------------------------------------------- << 91 #include "G4RunManager.hh" 94 void G4VUserDetectorConstruction::ConstructSDa << 95 92 96 // ------------------------------------------- << 93 void G4VUserDetectorConstruction::ConstructSDandField() 97 void G4VUserDetectorConstruction::CloneF() << 98 { 94 { 99 using FMtoFMmap = std::map<G4FieldManager*, << 95 // G4RunManager::RMType rmtype = G4RunManager::GetRunManager()->GetRunManagerType(); 100 using FMpair = std::pair<G4FieldManager*, G4 << 96 // if(rmtype != G4RunManager::sequentialRM) >> 97 // { >> 98 // G4cout >> 99 // << "User-derived detector construction class does not implement \n" >> 100 // << "ConstructSDandFiled method: i.e. workers will not have SD and fields!\n" >> 101 // << "The user can safely ignore this message if (s)he has no sensitive\n" >> 102 // << "detector or field in her/his application." << G4endl; >> 103 // } >> 104 } 101 105 102 FMtoFMmap masterToWorker; << 106 #include <map> 103 G4LogicalVolumeStore* const logVolStore = G4 << 107 void G4VUserDetectorConstruction::CloneF() 104 for (const auto& g4LogicalVolume : *logVolSt << 108 { 105 // Use shadow of master to get instance of << 109 typedef std::map<G4FieldManager*,G4FieldManager*> FMtoFMmap; 106 G4FieldManager* masterFM = nullptr; // g4 << 110 typedef std::pair<G4FieldManager*,G4FieldManager*> FMpair; 107 G4FieldManager* clonedFM = nullptr; << 111 FMtoFMmap masterToWorker; 108 if (masterFM != nullptr) { << 112 G4LogicalVolumeStore* const logVolStore = G4LogicalVolumeStore::GetInstance(); 109 auto fmFound = masterToWorker.find(maste << 113 assert( logVolStore != NULL ); 110 if (fmFound == masterToWorker.cend()) { << 114 for ( G4LogicalVolumeStore::const_iterator it = logVolStore->begin() ; it != logVolStore->end() ; ++it ) 111 // First time we see this SD, let's cl << 115 { 112 try { << 116 G4LogicalVolume *g4LogicalVolume = *it; 113 auto insertedEl = masterToWorker.ins << 117 //Use shadow of master to get instance of FM 114 clonedFM = (insertedEl.first)->secon << 118 G4FieldManager* masterFM = 0;//g4LogicalVolume->fFieldManager; 115 } << 119 G4FieldManager* clonedFM = 0; 116 catch (...) { << 120 if ( masterFM ) 117 G4ExceptionDescription msg; << 121 { 118 msg << "Cloning of G4FieldManager fa << 122 FMtoFMmap::iterator fmFound = masterToWorker.find(masterFM); 119 << " But derived class does not << 123 if ( fmFound == masterToWorker.end() ) 120 "continue."; << 124 { 121 G4Exception("G4VUserDetectorConstruc << 125 //First time we see this SD, let's clone and remember... 122 } << 126 try { 123 } << 127 std::pair<FMtoFMmap::iterator,bool> insertedEl = masterToWorker.insert( FMpair(masterFM, masterFM->Clone()) ); 124 else { << 128 clonedFM = (insertedEl.first)->second; 125 // We have already seen this SD attach << 129 } 126 // let's re-use previous clone << 130 catch (...) 127 clonedFM = (*fmFound).second; << 131 { 128 } << 132 G4ExceptionDescription msg; 129 } // masterFM != 0 << 133 msg << "Cloning of G4FieldManager failed." 130 // Note that we do not push FM to daughter << 134 << " But derived class does not implement cloning. Cannot continue."; 131 // we area looping on all logical volumes << 135 G4Exception("G4VUserDetectorConstruction::CloneSD", "Run0053", FatalException,msg); 132 // the map master<->cloned the final effec << 136 133 // correct Boolean flag: log-volumes that << 137 } 134 // FM they will have cloned ones << 138 } 135 g4LogicalVolume->SetFieldManager(clonedFM, << 139 else 136 } << 140 { >> 141 // We have already seen this SD attached to a fifferent LogicalVolume, let's re-use previous clone >> 142 clonedFM = (*fmFound).second; >> 143 } >> 144 }// masterFM != 0 >> 145 //Note that we do not push FM to doughters (false argument), however, since we area looping on all >> 146 //logical volumes and we implemented the "trick" of the map master<->cloned the final >> 147 //effect is the same as using here the correct boolean flag: log-volumes that originally were sharing >> 148 //the same FM they will have cloned ones >> 149 g4LogicalVolume->SetFieldManager(clonedFM, false); >> 150 } 137 } 151 } 138 152 139 // ------------------------------------------- << 140 void G4VUserDetectorConstruction::CloneSD() 153 void G4VUserDetectorConstruction::CloneSD() 141 { 154 { 142 // Loop on ALL logial volumes to search for << 155 //Loop on ALL logial volumes to search for attached SD 143 G4LogicalVolumeStore* const logVolStore = G4 << 156 G4LogicalVolumeStore* const logVolStore = G4LogicalVolumeStore::GetInstance(); 144 << 157 assert( logVolStore != NULL ); 145 using SDtoSDmap = std::map<G4VSensitiveDetec << 158 146 using SDpair = std::pair<G4VSensitiveDetecto << 159 typedef std::map<G4VSensitiveDetector*,G4VSensitiveDetector*> SDtoSDmap; 147 SDtoSDmap masterToWorker; << 160 typedef std::pair<G4VSensitiveDetector*,G4VSensitiveDetector*> SDpair; 148 << 161 SDtoSDmap masterToWorker; 149 for (const auto& g4LogicalVolume : *logVolSt << 162 150 // Use shadow of master to get the instanc << 163 for ( G4LogicalVolumeStore::const_iterator it = logVolStore->begin() ; it != logVolStore->end() ; ++it ) 151 G4VSensitiveDetector* masterSD = nullptr; << 164 { 152 G4VSensitiveDetector* clonedSD = nullptr; << 165 G4LogicalVolume *g4LogicalVolume = *it; 153 if (masterSD != nullptr) { << 166 //Use shadow of master to get the instance of SD 154 auto sdFound = masterToWorker.find(maste << 167 G4VSensitiveDetector* masterSD = 0;//g4LogicalVolume->fSensitiveDetector; 155 if (sdFound == masterToWorker.cend()) { << 168 G4VSensitiveDetector* clonedSD = 0; 156 // First time we see this SD, let's cl << 169 if ( masterSD ) 157 try { << 170 { 158 auto insertedEl = masterToWorker.ins << 171 SDtoSDmap::iterator sdFound = masterToWorker.find(masterSD); 159 clonedSD = (insertedEl.first)->secon << 172 if ( sdFound == masterToWorker.end() ) 160 } << 173 { 161 catch (...) { << 174 //First time we see this SD, let's clone and remember... 162 G4ExceptionDescription msg; << 175 try { 163 msg << "Cloning of G4VSensitiveDetec << 176 std::pair<SDtoSDmap::iterator,bool> insertedEl = masterToWorker.insert( SDpair(masterSD,masterSD->Clone()) ); >> 177 clonedSD = (insertedEl.first)->second; >> 178 } >> 179 catch (...) >> 180 { >> 181 G4ExceptionDescription msg; >> 182 msg << "Cloning of G4VSensitiveDetector requested for:" << masterSD->GetName() << "\n" 164 #ifndef WIN32 183 #ifndef WIN32 165 << " (full path name: " << maste << 184 << " (full path name: " << masterSD->GetFullPathName() << ").\n" 166 #endif 185 #endif 167 << " But derived class does not << 186 << " But derived class does not implement cloning. Cannot continue."; 168 "continue."; << 187 G4Exception("G4VUserDetectorConstruction::CloneSD", "Run0053", FatalException,msg); 169 G4Exception("G4VUserDetectorConstruc << 188 } 170 } << 189 171 } << 190 } 172 else { << 191 else 173 // We have already seen this SD attach << 192 { 174 // let's re-use previous clone << 193 // We have already seen this SD attached to a fifferent LogicalVolume, let's re-use previous clone 175 clonedSD = (*sdFound).second; << 194 clonedSD = (*sdFound).second; 176 } << 195 177 } // masterSD!=0 << 196 } 178 g4LogicalVolume->SetSensitiveDetector(clon << 197 }// masterSD!=0 179 } << 198 g4LogicalVolume->SetSensitiveDetector(clonedSD); >> 199 >> 200 } 180 } 201 } 181 202 182 // ------------------------------------------- << 203 void G4VUserDetectorConstruction::SetSensitiveDetector 183 void G4VUserDetectorConstruction::SetSensitive << 204 (const G4String& logVolName, G4VSensitiveDetector* aSD, G4bool multi) 184 << 205 { 185 { << 186 G4bool found = false; 206 G4bool found = false; 187 G4LogicalVolumeStore* store = G4LogicalVolum 207 G4LogicalVolumeStore* store = G4LogicalVolumeStore::GetInstance(); 188 auto volmap = store->GetMap(); << 208 for(G4LogicalVolumeStore::iterator pos=store->begin(); pos!=store->end(); pos++) 189 auto pos = volmap.find(logVolName); << 209 { 190 if (pos != volmap.cend()) { << 210 if((*pos)->GetName()==logVolName) 191 if ((pos->second.size() > 1) && !multi) { << 211 { 192 G4String eM = "More than one logical vol << 212 if(found && !multi) 193 eM += pos->first; << 213 { 194 eM += "> are found and thus the sensitiv << 214 G4String eM = "More than one logical volumes of the name <"; 195 eM += aSD->GetName(); << 215 eM += (*pos)->GetName(); 196 eM += "> cannot be uniquely assigned."; << 216 eM += "> are found and thus the sensitive detector <"; 197 G4Exception("G4VUserDetectorConstruction << 217 eM += aSD->GetName(); 198 FatalErrorInArgument, eM); << 218 eM += "> cannot be uniquely assigned."; 199 } << 219 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector", 200 found = true; << 220 "Run0052",FatalErrorInArgument,eM); 201 for (auto& i : pos->second) { << 221 } 202 SetSensitiveDetector(i, aSD); << 222 found = true; >> 223 SetSensitiveDetector(*pos,aSD); 203 } 224 } 204 } << 225 } 205 if (!found) { << 226 if(!found) 206 G4String eM2 = "No logical volume of name << 227 { >> 228 G4String eM2 = "No logical volume of the name <"; 207 eM2 += logVolName; 229 eM2 += logVolName; 208 eM2 += "> is found. The specified sensitiv 230 eM2 += "> is found. The specified sensitive detector <"; 209 eM2 += aSD->GetName(); 231 eM2 += aSD->GetName(); 210 eM2 += "> couldn't be assigned to any volu 232 eM2 += "> couldn't be assigned to any volume."; 211 G4Exception("G4VUserDetectorConstruction:: << 233 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector", 212 FatalErrorInArgument, eM2); << 234 "Run0053",FatalErrorInArgument,eM2); 213 } 235 } 214 } << 236 } 215 237 216 // ------------------------------------------- << 238 void G4VUserDetectorConstruction::SetSensitiveDetector 217 void G4VUserDetectorConstruction::SetSensitive << 239 (G4LogicalVolume* logVol, G4VSensitiveDetector* aSD) 218 << 240 { 219 { << 241 G4SDManager::GetSDMpointer()->AddNewDetector(aSD); 220 assert(logVol != nullptr && aSD != nullptr); << 242 logVol->SetSensitiveDetector(aSD); 221 << 222 // The aSD has already been added by user to << 223 // G4SDManager::GetSDMpointer()->AddNewDetec << 224 << 225 // New Logic: allow for "multiple" SDs being << 226 // To do that we use a special proxy SD call << 227 << 228 // Get existing SD if already set and check << 229 G4VSensitiveDetector* originalSD = logVol->G << 230 if (originalSD == aSD) { << 231 G4ExceptionDescription msg; << 232 msg << "Attempting to add multiple times t << 233 msg << originalSD->GetName() << "\") is no << 234 G4Exception("G4VUserDetectorConstruction:: << 235 return; << 236 } << 237 if (originalSD == nullptr) { << 238 logVol->SetSensitiveDetector(aSD); << 239 } << 240 else { << 241 auto msd = dynamic_cast<G4MultiSensitiveDe << 242 if (msd != nullptr) { << 243 msd->AddSD(aSD); << 244 } << 245 else { << 246 std::ostringstream mn; << 247 mn << "/MultiSD_" << logVol->GetName() < << 248 const G4String msdname = mn.str(); << 249 msd = new G4MultiSensitiveDetector(msdna << 250 // We need to register the proxy to have << 251 G4SDManager::GetSDMpointer()->AddNewDete << 252 msd->AddSD(originalSD); << 253 msd->AddSD(aSD); << 254 logVol->SetSensitiveDetector(msd); << 255 } << 256 } << 257 } 243 } 258 244