Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/magneticfield/src/G4FieldBuilder.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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