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) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSAcceleratorComponentRegistry.hh"
19#include "BDSDebug.hh"
20#include "BDSLine.hh"
21#include "BDSUtilities.hh"
22
23#include <ostream>
24#include <iomanip>
25#include <ios>
26#include <map>
27
28G4double ACRegistryKey::tolerance = 1e-7; // floating point precision even though we use doubles
29
31
38
39ACRegistryKey::ACRegistryKey():
40 componentName(""),
41 rigidity(0)
42{;}
43
44ACRegistryKey::ACRegistryKey(const std::string& componentNameIn,
45 G4double rigidityIn):
46 componentName(componentNameIn),
47 rigidity(rigidityIn)
48{;}
49
50bool ACRegistryKey::operator==(const ACRegistryKey& other) const
51{
52 G4bool v1 = other.componentName == componentName;
53 G4bool v2 = std::abs(other.rigidity - rigidity) < tolerance;
54 return v1 && v2;
55}
56
57std::ostream& operator<<(std::ostream& out, ACRegistryKey const& k)
58{
59 out << "\"" << k.componentName << "\" at Brho = " << k.rigidity;
60 return out;
61}
62
63
66
68{
69#ifdef BDSDEBUG
70 G4cout << __METHOD_NAME__ << "size of registry " << registry.size() << G4endl;
71#endif
72 for (auto& i : registry)
73 {delete i.second;}
74 for (auto ac : allocatedComponents)
75 {delete ac;}
76 for (auto ac : curvilinearComponents)
77 {delete ac;}
78 for (auto ac : tunnelComponents)
79 {delete ac;}
80
81 instance = nullptr;
82}
83
85 G4double rigidtyAtConstructionTime,
86 bool isModified)
87{
88 // If the component was modified beyond its original element definition in the parser,
89 // ie a drift was modified to match a pole face of a bend, then store if for memory
90 // management, but not in the registry
91 if (isModified)
92 {
93 if (IsRegisteredAllocated(component))
94 {return;}
95
96 allocatedComponents.insert(component);
97 // add to registry for unique components only
98 registryForAllocated[{component->GetName(),rigidtyAtConstructionTime}] = component;
99 nameCounter[component->GetName()] += 1;
100 if (BDSLine* line = dynamic_cast<BDSLine*>(component))
101 {// if line then also add constituents
102 for (const auto element : *line)
103 {RegisterComponent(element, rigidtyAtConstructionTime, true);}
104 }
105 return;
106 }
107
108 if (IsRegistered(component,rigidtyAtConstructionTime))
109 {return;} // don't register something that's already registered
110
111 // in both cases we register the BDSLine* object as it doesn't own its constituents
112 registry[{component->GetName(),rigidtyAtConstructionTime}] = component;
113 nameCounter[component->GetName()] += 1;
114 // increment counter for each component type
115 ++typeCounter[component->GetType()];
116 if (BDSLine* line = dynamic_cast<BDSLine*>(component))
117 {
118 for (const auto element : *line)
119 {RegisterComponent(element, rigidtyAtConstructionTime, false);}
120 }
121#ifdef BDSDEBUG
122 G4cout << __METHOD_NAME__ << "size of registry " << registry.size() << G4endl;
123#endif
124}
125
127 G4double rigidtyAtConstructionTime)
128{
129 return IsRegistered(component->GetName(), rigidtyAtConstructionTime);
130}
131
133{
134 return std::find(allocatedComponents.begin(), allocatedComponents.end(), component) != allocatedComponents.end();
135}
136
138 G4double rigidtyAtConstructionTime)
139{
140 auto search = registry.find({name,rigidtyAtConstructionTime});
141 return !(search == registry.end());
142}
143
145 G4double rigidtyAtConstructionTime)
146{
147 try
148 {return registry.at({name,rigidtyAtConstructionTime});}
149 catch (const std::out_of_range& /*oor*/)
150 {
151 G4cerr << __METHOD_NAME__ << "unknown component named: \"" << name << "\"" << G4endl;
152 return nullptr;
153 }
154}
155
160
162{
163 tunnelComponents.insert(component);
164}
165
166std::unordered_map<ACRegistryKey, BDSAcceleratorComponent*> BDSAcceleratorComponentRegistry::AllComponentsIncludingUnique() const
167{
168 std::unordered_map<ACRegistryKey, BDSAcceleratorComponent*> result;
169 result.insert(registry.begin(), registry.end());
170 result.insert(registryForAllocated.begin(), registryForAllocated.end());
171 return result;
172}
173
174G4int BDSAcceleratorComponentRegistry::AlreadyRegisteredNameCount(const G4String& name) const
175{
176 G4int count = BDS::MapGetWithDefault(nameCounter, (std::string)name, 0);
177 return count;
178}
179
180std::ostream& operator<< (std::ostream &out, BDSAcceleratorComponentRegistry const &r)
181{
182 // save flags since std::left changes the stream
183 std::ios_base::fmtflags ff = out.flags();
184 out << "Accelerator Component Registry:" << G4endl;
185 for (const auto& it : r.registry)
186 {out << std::left << std::setw(15) << it.second->GetType() << it.first << G4endl;}
187 out.flags(ff); // reset flags
188 return out;
189}
190
192{
193 G4cout << __METHOD_NAME__ << G4endl;
194 for (const auto& kv : typeCounter)
195 {G4cout << std::setw(20) << kv.first << " : " << kv.second << G4endl;}
196}
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:37
V MapGetWithDefault(const std::map< K, V > &m, const K &key, const V &defaultValue)