DLG4::VolumeBuilders
A fluent interface for Geant4 geometry definition.
Loading...
Searching...
No Matches
RZBuilder.cc
Go to the documentation of this file.
1/*
2 * VolumeMaker.cc
3 *
4 * Created on: Jun 29, 2024
5 * Author: D. S. Leonard
6 */
7// Presently includes src for VolumeMaker and GeantMultiPlane classes
8// See header for documentation.
9
10#include "RZBuilder.hh"
11#include <string>
13#include <G4Polycone.hh>
14#include <G4Polyhedra.hh>
15//#include "disableable_shared_from_this.hh"
16#include "i_shared_ptr.hh"
17#include "StructureBuilder.hh"
18#include "StructureBuilder.hpp"
19
20class G4String;
21using namespace DLG4::Utilities;
22
23//GeantMultiPlane methods //////////////////////////////////////////////////
25
26namespace DLG4::VolumeBuilders {
27 //Factories
28 RZBuilderPtr CreatePolyconeBuilder(const G4String &name, G4double phi_start, G4double phi_tot) {
29 // We could actually construct these as RZBuilderPtr without using new, vis i_shared_ptr constructor.
30 // But maybe we can unfriend i_shared_ptr in the future if we use new here, and avoid exposing
31 // a backdoor to the general ctor, which doesn't select a MakeSolidFunctionPtr.
32 // ReSharper disable once CppDFAMemoryLeak
33 auto object = RZBuilderPtr(new RZBuilder(name, phi_start, phi_tot, 0));
34 object->MakeSolidFunctionPtr_ = &RZBuilder::MakePolycone;
35 return RZBuilderPtr(object);
36 }
37
38 RZBuilderPtr CreatePolyhedraBuilder(const G4String &name, int sides, G4double phi_start,
39 G4double phi_tot) {
40 // ReSharper disable once CppDFAMemoryLeak
41 auto object = new RZBuilder(name, phi_start, phi_tot, sides);
42 object->MakeSolidFunctionPtr_ = &RZBuilder::MakePolyhedra;
43 return RZBuilderPtr(object);
44 }
45
47 G4double unit, const G4String &name, G4double endz, G4double h, G4double OR, G4double IR) {
48 // ReSharper disable once CppDFAMemoryLeak
49 auto object = RZBuilderPtr(new RZBuilder(name));
50 object->MakeSolidFunctionPtr_ = &RZBuilder::MakePolycone;
51 RZPlane plane;
52 plane.unit = unit;
53 plane.z = endz;
54 plane.IR = IR;
55 plane.OR = OR;
56 object->AddPlane(plane);
57 plane.z += h;
58 object->AddPlane(plane);
59 return RZBuilderPtr(object);
60 }
61
62 RZBuilderPtr CreateCylinderBuilder(const G4String &name, G4double endz, G4double h, G4double OR,
63 G4double IR) {
65 }
66}
67
69 RZBuilder::RZBuilder(const G4String &name, G4double init_phi_start, G4double init_phi_tot,
70 int init_sides) :
71 VolumeBuilder<RZBuilder>(), sides_(init_sides), phi_start_deg_(init_phi_start),
72 phi_tot_deg(init_phi_tot) {
73 set_shared_from_this_enabled(false);
74 SetName(name);
75 set_shared_from_this_enabled(true);
76 }
77
78 //Private default copy ctor.
79 //This is used by clone methods of concrete classes
80 RZBuilder::RZBuilder(const RZBuilder &other) :
81 VolumeBuilder<RZBuilder>(other), // Call base class copy constructor
82 sides_(other.sides_), phi_start_deg_(other.phi_start_deg_), phi_tot_deg(other.phi_tot_deg),
83 num_planes_(other.num_planes_), z_(other.z_), IR_(other.IR_), OR_(other.OR_),
84 MakeSolidFunctionPtr_(other.MakeSolidFunctionPtr_) {
85 set_shared_from_this_enabled(false);
86 SetName(other.GetBuilderName());
87 set_shared_from_this_enabled(true);
88 }
89
90
92 if (solid_ptr_) {
93 throw std::runtime_error("Error in RZBuilder::FillSolidConfig\"\n"
94 "Cannot fill a solid builder CONFIGURATION, when the solid is already built from it."
95 "Use ForkAndReset(\"new_name\") first to get an unbuilt copy.\n\n");
96 }
97
98 // set all ID's to 0.
99 for (int i = 0; i < num_planes_; i++) {
100 this->IR_[i] = 0;
101 }
102 return this->shared_from_this();
103 }
104
105
107 if (solid_ptr_) {
108 throw std::runtime_error("Error in RZBuilder::ReflectZSolidConfig\"\n"
109 "Cannot flip a solid builder CONFIGURATION, when the solid is already built from it.\n"
110 "Use ReflectZFinalSolidCopy(\"new_name\") instead to copy and flip the solid.\n\n");
111 }
112 // Mirror z values
113 for (int i = 0; i < num_planes_; i++) {
114 this->z_[i] = -this->z_[i];
115 }
116 return this->shared_from_this();
117 }
118
120 if (MakeSolidFunctionPtr_ == &RZBuilder::MakePolyhedra) {
121 sides_ = n;
122 } else {
123 G4cout <<
124 "Warning in RZBuilder: Calling SetNumSides() on a builder that makes round things"
125 << " might be as clever as giving a balloon to a hedgehog. \n Ignoring call." <<
126 G4endl;
127 }
128 return shared_from_this();
129 }
130
131 // Overloads are handled a lot more implicitly in VolumeBuilder, but it would all have to be redone
132 // here since the vector parameter names need to be different.
133 // overload to take direct values
135 if (plane.IR < 0 || plane.OR < 0) {
136 throw std::runtime_error("Error in RZBuilder::AddPlane()"
137 " for builder " + GetBuilderName() + ".\n"
138 "IR and OR must be non-negative.");
139 }
140 IR_.push_back(plane.IR * plane.unit);
141 OR_.push_back(plane.OR * plane.unit);
142 z_.push_back(plane.z * plane.unit);
143 num_planes_++;
144 return shared_from_this();
145 }
146
147 RZBuilderPtr RZBuilder::AddPlane(G4double unit, G4double IR, G4double OR, G4double z) {
148 auto plane = RZPlane{unit, IR, OR, z};
149 return AddPlane(plane);
150 }
151
152 // overload to take direct values with default unit
153 RZBuilderPtr RZBuilder::AddPlane(G4double IR, G4double OR, G4double z) {
154 auto plane = RZPlane{GetEffectiveDefaultUnit(), IR, OR, z};
155 return AddPlane(plane);
156 }
157
158 //Overloads for adding multiple planes at once:
159 // 1. Vector of full RZPlane objects (each with their own units)
160 RZBuilderPtr RZBuilder::AddPlanes(const std::vector<RZPlane> &planes) {
161 for (const auto &plane : planes) {
162 AddPlane(plane);
163 }
164 return shared_from_this();
165 }
166
167 // 2. Unitless planes using builder's preset default unit
168 RZBuilderPtr RZBuilder::AddPlanes(const std::vector<RZPlaneUnitless> &planes) {
169 for (const auto &plane : planes) {
170 G4double unit = this->GetEffectiveDefaultUnit();
171 auto rzplane = RZPlane{unit, plane.IR, plane.OR, plane.z};
172 AddPlane(rzplane);
173 }
174 return shared_from_this();
175 }
176
177 // 3. Most compact - one unit for all planes
178 RZBuilderPtr RZBuilder::AddPlanes(G4double unit, const std::vector<RZPlaneUnitless> &planes) {
179 for (const auto &plane : planes) {
180 auto rzplane = RZPlane{unit, plane.IR, plane.OR, plane.z};
181 AddPlane(rzplane);
182 }
183 return shared_from_this();
184 }
185
186
187 G4VSolid *RZBuilder::MakePolycone(const G4String &name) {
188 if (this->solid_ptr_.get() != nullptr) {
189 std::string error = "Error in MakePolycone: A solid was already built\n"
190 "You can copy and rename the builder to reset it and build again.";
191 throw std::runtime_error(error);
192 }
193 G4cout << G4endl;
194 G4cout << "New Polycone:" << GetBuilderName() << " phi_start: " << phi_start_deg_ <<
195 " degrees, phi_tot: " << phi_tot_deg
196 << " degrees" << G4endl;
197 for (int i = 0; i < z_.size(); i++) {
198 G4cout << "z: " << z_[i] << " IR: " << IR_[i] << " OR: " << OR_[i] << G4endl;
199 }
200 auto retval = new G4Polycone(
201 name, phi_start_deg_ * CLHEP::deg, phi_tot_deg * CLHEP::deg, num_planes_, z_.data(),
202 IR_.data(),
203 OR_.data());
204 return retval;
205 }
206
207 G4VSolid *RZBuilder::MakePolyhedra(const G4String &name) {
208 if (this->solid_ptr_.get() != nullptr) {
209 std::string error = "Error in MakePolyhedra: A solid was already built\n"
210 "You can copy and rename the builder to reset it and build again.";
211 throw std::runtime_error(error);
212 }
213 G4cout << G4endl;
214 G4cout << "New Polyhedra:" << GetBuilderName() << " with " << sides_ << " sides, "
215 << " phi_start: " << phi_start_deg_ << " degrees, phi_tot: " << phi_tot_deg <<
216 " degrees" << G4endl;
217 for (int i = 0; i < z_.size(); i++) {
218 G4cout << "z: " << z_[i] << " IR: " << IR_[i] << " OR: " << OR_[i] << G4endl;
219 }
220 auto retval = new G4Polyhedra(
221 name, phi_start_deg_ * CLHEP::deg, phi_tot_deg * CLHEP::deg, sides_, num_planes_,
222 z_.data(),
223 IR_.data(), OR_.data());
224 return retval;
225 }
226
227
228 // Could use a displaced box macro too...
229 // Can use something like G4VSolid *displacedBox = new G4DisplacedSolid("displacedBox",aBox,rotvet,G4ThreeVector(x,y,z));
230 // But I had issues making that work in the past.
231 // Probably should just have a separate class, no need for z planes.
232
233 // Development notes:
234 // Presently, no deletion is done. It's assumed this is used in a typical sloppy environment where the geometry generator has no
235 // instance lifetime so cannot manage lifetime of its generated things.
236 // However, we could add an optional "take_ownership" flag that signals the builder should delete all its owned Geant things.
237 // We'd need a move constructor for the return by value in the methods, or the internal copy would delete the resources.
238 // This avoids the user messing with unique_ptrs and doesn't require a change in user code.
239 // We'd need to track all volumes used in unions, and decide if we own materials or not (probably not).
240 // Could copy them, but then I think they need new names in geant.
241 // Anyway, this can all be done without breaking anything.
242}
Builder class for RZ mult-plane defined solids.
Definition RZBuilder.hh:131
VolumeBuilder: Common functionality for volume builder classes.
RZBuilderPtr CreatePolyhedraBuilder(const G4String &name, int sides, G4double phi_start=0., G4double phi_tot=360)
Create a builder for associated IR,OR,Z defined object.
Definition RZBuilder.cc:38
RZBuilderPtr CreateCylinderBuilder(G4double unit, const G4String &name, G4double endz, G4double height, G4double OR, G4double IR=0)
Create a simple cylinder builder.
Definition RZBuilder.cc:46
RZBuilderPtr CreatePolyconeBuilder(const G4String &name, G4double phi_start=0., G4double phi_tot=360)
Create a builder for associated IR,OR,Z defined object.
Definition RZBuilder.cc:28
RZBuilderPtr ReflectZSolidConfig()
Flip Solid Configuration.
Definition RZBuilder.cc:106
virtual RZBuilderPtr SetNumSides(G4double N)
Set number of sides.
Definition RZBuilder.cc:119
RZBuilderPtr AddPlane(const RZPlane &plane)
Adds a plane defining one IR,OR,Z triplet in the volume design.
Definition RZBuilder.cc:134
RZBuilderPtr AddPlanes(const std::vector< RZPlane > &planes)
Adds multiple RZ planes each defining one unit,IR,OR,Z set in the volume design.
Definition RZBuilder.cc:160
RZBuilderPtr FillSolidConfig()
Modifies a Solid CONFIGURATION to set all inner diameters (IDs) to 0.
Definition RZBuilder.cc:91
Struct for adding planes to GeantMultiPlane –DSLeonard 2024 Overloads make this not strictly needed.
Definition RZBuilder.hh:44