Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 /// \file DetectorConstruction.cc 28 /// \brief Implementation of the DetectorConstruction class 29 30 #include "DetectorConstruction.hh" 31 32 #include "DetectorMessenger.hh" 33 34 #include "G4GeometryManager.hh" 35 #include "G4LogicalVolume.hh" 36 #include "G4LogicalVolumeStore.hh" 37 #include "G4Material.hh" 38 #include "G4NistManager.hh" 39 #include "G4PVPlacement.hh" 40 #include "G4PhysicalConstants.hh" 41 #include "G4PhysicalVolumeStore.hh" 42 #include "G4ReflectionFactory.hh" 43 #include "G4RotationMatrix.hh" 44 #include "G4SolidStore.hh" 45 #include "G4SystemOfUnits.hh" 46 #include "G4Transform3D.hh" 47 #include "G4Trd.hh" 48 #include "G4Tubs.hh" 49 50 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 51 52 DetectorConstruction::DetectorConstruction() 53 { 54 fMessenger = new DetectorMessenger(this); 55 } 56 57 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 58 59 DetectorConstruction::~DetectorConstruction() 60 { 61 delete fMessenger; 62 } 63 64 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 65 66 G4VPhysicalVolume* DetectorConstruction::Construct() 67 { 68 // Materials 69 G4NistManager* nist = G4NistManager::Instance(); 70 G4Material* material = nist->FindOrBuildMaterial("G4_AIR"); 71 72 // Clean old geometry, if any 73 // 74 G4GeometryManager::GetInstance()->OpenGeometry(); 75 G4PhysicalVolumeStore::GetInstance()->Clean(); 76 G4LogicalVolumeStore::GetInstance()->Clean(); 77 G4SolidStore::GetInstance()->Clean(); 78 G4ReflectionFactory::Instance()->Clean(); 79 80 // World 81 // 82 G4double rmin = 0.; 83 G4double rmax = 5 * cm; 84 G4double hz = 5 * cm; 85 G4double phiMin = 0.; 86 G4double deltaPhi = 360 * degree; 87 88 auto solidWorld = new G4Tubs("World", // name 89 rmin, rmax, hz, phiMin, deltaPhi); // size 90 91 fWorldVolume = new G4LogicalVolume(solidWorld, // solid 92 material, // material 93 "World"); // name 94 95 G4VPhysicalVolume* physiWorld = new G4PVPlacement(nullptr, // no rotation 96 G4ThreeVector(), // at (0,0,0) 97 fWorldVolume, // logical volume 98 "World", // name 99 nullptr, // mother volume 100 false, // no boolean operation 101 0); // copy number 102 103 // Trd volume 104 // 105 G4double dX1 = 1 * cm; 106 G4double dX2 = 1 * cm; 107 G4double dY1 = 1 * cm; 108 G4double dY2 = 2 * cm; 109 G4double dZ = 3 * cm; 110 111 auto solidTrd = new G4Trd("trd", // name 112 dX1 / 2, dX2 / 2, dY1 / 2, dY2 / 2, dZ / 2); // size 113 114 fTrdVolume = new G4LogicalVolume(solidTrd, // solid 115 material, // material 116 "trd"); // name 117 118 // Place Volume1 and Volume2 according to selected methods 119 // 120 switch (fMethod) { 121 case kWithDirectMatrix: 122 PlaceWithDirectMatrix(); 123 break; 124 case kWithInverseMatrix: 125 PlaceWithInverseMatrix(); 126 break; 127 case kWithAxialRotations: 128 PlaceWithAxialRotations(); 129 break; 130 case kWithEulerAngles: 131 PlaceWithEulerAngles(); 132 break; 133 case kWithReflections: 134 PlaceWithReflections(); 135 break; 136 default:; 137 ; 138 } 139 140 // Return the root volume 141 // 142 return physiWorld; 143 } 144 145 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 146 147 void DetectorConstruction::PlaceWithDirectMatrix() 148 { 149 G4double og = 3 * cm; 150 151 // 1st position 152 // 153 G4double phi = 30 * deg; 154 // u, v, w are the daughter axes, projected on the mother frame 155 G4ThreeVector u = G4ThreeVector(0, 0, -1); 156 G4ThreeVector v = G4ThreeVector(-std::sin(phi), std::cos(phi), 0.); 157 G4ThreeVector w = G4ThreeVector(std::cos(phi), std::sin(phi), 0.); 158 G4RotationMatrix rotm1 = G4RotationMatrix(u, v, w); 159 G4cout << "\n --> phi = " << phi / deg << " deg; direct rotation matrix : "; 160 rotm1.print(G4cout); 161 G4ThreeVector position1 = og * w; 162 G4Transform3D transform1 = G4Transform3D(rotm1, position1); 163 164 new G4PVPlacement(transform1, // position, rotation 165 fTrdVolume, // logical volume 166 "Trd", // name 167 fWorldVolume, // mother volume 168 false, // no boolean operation 169 1); // copy number 170 171 // 2nd position 172 // 173 phi = phi + 90 * deg; 174 v = G4ThreeVector(-std::sin(phi), std::cos(phi), 0.); 175 w = G4ThreeVector(std::cos(phi), std::sin(phi), 0.); 176 G4RotationMatrix rotm2 = G4RotationMatrix(u, v, w); 177 G4ThreeVector position2 = og * w; 178 G4Transform3D transform2 = G4Transform3D(rotm2, position2); 179 new G4PVPlacement(transform2, // position, rotation 180 fTrdVolume, // logical volume 181 "Trd", // name 182 fWorldVolume, // mother volume 183 false, // no boolean operation 184 2); // copy number 185 } 186 187 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 188 189 void DetectorConstruction::PlaceWithInverseMatrix() 190 { 191 G4double og = 3 * cm; 192 193 // 1st position 194 // 195 G4double phi = 30 * deg; 196 // u, v, w are the daughter axes, projected on the mother frame 197 G4ThreeVector u = G4ThreeVector(0, 0, -1); 198 G4ThreeVector v = G4ThreeVector(-std::sin(phi), std::cos(phi), 0.); 199 G4ThreeVector w = G4ThreeVector(std::cos(phi), std::sin(phi), 0.); 200 G4RotationMatrix rotm1 = G4RotationMatrix(u, v, w); 201 auto rotm1Inv = new G4RotationMatrix(rotm1.inverse()); 202 G4cout << "\n --> phi = " << phi / deg << " deg; inverse rotation matrix : "; 203 rotm1Inv->print(G4cout); 204 G4ThreeVector position1 = og * w; 205 206 new G4PVPlacement(rotm1Inv, position1, 207 fTrdVolume, // logical volume 208 "Trd", // name 209 fWorldVolume, // mother volume 210 false, // no boolean operation 211 1); // copy number 212 213 // 2nd position 214 // 215 phi = phi + 90 * deg; 216 v = G4ThreeVector(-std::sin(phi), std::cos(phi), 0.); 217 w = G4ThreeVector(std::cos(phi), std::sin(phi), 0.); 218 G4RotationMatrix rotm2 = G4RotationMatrix(u, v, w); 219 auto rotm2Inv = new G4RotationMatrix(rotm2.inverse()); 220 G4ThreeVector position2 = og * w; 221 222 new G4PVPlacement(rotm2Inv, // rotation 223 position2, // position 224 fTrdVolume, // logical volume 225 "Trd", // name 226 fWorldVolume, // mother volume 227 false, // no boolean operation 228 2); // copy number 229 } 230 231 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 232 233 void DetectorConstruction::PlaceWithAxialRotations() 234 { 235 G4double og = 3 * cm; 236 237 // 1st position (with first G4PVPlacement constructor) 238 // 239 G4double phi = 30 * deg, theta = 90 * deg; 240 G4ThreeVector rotAxis = G4ThreeVector(std::sin(theta - pi / 2), 0., std::cos(theta - pi / 2)); 241 G4RotationMatrix rotm1 = G4RotationMatrix(); 242 rotm1.rotateY(theta); 243 rotm1.rotate(phi, rotAxis); 244 G4cout << "\n --> direct rotation matrix : " 245 << " theta = " << theta / deg << " deg;" 246 << " phi = " << phi / deg << " deg;"; 247 rotm1.print(G4cout); 248 G4ThreeVector w = 249 G4ThreeVector(std::sin(theta) * std::cos(phi), std::sin(phi), std::cos(theta) * std::cos(phi)); 250 G4ThreeVector position1 = og * w; 251 G4Transform3D transform1(rotm1, position1); 252 253 new G4PVPlacement(transform1, // rotation,position 254 fTrdVolume, // logical volume 255 "Trd", // name 256 fWorldVolume, // mother volume 257 false, // no boolean operation 258 1); // copy number 259 260 // 2nd position (with second G4PVPlacement constructor) 261 // 262 phi = phi + 90 * deg; 263 // rotm2Inv could be calculated with rotm2.inverse() 264 // but also by the following : 265 auto rotm2Inv = new G4RotationMatrix(); 266 rotm2Inv->rotate(-phi, rotAxis); 267 rotm2Inv->rotateY(-theta); 268 w = 269 G4ThreeVector(std::sin(theta) * std::cos(phi), std::sin(phi), std::cos(theta) * std::cos(phi)); 270 G4ThreeVector position2 = og * w; 271 272 new G4PVPlacement(rotm2Inv, // rotation 273 position2, // position 274 fTrdVolume, // logical volume 275 "Trd", // name 276 fWorldVolume, // mother volume 277 false, // no boolean operation 278 2); // copy number 279 } 280 281 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 282 283 void DetectorConstruction::PlaceWithEulerAngles() 284 { 285 // definitions : mother frame = {x,y,z} ; daughter frame = {u,v,w} 286 // n = node line = intercept of xy and uv planes 287 // phi_euler = (x,n) : precession 288 // theta_euler = (z,w) : nutation 289 // psi_euler = (n,u) : proper rotation 290 291 G4double og = 3 * cm; 292 293 // 1st position (with first G4PVPlacement constructor) 294 // 295 G4double phi = 30 * deg; 296 G4double phi_euler = phi + pi / 2; 297 G4double theta_euler = 90 * deg; 298 G4double psi_euler = -90 * deg; 299 // attention : clhep Euler constructor build inverse matrix ! 300 G4RotationMatrix rotm1Inv = G4RotationMatrix(phi_euler, theta_euler, psi_euler); 301 G4RotationMatrix rotm1 = rotm1Inv.inverse(); 302 // remark : could be built as rotm1 = G4RotationMatrix(-psi, -theta, -phi) 303 G4cout << "\n --> phi = " << phi / deg << " deg; direct rotation matrix : "; 304 rotm1.print(G4cout); 305 G4ThreeVector w = G4ThreeVector(std::cos(phi), std::sin(phi), 0.); 306 G4ThreeVector position1 = og * w; 307 G4Transform3D transform1 = G4Transform3D(rotm1, position1); 308 309 new G4PVPlacement(transform1, // position, rotation 310 fTrdVolume, // logical volume 311 "Trd", // name 312 fWorldVolume, // mother volume 313 false, // no boolean operation 314 1); // copy number 315 316 // 2nd position (with second G4PVPlacement constructor) 317 // 318 phi = phi + 90 * deg; 319 320 phi_euler = phi + pi / 2; 321 auto rotm2Inv = new G4RotationMatrix(phi_euler, theta_euler, psi_euler); 322 w = G4ThreeVector(std::cos(phi), std::sin(phi), 0.); 323 G4ThreeVector position2 = og * w; 324 325 new G4PVPlacement(rotm2Inv, // rotation 326 position2, // position 327 fTrdVolume, // logical volume 328 "Trd", // name 329 fWorldVolume, // mother volume 330 false, // no boolean operation 331 2); // copy number 332 } 333 334 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 335 336 void DetectorConstruction::PlaceWithReflections() 337 { 338 /// Placement with reflections. 339 /// In order to better show the reflection symmetry we do not apply 340 /// the rotation along Y axis. 341 342 G4double og = 3 * cm; 343 344 // Place first two positionz in z = + 3cm 345 // 346 347 // 1st position 348 G4double phi = 30 * deg; 349 G4RotationMatrix rotm1; 350 // rotm1.rotateY(90*deg); 351 rotm1.rotateZ(phi); 352 G4ThreeVector uz = G4ThreeVector(std::cos(phi), std::sin(phi), 0); 353 G4ThreeVector position = og * uz; 354 G4Transform3D transform1(rotm1, position); 355 G4Transform3D translateZ = HepGeom::Translate3D(0, 0, 3. * cm); 356 357 new G4PVPlacement(translateZ * transform1, // rotation,position 358 fTrdVolume, // logical volume 359 "Trd", // name 360 fWorldVolume, // mother volume 361 false, // no boolean operation 362 1); // copy number 363 364 // 2nd position 365 phi = phi + pi / 2; 366 G4RotationMatrix rotm2; 367 // rotm2.rotateY(90*deg); 368 rotm2.rotateZ(phi); 369 uz = G4ThreeVector(std::cos(phi), std::sin(phi), 0.); 370 position = og * uz; 371 G4Transform3D transform2 = G4Transform3D(rotm2, position); 372 373 new G4PVPlacement(translateZ * transform2, // rotation, position 374 fTrdVolume, // logical volume 375 "Trd", // name 376 fWorldVolume, // mother volume 377 false, // no boolean operation 378 2); // copy number 379 380 // Place next two positionz in z = - 3cm with reflection 381 // 382 383 // 3rd position 384 translateZ = HepGeom::Translate3D(0, 0, -3. * cm); 385 G4Transform3D reflect3D = HepGeom::ReflectZ3D(); 386 387 G4ReflectionFactory::Instance()->Place(translateZ * transform1 * reflect3D, // rotation,position 388 "Trd", // name 389 fTrdVolume, // logical volume 390 fWorldVolume, // mother volume 391 false, // no boolean operation 392 3); // copy number 393 394 // 4rd position 395 G4ReflectionFactory::Instance()->Place(translateZ * transform2 * reflect3D, // rotation,position 396 "Trd", // name 397 fTrdVolume, // logical volume 398 fWorldVolume, // mother volume 399 false, // no boolean operation 400 4); // copy number 401 } 402 403 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 404 405 #include "G4RunManager.hh" 406 407 void DetectorConstruction::SetMethod(EMethod method) 408 { 409 fMethod = method; 410 G4RunManager::GetRunManager()->DefineWorldVolume(Construct()); 411 } 412 413 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 414