BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSAcceleratorComponentRegistry.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2024.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSAcceleratorComponentRegistry.hh"
20#include "BDSDebug.hh"
21#include "BDSLine.hh"
22#include "BDSUtilities.hh"
23
24#include <ostream>
25#include <iomanip>
26#include <ios>
27#include <map>
28
29G4double ACRegistryKey::tolerance = 1e-7; // floating point precision even though we use doubles
30
32
39
40ACRegistryKey::ACRegistryKey():
41 componentName(""),
42 rigidity(0)
43{;}
44
45ACRegistryKey::ACRegistryKey(const std::string& componentNameIn,
46 G4double rigidityIn):
47 componentName(componentNameIn),
48 rigidity(rigidityIn)
49{;}
50
51bool ACRegistryKey::operator==(const ACRegistryKey& other) const
52{
53 G4bool v1 = other.componentName == componentName;
54 G4bool v2 = std::abs(other.rigidity - rigidity) < tolerance;
55 return v1 && v2;
56}
57
58std::ostream& operator<<(std::ostream& out, ACRegistryKey const& k)
59{
60 out << "\"" << k.componentName << "\" at Brho = " << k.rigidity;
61 return out;
62}
63
64
67
69{
70#ifdef BDSDEBUG
71 G4cout << __METHOD_NAME__ << "size of registry " << registry.size() << G4endl;
72#endif
73 for (auto& i : registry)
74 {delete i.second;}
75 for (auto ac : allocatedComponents)
76 {delete ac;}
77 for (auto ac : curvilinearComponents)
78 {delete ac;}
79 for (auto ac : tunnelComponents)
80 {delete ac;}
81
82 instance = nullptr;
83}
84
86 G4double rigidtyAtConstructionTime,
87 bool isModified)
88{
89 // If the component was modified beyond its original element definition in the parser,
90 // ie a drift was modified to match a pole face of a bend, then store if for memory
91 // management, but not in the registry
92 if (isModified)
93 {
94 if (IsRegisteredAllocated(component))
95 {return;}
96
97 allocatedComponents.insert(component);
98 // add to registry for unique components only
99 registryForAllocated[{component->GetName(),rigidtyAtConstructionTime}] = component;
100 nameCounter[component->GetName()] += 1;
101 if (BDSLine* line = dynamic_cast<BDSLine*>(component))
102 {// if line then also add constituents
103 for (const auto element : *line)
104 {RegisterComponent(element, rigidtyAtConstructionTime, true);}
105 }
106 return;
107 }
108
109 if (IsRegistered(component,rigidtyAtConstructionTime))
110 {return;} // don't register something that's already registered
111
112 // in both cases we register the BDSLine* object as it doesn't own its constituents
113 registry[{component->GetName(),rigidtyAtConstructionTime}] = component;
114 nameCounter[component->GetName()] += 1;
115 // increment counter for each component type
116 ++typeCounter[component->GetType()];
117 if (BDSLine* line = dynamic_cast<BDSLine*>(component))
118 {
119 for (const auto element : *line)
120 {RegisterComponent(element, rigidtyAtConstructionTime, false);}
121 }
122#ifdef BDSDEBUG
123 G4cout << __METHOD_NAME__ << "size of registry " << registry.size() << G4endl;
124#endif
125}
126
128 G4double rigidtyAtConstructionTime)
129{
130 return IsRegistered(component->GetName(), rigidtyAtConstructionTime);
131}
132
134{
135 return std::find(allocatedComponents.begin(), allocatedComponents.end(), component) != allocatedComponents.end();
136}
137
139 G4double rigidtyAtConstructionTime)
140{
141 auto search = registry.find({name,rigidtyAtConstructionTime});
142 return !(search == registry.end());
143}
144
146 G4double rigidtyAtConstructionTime)
147{
148 try
149 {return registry.at({name,rigidtyAtConstructionTime});}
150 catch (const std::out_of_range& /*oor*/)
151 {
152 G4cerr << __METHOD_NAME__ << "unknown component named: \"" << name << "\"" << G4endl;
153 return nullptr;
154 }
155}
156
161
163{
164 tunnelComponents.insert(component);
165}
166
167std::unordered_map<ACRegistryKey, BDSAcceleratorComponent*> BDSAcceleratorComponentRegistry::AllComponentsIncludingUnique() const
168{
169 std::unordered_map<ACRegistryKey, BDSAcceleratorComponent*> result;
170 result.insert(registry.begin(), registry.end());
171 result.insert(registryForAllocated.begin(), registryForAllocated.end());
172 return result;
173}
174
175G4int BDSAcceleratorComponentRegistry::AlreadyRegisteredNameCount(const G4String& name) const
176{
177 G4int count = BDS::MapGetWithDefault(nameCounter, (std::string)name, 0);
178 return count;
179}
180
181std::ostream& operator<< (std::ostream &out, BDSAcceleratorComponentRegistry const &r)
182{
183 // save flags since std::left changes the stream
184 std::ios_base::fmtflags ff = out.flags();
185 out << "Accelerator Component Registry:" << G4endl;
186 for (const auto& it : r.registry)
187 {out << std::left << std::setw(15) << it.second->GetType() << it.first << G4endl;}
188 out.flags(ff); // reset flags
189 return out;
190}
191
193{
194 G4cout << __METHOD_NAME__ << G4endl;
195 for (const auto& kv : typeCounter)
196 {G4cout << std::setw(20) << kv.first << " : " << kv.second << G4endl;}
197}
custom key class for pair of <name,rigidity>.
std::string componentName
Has to be std::string for hashing as G4String doesn't provide one.
A registry of constructed BDSAcceleratorComponent instances that can be searched.
void RegisterCurvilinearComponent(BDSAcceleratorComponent *component)
static BDSAcceleratorComponentRegistry * Instance()
Singleton accessor.
void RegisterTunnelComponent(BDSAcceleratorComponent *component)
std::set< BDSAcceleratorComponent * > allocatedComponents
Set of created components not in registry, for memory management.
std::set< BDSAcceleratorComponent * > curvilinearComponents
Set of curvilinear components - purely for memory management.
static BDSAcceleratorComponentRegistry * instance
The singleton instance.
G4bool IsRegisteredAllocated(const BDSAcceleratorComponent *componentName) const
Check if a unique component is registered in the allocatedComponents.
std::unordered_map< ACRegistryKey, BDSAcceleratorComponent * > AllComponentsIncludingUnique() const
void PrintNumberOfEachType() const
Print out the number of each type of component registered.
std::unordered_map< std::string, int > typeCounter
BDSAcceleratorComponent * GetComponent(const G4String &name, G4double rigidtyAtConstructionTime)
void RegisterComponent(BDSAcceleratorComponent *component, G4double rigidtyAtConstructionTime, bool isModified=false)
G4bool IsRegistered(BDSAcceleratorComponent *component, G4double rigidtyAtConstructionTime)
Check whether an accelerator component is already registered.
BDSAcceleratorComponentRegistry()
Default constructor is private as singleton.
std::unordered_map< std::string, int > nameCounter
RegistryMap registry
Registry is a map - note 'register' is a protected keyword.
RegistryMap registryForAllocated
A map for absolutely everything including components that are unique.
Abstract class that represents a component of an accelerator.
virtual G4String GetName() const
The name of the component without modification.
G4String GetType() const
Get a string describing the type of the component.
A class that hold multiple accelerator components.
Definition BDSLine.hh:38
V MapGetWithDefault(const std::map< K, V > &m, const K &key, const V &defaultValue)