Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // Class G4AssemblyVolume - implementation 27 // 28 // Author: Radovan Chytracek, CERN - November 29 // ------------------------------------------- 30 31 #include "G4AssemblyVolume.hh" 32 #include "G4AssemblyStore.hh" 33 #include "G4PVPlacement.hh" 34 #include "G4RotationMatrix.hh" 35 #include "G4AffineTransform.hh" 36 #include "G4LogicalVolume.hh" 37 #include "G4VPhysicalVolume.hh" 38 #include "G4ReflectionFactory.hh" 39 40 #include <sstream> 41 42 G4ThreadLocal unsigned int G4AssemblyVolume::f 43 44 // ------------------------------------------- 45 // Default constructor 46 // 47 G4AssemblyVolume::G4AssemblyVolume() 48 { 49 InstanceCountPlus(); 50 SetAssemblyID( GetInstanceCount() ); 51 SetImprintsCount( 0 ); 52 G4AssemblyStore* aStore = G4AssemblyStore::G 53 if (aStore->GetAssembly(fAssemblyID,false) ! 54 { 55 std::ostringstream message; 56 message << "The assembly has NOT been regi 57 << " Assembly " << fAssem 58 << " already existing in store !" 59 G4Exception("G4AssemblyVolume::G4AssemblyV 60 JustWarning, message); 61 } 62 else 63 { 64 aStore->Register(this); 65 } 66 } 67 68 // ------------------------------------------- 69 // Composing constructor 70 // 71 G4AssemblyVolume::G4AssemblyVolume( G4LogicalV 72 G4ThreeVec 73 G4Rotation 74 { 75 InstanceCountPlus(); 76 SetAssemblyID( GetInstanceCount() ); 77 SetImprintsCount( 0 ); 78 AddPlacedVolume(volume, translation, rotatio 79 G4AssemblyStore* aStore = G4AssemblyStore::G 80 if (aStore->GetAssembly(fAssemblyID,false) ! 81 { 82 std::ostringstream message; 83 message << "The assembly has NOT been regi 84 << " Assembly " << fAssem 85 << " already existing in store !" 86 G4Exception("G4Assembly::G4Assembly()", "G 87 JustWarning, message); 88 } 89 else 90 { 91 aStore->Register(this); 92 } 93 } 94 95 // ------------------------------------------- 96 // Destructor 97 // 98 G4AssemblyVolume::~G4AssemblyVolume() 99 { 100 std::size_t howmany = fTriplets.size(); 101 if( howmany != 0 ) 102 { 103 for( std::size_t i = 0; i < howmany; ++i ) 104 { 105 G4RotationMatrix* pRotToClean = fTriplet 106 delete pRotToClean; 107 } 108 } 109 fTriplets.clear(); 110 111 // No need to delete physical volumes, as th 112 // by physical-volumes store. 113 // 114 fPVStore.clear(); 115 InstanceCountMinus(); 116 G4AssemblyStore::GetInstance()->DeRegister(t 117 } 118 119 // ------------------------------------------- 120 // Add and place the given volume according to 121 // translation and rotation. 122 // 123 // The rotation matrix passed in can be 0 = id 124 // object on the upper stack frame. During ass 125 // a new matrix and keeps track of it so it ca 126 // time. 127 // This policy has been adopted since user has 128 // rotations are combined. 129 // 130 void G4AssemblyVolume::AddPlacedVolume( G4Logi 131 G4Thre 132 G4Rota 133 { 134 auto toStore = new G4RotationMatrix; 135 136 if( pRotation != nullptr ) { *toStore = *pR 137 138 G4AssemblyTriplet toAdd( pVolume, translatio 139 fTriplets.push_back( toAdd ); 140 } 141 142 // ------------------------------------------- 143 // Add and place the given volume according to 144 // 145 void G4AssemblyVolume::AddPlacedVolume( G4Logi 146 G4Tran 147 { 148 // Decompose transformation 149 G4Scale3D scale; 150 G4Rotate3D rotation; 151 G4Translate3D translation; 152 transformation.getDecomposition(scale, rotat 153 154 G4ThreeVector v = translation.getTranslation 155 auto r = new G4RotationMatrix; 156 *r = rotation.getRotation(); 157 158 G4bool isReflection = false; 159 if (scale(0,0)*scale(1,1)*scale(2,2) < 0.) 160 161 G4AssemblyTriplet toAdd( pVolume, v, r, isRe 162 fTriplets.push_back( toAdd ); 163 } 164 165 // ------------------------------------------- 166 // Add and place the given assembly volume acc 167 // translation and rotation. 168 // 169 void G4AssemblyVolume::AddPlacedAssembly( G4As 170 G4Th 171 G4Ro 172 { 173 auto toStore = new G4RotationMatrix; 174 175 if( pRotation != nullptr ) { *toStore = *pR 176 177 G4AssemblyTriplet toAdd( pAssembly, translat 178 fTriplets.push_back( toAdd ); 179 } 180 181 // ------------------------------------------- 182 // Add and place the given assembly volume acc 183 // transformation 184 // 185 void G4AssemblyVolume::AddPlacedAssembly( G4As 186 G4Tr 187 { 188 // Decompose transformation 189 // 190 G4Scale3D scale; 191 G4Rotate3D rotation; 192 G4Translate3D translation; 193 transformation.getDecomposition(scale, rotat 194 195 G4ThreeVector v = translation.getTransl 196 auto r = new G4RotationMatrix; 197 *r = rotation.getRotation(); 198 199 G4bool isReflection = false; 200 if (scale(0,0)*scale(1,1)*scale(2,2) < 0.) 201 202 G4AssemblyTriplet toAdd( pAssembly, v, r, is 203 fTriplets.push_back( toAdd ); 204 } 205 206 // ------------------------------------------- 207 // Create an instance of an assembly volume in 208 // mother volume. This works analogically to m 209 // This method makes use of the Geant4 affine 210 // The algorithm is defined as follows: 211 // 212 // Having rotation matrix Rm and translation v 213 // inside the mother and rotation matrix Ra an 214 // to be applied inside the assembly itself fo 215 // volumes the resulting transformation is 216 // 217 // Tfinal = Ta * Tm 218 // 219 // where Ta and Tm are constructed as 220 // 221 // -1 222 // Ta = Ra * Ta and Tm = 223 // 224 // which in words means that we create first t 225 // by inverse rotation matrices and translatio 226 // The resulting final transformation to be ap 227 // participating volumes is their product. 228 // 229 // IMPORTANT NOTE! 230 // The order of multiplication is reversed whe 231 // transformation matrix(G4Transform3D class). 232 // 233 // The rotation matrix passed in can be 0 = id 234 // object on the upper stack frame. During ass 235 // a new matrix and keeps track of it so it ca 236 // time. 237 // This policy has been adopted since user has 238 // rotations are combined. 239 // 240 // If the assembly volume contains assembly (a 241 // recursively with composed transformation: 242 // 243 // Tanew = Ta * Ta' 244 // 245 void G4AssemblyVolume::MakeImprint( G4Assembly 246 G4LogicalV 247 G4Transfor 248 G4int copy 249 G4bool sur 250 { 251 std::size_t numberOfDaughters; 252 253 if( copyNumBase == 0 ) 254 { 255 numberOfDaughters = pMotherLV->GetNoDaught 256 } 257 else 258 { 259 numberOfDaughters = copyNumBase; 260 } 261 262 // We start from the first available index 263 // 264 ++numberOfDaughters; 265 266 ImprintsCountPlus(); 267 268 auto triplets = pAssembly->fTriplets; 269 270 // store the transformation in a container ( 271 fImprintsTransf[GetImprintsCount()] = transf 272 273 for( std::size_t i = 0; i < triplets.size(); 274 { 275 G4Transform3D Ta( *(triplets[i].GetRotatio 276 triplets[i].GetTranslati 277 if ( triplets[i].IsReflection() ) { Ta = 278 279 G4Transform3D Tfinal = transformation * Ta 280 281 if ( triplets[i].GetVolume() != nullptr ) 282 { 283 // Generate the unique name for the next 284 // The name has format: 285 // 286 // av_WWW_impr_XXX_YYY_ZZZ 287 // where the fields mean: 288 // WWW - assembly volume instance number 289 // XXX - assembly volume imprint number 290 // YYY - the name of a log. volume we wa 291 // ZZZ - the log. volume index inside th 292 // 293 std::stringstream pvName; 294 pvName << "av_" 295 << GetAssemblyID() 296 << "_impr_" 297 << GetImprintsCount() 298 << "_" 299 << triplets[i].GetVolume()->GetNa 300 << "_pv_" 301 << i 302 << std::ends; 303 304 // Generate a new physical volume instan 305 // (as we allow 3D transformation use G4 306 // take into account eventual reflectio 307 // 308 G4PhysicalVolumesPair pvPlaced 309 = G4ReflectionFactory::Instance()->Pla 310 311 312 313 314 315 316 317 // Register the physical volume created 318 // 319 fPVStore.push_back( pvPlaced.first ); 320 if ( pvPlaced.second != nullptr ) { fPV 321 322 // Here I want to save the imprint trans 323 // imprintTrans[GetImprintsCount()] = tr 324 325 } 326 else if ( triplets[i].GetAssembly() != nul 327 { 328 // Place volumes in this assembly with c 329 // 330 MakeImprint( triplets[i].GetAssembly(), 331 Tfinal, (G4int)i*100+copyNu 332 } 333 else 334 { 335 G4Exception("G4AssemblyVolume::MakeImpri 336 "GeomVol0003", FatalExceptio 337 "Triplet has no volume and n 338 } 339 } 340 } 341 342 // ------------------------------------------- 343 void G4AssemblyVolume::MakeImprint( G4LogicalV 344 G4ThreeVec 345 G4Rotation 346 G4int copy 347 G4bool sur 348 { 349 // If needed user can specify explicitely th 350 // off for the generation of phys. vol. copy 351 // The old behaviour is preserved when copyN 352 // copy numbers start from the count equal t 353 // volumes before an imprint is made 354 355 // Compose transformation 356 // 357 if( pRotationInMother == nullptr ) 358 { 359 // Make it by default an indentity matrix 360 // 361 pRotationInMother = 362 const_cast<G4RotationMatrix*>( &G4Rotati 363 } 364 365 G4Transform3D transform( *pRotationInMother, 366 translationInMothe 367 MakeImprint(this, pMotherLV, transform, copy 368 } 369 370 // ------------------------------------------- 371 void G4AssemblyVolume::MakeImprint( G4LogicalV 372 G4Transfor 373 G4int copy 374 G4bool sur 375 { 376 // If needed user can specify explicitely th 377 // off for the generation of phys. vol. copy 378 // The old behaviour is preserved when copyN 379 // copy numbers start from the count equal t 380 // volumes before a imprint is made 381 382 MakeImprint(this, pMotherLV, transformation, 383 } 384 385 // ------------------------------------------- 386 unsigned int G4AssemblyVolume::GetInstanceCoun 387 { 388 return G4AssemblyVolume::fsInstanceCounter; 389 } 390 391 // ------------------------------------------- 392 void G4AssemblyVolume::SetInstanceCount( unsig 393 { 394 G4AssemblyVolume::fsInstanceCounter = value; 395 } 396 397 // ------------------------------------------- 398 void G4AssemblyVolume::InstanceCountPlus() 399 { 400 G4AssemblyVolume::fsInstanceCounter++; 401 } 402 403 // ------------------------------------------- 404 void G4AssemblyVolume::InstanceCountMinus() 405 { 406 G4AssemblyVolume::fsInstanceCounter--; 407 } 408