Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4FieldBuilder.cc
Go to the documentation of this file.
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// Implementation of the G4FieldBuilder class
26//
27// Author: Ivana Hrivnacova (IJCLab, Orsay), 2024
28// -------------------------------------------------------------------
29
30#include "G4FieldBuilder.hh"
32
33#include "G4Exception.hh"
34#include "G4Field.hh"
35#include "G4FieldParameters.hh"
36#include "G4FieldSetup.hh"
37#include "G4LogicalVolume.hh"
38#include "G4ios.hh"
39
40G4ThreadLocal G4Field* G4FieldBuilder::fGlobalField = nullptr;
41G4ThreadLocal G4bool G4FieldBuilder::fIsConstructed = false;
42
43//_____________________________________________________________________________
45{
47 fgIsInstance = true;
48 return &instance;
49}
50
51//_____________________________________________________________________________
53{
54 // Default constructor
55
56 fMessenger = new G4FieldBuilderMessenger(this);
57
58 // Field parameters for global field
59 fFieldParameters.push_back(new G4FieldParameters());
60}
61
62//_____________________________________________________________________________
64{
65 // Destructor
66
67 delete fMessenger;
68
69 for (auto parameters : fFieldParameters)
70 {
71 delete parameters;
72 }
73
74 for (auto setup : GetFieldSetups())
75 {
76 delete setup;
77 }
78
79 fgIsInstance = false;
80
81 // magnetic field objects are deleted via G4 kernel
82}
83
84//_____________________________________________________________________________
86{
87 // Return the information if an instance exists
88
89 return fgIsInstance;
90}
91
92//
93// private methods
94//
95
96//_____________________________________________________________________________
98{
99 // Set verbose level
100
101 fVerboseLevel = value;
102}
103
104//_____________________________________________________________________________
105G4FieldParameters* G4FieldBuilder::GetOrCreateFieldParameters(
106 const G4String& volumeName)
107{
108 // Get field parameters with the given volumeName or create them if they
109 // do not exist yet
110
111 // Get user field parameters
112 for (auto fieldParameters : fFieldParameters)
113 {
114 if (fieldParameters->GetVolumeName() == volumeName)
115 {
116 return fieldParameters;
117 }
118 }
119
120 // Create field parameters if not yet defined
121 auto fieldParameters = new G4FieldParameters(volumeName);
122 fFieldParameters.push_back(fieldParameters);
123 return fieldParameters;
124}
125
126//_____________________________________________________________________________
127G4FieldSetup* G4FieldBuilder::GetFieldSetup(G4LogicalVolume* lv)
128{
129 // Get field setup with the given logical volume
130
131 // Get user field parameters
132 for (auto fieldSetup : GetFieldSetups())
133 {
134 if (fieldSetup->GetLogicalVolume() == lv)
135 {
136 return fieldSetup;
137 }
138 }
139
140 return nullptr;
141}
142
143//_____________________________________________________________________________
144void G4FieldBuilder::CreateFieldSetup(G4Field* field,
145 G4FieldParameters* fieldParameters, G4LogicalVolume* lv)
146{
147 // Create magnetic, electromagnetic or gravity field setup
148
149 auto fieldSetup = new G4FieldSetup(*fieldParameters, field, lv);
150 fieldSetup->PrintInfo(fVerboseLevel);
151
152 if (fFieldSetups.Get() == nullptr)
153 {
154 auto fieldSetups = new std::vector<G4FieldSetup*>();
155 fFieldSetups.Put(fieldSetups);
156 }
157
158 GetFieldSetups().push_back(fieldSetup);
159}
160
161//_____________________________________________________________________________
162void G4FieldBuilder::ConstructGlobalField()
163{
164 // Construct Geant4 global magnetic field setup
165
166 if (fVerboseLevel > 1)
167 {
168 G4cout << "G4FieldBuilder::ConstructGlobalField " << G4endl;
169 }
170
171 CreateFieldSetup(fGlobalField, fFieldParameters[0], nullptr);
172}
173
174//_____________________________________________________________________________
175void G4FieldBuilder::ConstructLocalFields()
176{
177 // Construct Geant4 local magnetic field setups from the local fields map
178
179 if (fLocalFields.Get() == nullptr) { return; }
180
181 if (fVerboseLevel > 1)
182 {
183 G4cout << "G4FieldBuilder::ConstructLocalFields()" << G4endl;
184 }
185
186 // Loop over local field map
187 for (auto [lv, field] : GetLocalFields())
188 {
189 // Volume name
190 const auto& volumeName = lv->GetName();
191
192 // Get or create user field parameters
193 G4FieldParameters* fieldParameters =
194 GetOrCreateFieldParameters(volumeName);
195
196 if (fVerboseLevel > 1)
197 {
198 G4cout << "Construct local field in volume: " << volumeName << G4endl;
199 }
200
201 // Create magnetic field
202 CreateFieldSetup(field, fieldParameters, lv);
203 }
204}
205
206//_____________________________________________________________________________
207void G4FieldBuilder::UpdateFieldSetups()
208{
209 // Update all field setups
210
211 if (fVerboseLevel > 1)
212 {
213 G4cout << "G4FieldBuilder::UpdateFieldSetups " << G4endl;
214 }
215
216 for (auto fieldSetup : GetFieldSetups())
217 {
218 fieldSetup->Update();
219
220 if (fVerboseLevel > 1)
221 {
222 fieldSetup->PrintInfo(fVerboseLevel, "updated");
223 }
224 }
225}
226
227//
228// public methods
229//
230
231//_____________________________________________________________________________
233 const G4String& fieldVolName)
234{
235 // Create local magnetic field parameters (configuration) which can be then
236 // configured by the user via UI commands.
237 // The parameters are used in geometry only if a local magnetic field is
238 // associated with the volumes with the given name.
239
240 auto fieldParameters = new G4FieldParameters(fieldVolName);
241 fFieldParameters.push_back(fieldParameters);
242
243 return fieldParameters;
244}
245
246//_____________________________________________________________________________
248{
249 // Construct setups for all registered fields.
250
251 if (fVerboseLevel > 1)
252 {
253 G4cout << "G4FieldBuilder::ConstructField" << G4endl;
254 }
255
256 if (fIsConstructed)
257 {
259 "G4FieldBuilder::ConstructField:", "GeomFieldParameters0001",
260 JustWarning, "Field was already constructed.");
261 return;
262 }
263
264 ConstructGlobalField();
265 ConstructLocalFields();
266
267 UpdateFieldSetups();
268
269 fIsConstructed = true;
270}
271
272//_____________________________________________________________________________
274{
275 // Update magnetic field.
276 // This function must be called if the field parameters were changed
277 // in other than PreInit> phase.
278
279 if (fFieldSetups.Get() == nullptr)
280 {
282 "G4FieldBuilder::UpdateField", "GeomFieldParameters0001",
283 JustWarning, "No field setup is defined.");
284 return;
285 }
286
287 if (fVerboseLevel > 1)
288 {
289 G4cout << "G4FieldBuilder::UpdateField" << G4endl;
290 }
291
292 // Update the objects defined in G4FieldSetup's
293 UpdateFieldSetups();
294}
295
296//_____________________________________________________________________________
298{
299 // Reinitialize if geometry has been modified.
300 // This function is called by G4RunManager during ReinitializeGeometry()
301
302 if (fVerboseLevel > 1)
303 {
304 G4cout << "G4FieldBuilder::Reinitialize" << G4endl;
305 }
306
307 // Delete global field
308 delete fGlobalField;
309 fGlobalField = nullptr;
310
311 // Delete local fields if defined
312 if (fLocalFields.Get() != nullptr)
313 {
314 for (auto vectorElement : GetLocalFields())
315 {
316 delete vectorElement.second;
317 }
318 // Clear local fields map
319 GetLocalFields().clear();
320 }
321
322 // Clear field setups if defined
323 if (fFieldSetups.Get() != nullptr)
324 {
325 for (auto fieldSetup : GetFieldSetups())
326 {
327 fieldSetup->SetG4Field(nullptr);
328 fieldSetup->Clear();
329 }
330 }
331
332 fIsConstructed = false;
333
334 if (fVerboseLevel > 1)
335 {
336 G4cout << "End of G4FieldBuilder::Reinitialize" << G4endl;
337 }
338}
339
340//_____________________________________________________________________________
342{
343// Default field type is set to kMagnetic;
344// this function should be called for other than magnetic field
345// in order to update the default equation and stepper types.
346
347 if (fIsConstructed)
348 {
350 "G4FieldBuilder::SetFieldType:", "GeomFieldParameters0001",
351 JustWarning, "Field was already constructed.");
352 return;
353 }
354
355 fFieldParameters[0]->SetFieldType(fieldType);
356
357 // change default equation and stepper if other than magnetic field
358 if (fieldType == kElectroMagnetic)
359 {
360 fFieldParameters[0]->SetEquationType(kEqElectroMagnetic);
361 fFieldParameters[0]->SetStepperType(kClassicalRK4);
362 }
363}
364
365//_____________________________________________________________________________
367{
368 // Set or reset the global field.
369 // Update field objects, if the field was already constructed.
370 // If warn, issue a warning if the previous field is deleted.
371
372 if (fGlobalField != nullptr && warn)
373 {
375 "G4FieldBuilder::SetGlobalField:", "GeomFieldParameters0001",
376 JustWarning, "The global field already exists, it will be deleted.");
377 }
378 delete fGlobalField;
379 fGlobalField = field;
380
381 if (fIsConstructed)
382 {
383 // update the global field objects if already constructed
384 GetFieldSetups()[0]->SetG4Field(field);
385 GetFieldSetups()[0]->Update();
386 }
387}
388
389//_____________________________________________________________________________
391 G4Field* field, G4LogicalVolume* lv, G4bool warn)
392{
393 // Register the local field in the map.
394 // Update field objects, if the field was already constructed.
395 // If warn, issue a warning if the previous field is deleted.
396
397 if (lv == nullptr)
398 {
399 G4cerr << "Cannot register local field without Logical volume." << G4endl;
400 return;
401 }
402
403 if (fLocalFields.Get() == nullptr)
404 {
405 auto localFields = new std::vector<std::pair<G4LogicalVolume*, G4Field*>>();
406 fLocalFields.Put(localFields);
407 }
408
409 auto it = GetLocalFields().begin();
410 for (it = GetLocalFields().begin(); it != GetLocalFields().end(); ++it)
411 {
412 if (it->first == lv) { break; }
413 }
414
415 if (it != GetLocalFields().end())
416 {
417 // replaced field if already in the map
418 if (warn)
419 {
421 descr << "Logical volume " << lv->GetName() << " has already field."
422 " It will be deleted.";
424 "G4FieldBuilder::SetLocalField:", "GeomFieldParameters0001",
425 JustWarning, descr);
426 }
427 delete it->second;
428 it->second = field;
429 }
430 else
431 {
432 // register field in the map
433 GetLocalFields().emplace_back(lv,field);
434 }
435
436 if (fIsConstructed) {
437 // update this local field objects if already constructed
438 auto fieldSetup = GetFieldSetup(lv);
439 if (fieldSetup == nullptr)
440 {
442 "G4FieldBuilder::SetLocalField:", "GeomFieldParameters0001",
443 JustWarning, "Cannot get field setup for a local field.");
444 return;
445 }
446 fieldSetup->SetG4Field(field);
447 fieldSetup->Update();
448 }
449}
450
451//_____________________________________________________________________________
453 G4EquationOfMotion* equation, const G4String& volumeName)
454{
455 // Set user equation of motion
456
457 if (volumeName.empty())
458 {
459 // global field
460 fFieldParameters[0]->SetUserEquationOfMotion(equation);
461 }
462 else
463 {
464 // local field
465 // Get or create user field parameters
466 G4FieldParameters* fieldParameters =
467 GetOrCreateFieldParameters(volumeName);
468 fieldParameters->SetUserEquationOfMotion(equation);
469 }
470}
471
472//_____________________________________________________________________________
474 G4MagIntegratorStepper* stepper, const G4String& volumeName)
475{
476 // Set user stepper
477
478 if (volumeName.empty())
479 {
480 // global field
481 fFieldParameters[0]->SetUserStepper(stepper);
482 }
483 else
484 {
485 // local field
486 // Get or create user field parameters
487 G4FieldParameters* fieldParameters =
488 GetOrCreateFieldParameters(volumeName);
489 fieldParameters->SetUserStepper(stepper);
490 }
491}
492
493//_____________________________________________________________________________
495 const G4String& volumeName) const
496{
497 // Get field parameters with the given volumeName.
498 // Return global field parameters, if volume name is empty.
499
500 // Get user field parameters
501 for (auto fieldParameters : fFieldParameters)
502 {
503 if (fieldParameters->GetVolumeName() == volumeName)
504 {
505 return fieldParameters;
506 }
507 }
508
510 "G4FieldBuilder::GetFieldParameters:", "GeomFieldParameters0001",
511 JustWarning, "Field parameters not found.");
512 return nullptr;
513}
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
@ kEqElectroMagnetic
G4FieldType
G4FieldType defines the available fields in Geant4.
@ kElectroMagnetic
electromagnetic field
@ kClassicalRK4
G4ClassicalRK4.
G4TemplateRNGHelper< G4long > * G4TemplateRNGHelper< G4long >::instance
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
G4EquationOfMotion is the abstract base class for the right hand size of the equation of motion of a ...
G4FieldBuilderMessenger is messenger class that defines commands for G4FieldBuilder.
G4FieldParameters * CreateFieldParameters(const G4String &fieldVolName)
void SetUserEquationOfMotion(G4EquationOfMotion *equation, const G4String &volumeName="")
void SetUserStepper(G4MagIntegratorStepper *stepper, const G4String &volumeName="")
G4FieldParameters * GetFieldParameters(const G4String &volumeName="") const
void SetLocalField(G4Field *field, G4LogicalVolume *lv, G4bool warn=false)
static G4bool IsInstance()
static G4FieldBuilder * Instance()
G4FieldBuilder(const G4FieldBuilder &right)=delete
void SetFieldType(G4FieldType fieldType)
void SetVerboseLevel(G4int value)
void SetGlobalField(G4Field *field, G4bool warn=false)
G4FieldParameters defines the type of equation of motion of a particle in a field and the integration...
void SetUserStepper(G4MagIntegratorStepper *stepper)
void SetUserEquationOfMotion(G4EquationOfMotion *equation)
const G4String & GetVolumeName() const
G4FieldSetup is a class for constructing magnetic, electromagnetic and gravity fields which strength ...
G4Field is the abstract class for any kind of field. It allows any kind of field (vector,...
Definition G4Field.hh:67
G4LogicalVolume represents a leaf node or unpositioned subtree in the geometry hierarchy....
const G4String & GetName() const
G4MagIntegratorStepper is an abstract base class for integrator of particle's equation of motion,...
#define G4ThreadLocal
Definition tls.hh:77