Geant4 Cross Reference |
1 // ******************************************************************** 2 // * License and Disclaimer * 3 // * * 4 // * The Geant4 software is copyright of the Copyright Holders of * 5 // * the Geant4 Collaboration. It is provided under the terms and * 6 // * conditions of the Geant4 Software License, included in the file * 7 // * LICENSE and available at http://cern.ch/geant4/license . These * 8 // * include a list of copyright holders. * 9 // * * 10 // * Neither the authors of this software system, nor their employing * 11 // * institutes,nor the agencies providing financial support for this * 12 // * work make any representation or warranty, express or implied, * 13 // * regarding this software system or assume any liability for its * 14 // * use. Please see the license in the file LICENSE and URL above * 15 // * for the full disclaimer and the limitation of liability. * 16 // * * 17 // * This code implementation is the result of the scientific and * 18 // * technical work of the GEANT4 collaboration. * 19 // * By using, copying, modifying or distributing the software (or * 20 // * any work based on the software) you agree to acknowledge its * 21 // * use in resulting scientific publications, and indicate your * 22 // * acceptance of all terms of the Geant4 Software license. * 23 // ******************************************************************** 24 // 25 //------------------------------------------------ 26 // The Geant4 Virtual Monte Carlo package 27 // Copyright (C) 2007 - 2015 Ivana Hrivnacova 28 // All rights reserved. 29 // 30 // For the licensing terms see geant4_vmc/LICENSE. 31 // Contact: root-vmc@cern.ch 32 //------------------------------------------------- 33 34 /// \file G4FieldBuilder.cc 35 /// \brief Implementation of the G4FieldBuilder class 36 /// 37 /// \author I. Hrivnacova; IJCLab, Orsay 38 39 #include "G4FieldBuilder.hh" 40 #include "G4FieldBuilderMessenger.hh" 41 42 #include "G4Exception.hh" 43 #include "G4FieldParameters.hh" 44 #include "G4FieldSetup.hh" 45 #include "G4LogicalVolume.hh" 46 #include "G4ios.hh" 47 48 G4ThreadLocal G4Field* G4FieldBuilder::fGlobalField = nullptr; 49 G4ThreadLocal G4bool G4FieldBuilder::fIsConstructed = false; 50 51 //_____________________________________________________________________________ 52 G4FieldBuilder* G4FieldBuilder::Instance() 53 { 54 static G4FieldBuilder instance; 55 fgIsInstance = true; 56 return &instance; 57 } 58 59 //_____________________________________________________________________________ 60 G4FieldBuilder::G4FieldBuilder() 61 { 62 // Default constructor 63 64 fMessenger = new G4FieldBuilderMessenger(this); 65 66 // Field parameters for global field 67 fFieldParameters.push_back(new G4FieldParameters()); 68 } 69 70 //_____________________________________________________________________________ 71 G4FieldBuilder::~G4FieldBuilder() 72 { 73 // Destructor 74 75 delete fMessenger; 76 77 for (auto parameters : fFieldParameters) { 78 delete parameters; 79 } 80 81 for (auto setup : GetFieldSetups()) { 82 delete setup; 83 } 84 85 fgIsInstance = false; 86 87 // magnetic field objects are deleted via G4 kernel 88 } 89 90 // 91 // private methods 92 // 93 94 //_____________________________________________________________________________ 95 G4FieldParameters* G4FieldBuilder::GetOrCreateFieldParameters( 96 const G4String& volumeName) 97 { 98 // Get field parameters with the given volumeName or create them if they 99 // do not exist yet 100 101 // Get user field parameters 102 for (auto fieldParameters : fFieldParameters) { 103 if (fieldParameters->GetVolumeName() == volumeName) { 104 // G4cout << "Found field parameters for " << volumeName << G4endl; 105 return fieldParameters; 106 } 107 } 108 109 // Create field parameters if not yet defined 110 // G4cout << "Go to create field parameters for " << volumeName << G4endl; 111 auto fieldParameters = new G4FieldParameters(volumeName); 112 fFieldParameters.push_back(fieldParameters); 113 return fieldParameters; 114 } 115 116 //_____________________________________________________________________________ 117 G4FieldSetup* G4FieldBuilder::GetFieldSetup(G4LogicalVolume* lv) 118 { 119 // Get field setup with the given logical volume 120 121 // Get user field parameters 122 for (auto fieldSetup : GetFieldSetups()) { 123 if (fieldSetup->GetLogicalVolume() == lv) { 124 return fieldSetup; 125 } 126 } 127 128 return nullptr; 129 } 130 131 //_____________________________________________________________________________ 132 void G4FieldBuilder::CreateFieldSetup(G4Field* field, 133 G4FieldParameters* fieldParameters, G4LogicalVolume* lv) 134 { 135 // Create magnetic, electromagnetic or gravity field setup 136 137 auto fieldSetup = new G4FieldSetup(*fieldParameters, field, lv); 138 fieldSetup->PrintInfo(fVerboseLevel); 139 140 if (fFieldSetups.Get() == nullptr) { 141 auto fieldSetups = new std::vector<G4FieldSetup*>(); 142 fFieldSetups.Put(fieldSetups); 143 } 144 145 GetFieldSetups().push_back(fieldSetup); 146 } 147 148 //_____________________________________________________________________________ 149 void G4FieldBuilder::ConstructGlobalField() 150 { 151 // Construct Geant4 global magnetic field setup 152 153 if (fVerboseLevel > 1) { 154 G4cout << "G4FieldBuilder::ConstructGlobalField " << G4endl; 155 } 156 157 CreateFieldSetup(fGlobalField, fFieldParameters[0], nullptr); 158 } 159 160 //_____________________________________________________________________________ 161 void G4FieldBuilder::ConstructLocalFields() 162 { 163 // Construct Geant4 local magnetic field setups from the local fields map 164 165 if (fLocalFields.Get() == nullptr) return; 166 167 if (fVerboseLevel > 1) { 168 G4cout << "G4FieldBuilder::ConstructLocalFields()" << G4endl; 169 } 170 171 // Loop over local field map 172 for (auto [lv, field] : GetLocalFields()) { 173 174 // Volume name 175 const auto& volumeName = lv->GetName(); 176 177 // Get or create user field parameters 178 G4FieldParameters* fieldParameters = 179 GetOrCreateFieldParameters(volumeName); 180 181 if (fVerboseLevel > 1) { 182 G4cout << "Construct local field in volume: " << volumeName << G4endl; 183 } 184 185 // Create magnetic field 186 CreateFieldSetup(field, fieldParameters, lv); 187 } 188 } 189 190 //_____________________________________________________________________________ 191 void G4FieldBuilder::UpdateFieldSetups() 192 { 193 // Update all field setups 194 195 if (fVerboseLevel > 1) { 196 G4cout << "G4FieldBuilder::UpdateFieldSetups " << G4endl; 197 } 198 199 for (auto fieldSetup : GetFieldSetups()) { 200 fieldSetup->Update(); 201 202 if (fVerboseLevel > 1) { 203 fieldSetup->PrintInfo(fVerboseLevel, "updated"); 204 } 205 } 206 } 207 208 // 209 // public methods 210 // 211 212 //_____________________________________________________________________________ 213 G4FieldParameters* G4FieldBuilder::CreateFieldParameters( 214 const G4String& fieldVolName) 215 { 216 // Create local magnetic field parameters (configuration) which can be then 217 // configured by the user via UI commands. 218 // The parameters are used in geometry only if a local magnetic field is 219 // associated with the volumes with the given name. 220 221 auto fieldParameters = new G4FieldParameters(fieldVolName); 222 fFieldParameters.push_back(fieldParameters); 223 224 return fieldParameters; 225 } 226 227 //_____________________________________________________________________________ 228 void G4FieldBuilder::ConstructFieldSetup() 229 { 230 // Construct setups for all registered fields. 231 232 if (fVerboseLevel > 1) { 233 G4cout << "G4FieldBuilder::ConstructField" << G4endl; 234 } 235 236 if (fIsConstructed) { 237 G4Exception( 238 "G4FieldBuilder::ConstructField:", "GeomFieldParameters0001", 239 JustWarning, "Field was already constructed."); 240 return; 241 } 242 243 ConstructGlobalField(); 244 ConstructLocalFields(); 245 246 UpdateFieldSetups(); 247 248 fIsConstructed = true; 249 } 250 251 //_____________________________________________________________________________ 252 void G4FieldBuilder::UpdateField() 253 { 254 // Update magnetic field. 255 // This function must be called if the field parameters were changed 256 // in other than PreInit> phase. 257 258 if (fFieldSetups.Get() == nullptr) { 259 G4Exception( 260 "G4FieldBuilder::UpdateField", "GeomFieldParameters0001", 261 JustWarning, "No field setup is defined."); 262 return; 263 } 264 265 if (fVerboseLevel > 1) { 266 G4cout << "G4FieldBuilder::UpdateField" << G4endl; 267 } 268 269 // Update the objects defined in G4FieldSetup's 270 UpdateFieldSetups(); 271 } 272 273 //_____________________________________________________________________________ 274 void G4FieldBuilder::Reinitialize() 275 { 276 // Reinitialize if geometry has been modified. 277 // This function is called by G4RunManager during ReinitializeGeometry() 278 279 if (fVerboseLevel > 1) { 280 G4cout << "G4FieldBuilder::Reinitialize" << G4endl; 281 } 282 283 // Delete global field 284 delete fGlobalField; 285 fGlobalField = nullptr; 286 287 // Delete local fields if defined 288 if (fLocalFields.Get() != nullptr) { 289 for (auto vectorElement : GetLocalFields()) { 290 delete vectorElement.second; 291 } 292 // Clear local fields map 293 GetLocalFields().clear(); 294 } 295 296 // Clear field setups if defined 297 if (fFieldSetups.Get() != nullptr) { 298 for (auto fieldSetup : GetFieldSetups()) { 299 fieldSetup->SetG4Field(nullptr); 300 fieldSetup->Clear(); 301 } 302 } 303 304 fIsConstructed = false; 305 306 if (fVerboseLevel > 1) { 307 G4cout << "End of G4FieldBuilder::Reinitialize" << G4endl; 308 } 309 } 310 311 //_____________________________________________________________________________ 312 void G4FieldBuilder::SetFieldType(G4FieldType fieldType) 313 { 314 // Default field type is set to kMagnetic; 315 // this function should be called for other than magnetic field 316 // in order to update the default equation and stepper types. 317 318 if (fIsConstructed) { 319 G4Exception( 320 "G4FieldBuilder::SetFieldType:", "GeomFieldParameters0001", 321 JustWarning, "Field was already constructed."); 322 return; 323 } 324 325 fFieldParameters[0]->SetFieldType(fieldType); 326 327 // change default equation and stepper if other than magnetic field 328 if (fieldType == kElectroMagnetic) { 329 fFieldParameters[0]->SetEquationType(kEqElectroMagnetic); 330 fFieldParameters[0]->SetStepperType(kClassicalRK4); 331 } 332 } 333 334 //_____________________________________________________________________________ 335 void G4FieldBuilder::SetGlobalField(G4Field* field, G4bool warn) 336 { 337 // Set or reset the global field. 338 // Update field objects, if the field was already constructed. 339 // If warn, issue a warning if the previous field is deleted. 340 341 if (fGlobalField != nullptr && warn) { 342 G4Exception( 343 "G4FieldBuilder::SetGlobalField:", "GeomFieldParameters0001", 344 JustWarning, "The global field already exists, it will be deleted."); 345 } 346 delete fGlobalField; 347 fGlobalField = field; 348 349 if (fIsConstructed) { 350 // update the global field objects if already constructed 351 GetFieldSetups()[0]->SetG4Field(field); 352 GetFieldSetups()[0]->Update(); 353 } 354 } 355 356 //_____________________________________________________________________________ 357 void G4FieldBuilder::SetLocalField( 358 G4Field* field, G4LogicalVolume* lv, G4bool warn) 359 { 360 // Register the local field in the map. 361 // Update field objects, if the field was already constructed. 362 // If warn, issue a warning if the previous field is deleted. 363 364 if (lv == nullptr) { 365 G4cerr << "Cannot register local field without Logical volume." << G4endl; 366 return; 367 } 368 369 if (fLocalFields.Get() == nullptr) { 370 auto localFields = new std::vector<std::pair<G4LogicalVolume*, G4Field*>>(); 371 fLocalFields.Put(localFields); 372 } 373 374 auto it = GetLocalFields().begin(); 375 for (it = GetLocalFields().begin(); it != GetLocalFields().end(); ++it) { 376 if (it->first == lv) break; 377 } 378 379 if (it != GetLocalFields().end()) { 380 // replaced field if already in the map 381 if (warn) { 382 G4ExceptionDescription descr; 383 descr << "Logical volume " << lv->GetName() << " has already field." 384 " It will be deleted."; 385 G4Exception( 386 "G4FieldBuilder::SetLocalField:", "GeomFieldParameters0001", 387 JustWarning, descr); 388 } 389 delete it->second; 390 it->second = field; 391 } 392 else { 393 // register field in the map 394 GetLocalFields().push_back(std::pair(lv,field)); 395 } 396 397 if (fIsConstructed) { 398 // update this local field objects if already constructed 399 auto fieldSetup = GetFieldSetup(lv); 400 if (fieldSetup == nullptr) { 401 G4Exception( 402 "G4FieldBuilder::SetLocalField:", "GeomFieldParameters0001", 403 JustWarning, "Cannot get field setup for a local field."); 404 return; 405 } 406 fieldSetup->SetG4Field(field); 407 fieldSetup->Update(); 408 } 409 } 410 411 //_____________________________________________________________________________ 412 void G4FieldBuilder::SetUserEquationOfMotion( 413 G4EquationOfMotion* equation, G4String volumeName) 414 { 415 // Set user equation of motion 416 417 if (!volumeName.size()) { 418 // global field 419 fFieldParameters[0]->SetUserEquationOfMotion(equation); 420 } 421 else { 422 // local field 423 // Get or create user field parameters 424 G4FieldParameters* fieldParameters = 425 GetOrCreateFieldParameters(volumeName); 426 fieldParameters->SetUserEquationOfMotion(equation); 427 } 428 } 429 430 //_____________________________________________________________________________ 431 void G4FieldBuilder::SetUserStepper( 432 G4MagIntegratorStepper* stepper, G4String volumeName) 433 { 434 // Set user stepper 435 436 if (!volumeName.size()) { 437 // global field 438 fFieldParameters[0]->SetUserStepper(stepper); 439 } 440 else { 441 // local field 442 // Get or create user field parameters 443 G4FieldParameters* fieldParameters = 444 GetOrCreateFieldParameters(volumeName); 445 fieldParameters->SetUserStepper(stepper); 446 } 447 } 448 449 //_____________________________________________________________________________ 450 G4FieldParameters* G4FieldBuilder::GetFieldParameters( 451 const G4String& volumeName) const 452 { 453 // Get field parameters with the given volumeName. 454 // Return global field parameters, if volume name is empty. 455 456 // Get user field parameters 457 for (auto fieldParameters : fFieldParameters) { 458 if (fieldParameters->GetVolumeName() == volumeName) { 459 // G4cout << "Found field parameters for " << volumeName << G4endl; 460 return fieldParameters; 461 } 462 } 463 464 G4Exception( 465 "G4FieldBuilder::GetFieldParameters:", "GeomFieldParameters0001", 466 JustWarning, "Field parameters not found."); 467 return nullptr; 468 } 469