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 26 // G4VUserDetectorConstruction implementation 27 // 27 // 28 // Original author: M.Asai, 1999 28 // Original author: M.Asai, 1999 29 // ------------------------------------------- 29 // -------------------------------------------------------------------- 30 30 31 #include "G4VUserDetectorConstruction.hh" << 31 #include <sstream> >> 32 #include <map> >> 33 #include <assert.h> 32 34 >> 35 #include "G4VUserDetectorConstruction.hh" 33 #include "G4FieldManager.hh" 36 #include "G4FieldManager.hh" 34 #include "G4LogicalVolume.hh" 37 #include "G4LogicalVolume.hh" 35 #include "G4LogicalVolumeStore.hh" 38 #include "G4LogicalVolumeStore.hh" 36 #include "G4MultiSensitiveDetector.hh" 39 #include "G4MultiSensitiveDetector.hh" 37 #include "G4RunManager.hh" << 38 #include "G4SDManager.hh" 40 #include "G4SDManager.hh" 39 #include "G4VPhysicalVolume.hh" 41 #include "G4VPhysicalVolume.hh" 40 #include "G4VSensitiveDetector.hh" 42 #include "G4VSensitiveDetector.hh" 41 #include "G4VUserParallelWorld.hh" 43 #include "G4VUserParallelWorld.hh" >> 44 #include "G4RunManager.hh" 42 45 43 #include <cassert> << 46 // -------------------------------------------------------------------- 44 #include <map> << 47 G4VUserDetectorConstruction::G4VUserDetectorConstruction() 45 #include <sstream> << 48 { >> 49 } >> 50 >> 51 // -------------------------------------------------------------------- >> 52 G4VUserDetectorConstruction::~G4VUserDetectorConstruction() >> 53 { >> 54 } 46 55 47 // ------------------------------------------- 56 // -------------------------------------------------------------------- 48 void G4VUserDetectorConstruction::RegisterPara << 57 void G4VUserDetectorConstruction:: >> 58 RegisterParallelWorld(G4VUserParallelWorld* aPW) 49 { 59 { 50 auto pwItr = std::find(parallelWorld.cbegin( 60 auto pwItr = std::find(parallelWorld.cbegin(), parallelWorld.cend(), aPW); 51 if (pwItr != parallelWorld.cend()) { << 61 if (pwItr != parallelWorld.cend()) >> 62 { 52 G4String eM = "A parallel world <"; 63 G4String eM = "A parallel world <"; 53 eM += aPW->GetName(); 64 eM += aPW->GetName(); 54 eM += "> is already registered to the user 65 eM += "> is already registered to the user detector construction."; 55 G4Exception("G4VUserDetectorConstruction:: << 66 G4Exception("G4VUserDetectorConstruction::RegisterParallelWorld", 56 FatalErrorInArgument, eM); << 67 "Run0051", FatalErrorInArgument, eM); 57 } 68 } 58 parallelWorld.push_back(aPW); 69 parallelWorld.push_back(aPW); 59 } 70 } 60 71 61 // ------------------------------------------- 72 // -------------------------------------------------------------------- 62 G4int G4VUserDetectorConstruction::ConstructPa 73 G4int G4VUserDetectorConstruction::ConstructParallelGeometries() 63 { 74 { 64 G4int nP = 0; 75 G4int nP = 0; 65 for (const auto& pwItr : parallelWorld) { << 76 for(auto pwItr = parallelWorld.cbegin(); 66 pwItr->Construct(); << 77 pwItr != parallelWorld.cend(); ++pwItr) >> 78 { >> 79 (*pwItr)->Construct(); 67 ++nP; 80 ++nP; 68 } 81 } 69 return nP; 82 return nP; 70 } 83 } 71 84 72 // ------------------------------------------- 85 // -------------------------------------------------------------------- 73 void G4VUserDetectorConstruction::ConstructPar 86 void G4VUserDetectorConstruction::ConstructParallelSD() 74 { 87 { 75 for (const auto& pwItr : parallelWorld) { << 88 for(auto pwItr = parallelWorld.cbegin(); 76 pwItr->ConstructSD(); << 89 pwItr != parallelWorld.cend(); ++pwItr) >> 90 { >> 91 (*pwItr)->ConstructSD(); 77 } 92 } 78 } 93 } 79 94 80 // ------------------------------------------- 95 // -------------------------------------------------------------------- 81 G4int G4VUserDetectorConstruction::GetNumberOf 96 G4int G4VUserDetectorConstruction::GetNumberOfParallelWorld() const 82 { 97 { 83 return (G4int)parallelWorld.size(); 98 return (G4int)parallelWorld.size(); 84 } 99 } 85 100 86 // ------------------------------------------- 101 // -------------------------------------------------------------------- 87 G4VUserParallelWorld* G4VUserDetectorConstruct << 102 G4VUserParallelWorld* >> 103 G4VUserDetectorConstruction::GetParallelWorld(G4int i) const 88 { 104 { 89 if (i < 0 || i >= GetNumberOfParallelWorld() << 105 if(i < 0 || i >= GetNumberOfParallelWorld()) >> 106 return nullptr; 90 return parallelWorld[i]; 107 return parallelWorld[i]; 91 } 108 } 92 109 93 // ------------------------------------------- 110 // -------------------------------------------------------------------- 94 void G4VUserDetectorConstruction::ConstructSDa << 111 void G4VUserDetectorConstruction::ConstructSDandField() >> 112 { >> 113 // G4RunManager::RMType rmtype = >> 114 // G4RunManager::GetRunManager()->GetRunManagerType(); if(rmtype != >> 115 // G4RunManager::sequentialRM) >> 116 // { >> 117 // G4cout >> 118 // << "User-derived detector construction class does not implement \n" >> 119 // << "ConstructSDandFiled method: workers will not have SD and fields!\n" >> 120 // << "The user can safely ignore this message if (s)he has no sensitive\n" >> 121 // << "detector or field in her/his application." << G4endl; >> 122 // } >> 123 } 95 124 96 // ------------------------------------------- 125 // -------------------------------------------------------------------- 97 void G4VUserDetectorConstruction::CloneF() 126 void G4VUserDetectorConstruction::CloneF() 98 { 127 { 99 using FMtoFMmap = std::map<G4FieldManager*, 128 using FMtoFMmap = std::map<G4FieldManager*, G4FieldManager*>; 100 using FMpair = std::pair<G4FieldManager*, G4 129 using FMpair = std::pair<G4FieldManager*, G4FieldManager*>; 101 130 102 FMtoFMmap masterToWorker; 131 FMtoFMmap masterToWorker; 103 G4LogicalVolumeStore* const logVolStore = G4 132 G4LogicalVolumeStore* const logVolStore = G4LogicalVolumeStore::GetInstance(); 104 for (const auto& g4LogicalVolume : *logVolSt << 133 for(auto it = logVolStore->cbegin(); it != logVolStore->cend(); ++it) >> 134 { >> 135 G4LogicalVolume* g4LogicalVolume = *it; 105 // Use shadow of master to get instance of 136 // Use shadow of master to get instance of FM 106 G4FieldManager* masterFM = nullptr; // g4 137 G4FieldManager* masterFM = nullptr; // g4LogicalVolume->fFieldManager; 107 G4FieldManager* clonedFM = nullptr; 138 G4FieldManager* clonedFM = nullptr; 108 if (masterFM != nullptr) { << 139 if(masterFM != nullptr) >> 140 { 109 auto fmFound = masterToWorker.find(maste 141 auto fmFound = masterToWorker.find(masterFM); 110 if (fmFound == masterToWorker.cend()) { << 142 if(fmFound == masterToWorker.cend()) >> 143 { 111 // First time we see this SD, let's cl 144 // First time we see this SD, let's clone and remember... 112 try { << 145 try 113 auto insertedEl = masterToWorker.ins << 146 { >> 147 auto insertedEl = >> 148 masterToWorker.insert(FMpair(masterFM, masterFM->Clone())); 114 clonedFM = (insertedEl.first)->secon 149 clonedFM = (insertedEl.first)->second; 115 } << 150 } catch(...) 116 catch (...) { << 151 { 117 G4ExceptionDescription msg; 152 G4ExceptionDescription msg; 118 msg << "Cloning of G4FieldManager fa 153 msg << "Cloning of G4FieldManager failed." 119 << " But derived class does not 154 << " But derived class does not implement cloning. Cannot " 120 "continue."; 155 "continue."; 121 G4Exception("G4VUserDetectorConstruc << 156 G4Exception("G4VUserDetectorConstruction::CloneSD()", "Run0053", >> 157 FatalException, msg); 122 } 158 } 123 } 159 } 124 else { << 160 else >> 161 { 125 // We have already seen this SD attach 162 // We have already seen this SD attached to a different LogicalVolume, 126 // let's re-use previous clone 163 // let's re-use previous clone 127 clonedFM = (*fmFound).second; 164 clonedFM = (*fmFound).second; 128 } 165 } 129 } // masterFM != 0 166 } // masterFM != 0 130 // Note that we do not push FM to daughter 167 // Note that we do not push FM to daughters (false argument), however, since 131 // we area looping on all logical volumes 168 // we area looping on all logical volumes and we implemented the "trick" of 132 // the map master<->cloned the final effec 169 // the map master<->cloned the final effect is the same as using here the 133 // correct Boolean flag: log-volumes that 170 // correct Boolean flag: log-volumes that originally were sharing the same 134 // FM they will have cloned ones 171 // FM they will have cloned ones 135 g4LogicalVolume->SetFieldManager(clonedFM, 172 g4LogicalVolume->SetFieldManager(clonedFM, false); 136 } 173 } 137 } 174 } 138 175 139 // ------------------------------------------- 176 // -------------------------------------------------------------------- 140 void G4VUserDetectorConstruction::CloneSD() 177 void G4VUserDetectorConstruction::CloneSD() 141 { 178 { 142 // Loop on ALL logial volumes to search for 179 // Loop on ALL logial volumes to search for attached SD 143 G4LogicalVolumeStore* const logVolStore = G4 180 G4LogicalVolumeStore* const logVolStore = G4LogicalVolumeStore::GetInstance(); 144 181 145 using SDtoSDmap = std::map<G4VSensitiveDetec 182 using SDtoSDmap = std::map<G4VSensitiveDetector*, G4VSensitiveDetector*>; 146 using SDpair = std::pair<G4VSensitiveDetecto 183 using SDpair = std::pair<G4VSensitiveDetector*, G4VSensitiveDetector*>; 147 SDtoSDmap masterToWorker; 184 SDtoSDmap masterToWorker; 148 185 149 for (const auto& g4LogicalVolume : *logVolSt << 186 for(auto it = logVolStore->cbegin(); it != logVolStore->cend(); ++it) >> 187 { >> 188 G4LogicalVolume* g4LogicalVolume = *it; 150 // Use shadow of master to get the instanc 189 // Use shadow of master to get the instance of SD 151 G4VSensitiveDetector* masterSD = nullptr; 190 G4VSensitiveDetector* masterSD = nullptr; 152 G4VSensitiveDetector* clonedSD = nullptr; 191 G4VSensitiveDetector* clonedSD = nullptr; 153 if (masterSD != nullptr) { << 192 if(masterSD != nullptr) >> 193 { 154 auto sdFound = masterToWorker.find(maste 194 auto sdFound = masterToWorker.find(masterSD); 155 if (sdFound == masterToWorker.cend()) { << 195 if(sdFound == masterToWorker.cend()) >> 196 { 156 // First time we see this SD, let's cl 197 // First time we see this SD, let's clone and remember... 157 try { << 198 try 158 auto insertedEl = masterToWorker.ins << 199 { >> 200 auto insertedEl = >> 201 masterToWorker.insert(SDpair(masterSD, masterSD->Clone())); 159 clonedSD = (insertedEl.first)->secon 202 clonedSD = (insertedEl.first)->second; 160 } << 203 } catch(...) 161 catch (...) { << 204 { 162 G4ExceptionDescription msg; 205 G4ExceptionDescription msg; 163 msg << "Cloning of G4VSensitiveDetec << 206 msg << "Cloning of G4VSensitiveDetector requested for:" >> 207 << masterSD->GetName() << "\n" 164 #ifndef WIN32 208 #ifndef WIN32 165 << " (full path name: " << maste 209 << " (full path name: " << masterSD->GetFullPathName() << ").\n" 166 #endif 210 #endif 167 << " But derived class does not 211 << " But derived class does not implement cloning. Cannot " 168 "continue."; 212 "continue."; 169 G4Exception("G4VUserDetectorConstruc << 213 G4Exception("G4VUserDetectorConstruction::CloneSD()", "Run0053", >> 214 FatalException, msg); 170 } 215 } 171 } 216 } 172 else { << 217 else >> 218 { 173 // We have already seen this SD attach 219 // We have already seen this SD attached to a different LogicalVolume, 174 // let's re-use previous clone 220 // let's re-use previous clone 175 clonedSD = (*sdFound).second; 221 clonedSD = (*sdFound).second; 176 } 222 } 177 } // masterSD!=0 223 } // masterSD!=0 178 g4LogicalVolume->SetSensitiveDetector(clon 224 g4LogicalVolume->SetSensitiveDetector(clonedSD); 179 } 225 } 180 } 226 } 181 227 182 // ------------------------------------------- 228 // -------------------------------------------------------------------- 183 void G4VUserDetectorConstruction::SetSensitive << 229 void G4VUserDetectorConstruction:: 184 << 230 SetSensitiveDetector(const G4String& logVolName, >> 231 G4VSensitiveDetector* aSD, G4bool multi) 185 { 232 { 186 G4bool found = false; << 233 G4bool found = false; 187 G4LogicalVolumeStore* store = G4LogicalVolum 234 G4LogicalVolumeStore* store = G4LogicalVolumeStore::GetInstance(); 188 auto volmap = store->GetMap(); 235 auto volmap = store->GetMap(); 189 auto pos = volmap.find(logVolName); 236 auto pos = volmap.find(logVolName); 190 if (pos != volmap.cend()) { << 237 if(pos != volmap.cend()) 191 if ((pos->second.size() > 1) && !multi) { << 238 { >> 239 if ((pos->second.size()>1) && !multi) >> 240 { 192 G4String eM = "More than one logical vol 241 G4String eM = "More than one logical volumes of name <"; 193 eM += pos->first; 242 eM += pos->first; 194 eM += "> are found and thus the sensitiv 243 eM += "> are found and thus the sensitive detector <"; 195 eM += aSD->GetName(); 244 eM += aSD->GetName(); 196 eM += "> cannot be uniquely assigned."; 245 eM += "> cannot be uniquely assigned."; 197 G4Exception("G4VUserDetectorConstruction << 246 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector()", 198 FatalErrorInArgument, eM); << 247 "Run0052", FatalErrorInArgument, eM); 199 } 248 } 200 found = true; 249 found = true; 201 for (auto& i : pos->second) { << 250 for (std::size_t i = 0; i < pos->second.size(); ++i) 202 SetSensitiveDetector(i, aSD); << 251 { >> 252 SetSensitiveDetector(pos->second[i], aSD); 203 } 253 } 204 } 254 } 205 if (!found) { << 255 if(!found) >> 256 { 206 G4String eM2 = "No logical volume of name 257 G4String eM2 = "No logical volume of name <"; 207 eM2 += logVolName; 258 eM2 += logVolName; 208 eM2 += "> is found. The specified sensitiv 259 eM2 += "> is found. The specified sensitive detector <"; 209 eM2 += aSD->GetName(); 260 eM2 += aSD->GetName(); 210 eM2 += "> couldn't be assigned to any volu 261 eM2 += "> couldn't be assigned to any volume."; 211 G4Exception("G4VUserDetectorConstruction:: << 262 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector()", 212 FatalErrorInArgument, eM2); << 263 "Run0053", FatalErrorInArgument, eM2); 213 } 264 } 214 } 265 } 215 266 216 // ------------------------------------------- 267 // -------------------------------------------------------------------- 217 void G4VUserDetectorConstruction::SetSensitive << 268 void G4VUserDetectorConstruction:: 218 << 269 SetSensitiveDetector(G4LogicalVolume* logVol, G4VSensitiveDetector* aSD) 219 { 270 { 220 assert(logVol != nullptr && aSD != nullptr); 271 assert(logVol != nullptr && aSD != nullptr); 221 272 222 // The aSD has already been added by user to 273 // The aSD has already been added by user to the manager if needed 223 // G4SDManager::GetSDMpointer()->AddNewDetec 274 // G4SDManager::GetSDMpointer()->AddNewDetector(aSD); 224 275 225 // New Logic: allow for "multiple" SDs being 276 // New Logic: allow for "multiple" SDs being attached to a single LV. 226 // To do that we use a special proxy SD call 277 // To do that we use a special proxy SD called G4MultiSensitiveDetector 227 278 228 // Get existing SD if already set and check 279 // Get existing SD if already set and check if it is of the special type 229 G4VSensitiveDetector* originalSD = logVol->G 280 G4VSensitiveDetector* originalSD = logVol->GetSensitiveDetector(); 230 if (originalSD == aSD) { << 281 if(originalSD == aSD) >> 282 { 231 G4ExceptionDescription msg; 283 G4ExceptionDescription msg; 232 msg << "Attempting to add multiple times t 284 msg << "Attempting to add multiple times the same sensitive detector (\""; 233 msg << originalSD->GetName() << "\") is no 285 msg << originalSD->GetName() << "\") is not allowed, skipping."; 234 G4Exception("G4VUserDetectorConstruction:: << 286 G4Exception("G4VUserDetectorConstruction::SetSensitiveDetector", "Run0054", >> 287 JustWarning, msg); 235 return; 288 return; 236 } 289 } 237 if (originalSD == nullptr) { << 290 if(originalSD == nullptr) >> 291 { 238 logVol->SetSensitiveDetector(aSD); 292 logVol->SetSensitiveDetector(aSD); 239 } 293 } 240 else { << 294 else 241 auto msd = dynamic_cast<G4MultiSensitiveDe << 295 { 242 if (msd != nullptr) { << 296 G4MultiSensitiveDetector* msd = >> 297 dynamic_cast<G4MultiSensitiveDetector*>(originalSD); >> 298 if(msd != nullptr) >> 299 { 243 msd->AddSD(aSD); 300 msd->AddSD(aSD); 244 } 301 } 245 else { << 302 else >> 303 { 246 std::ostringstream mn; 304 std::ostringstream mn; 247 mn << "/MultiSD_" << logVol->GetName() < 305 mn << "/MultiSD_" << logVol->GetName() << "_" << logVol; 248 const G4String msdname = mn.str(); 306 const G4String msdname = mn.str(); 249 msd = new G4MultiSensitiveDetector(msdna << 307 msd = new G4MultiSensitiveDetector(msdname); 250 // We need to register the proxy to have 308 // We need to register the proxy to have correct handling of IDs 251 G4SDManager::GetSDMpointer()->AddNewDete 309 G4SDManager::GetSDMpointer()->AddNewDetector(msd); 252 msd->AddSD(originalSD); 310 msd->AddSD(originalSD); 253 msd->AddSD(aSD); 311 msd->AddSD(aSD); 254 logVol->SetSensitiveDetector(msd); 312 logVol->SetSensitiveDetector(msd); 255 } 313 } 256 } 314 } 257 } 315 } 258 316