remage
Simulation framework for HPGe-based experiments
 
Loading...
Searching...
No Matches
RMGVertexConfinement.hh
1// Copyright (C) 2022 Luigi Pertoldi <https://orcid.org/0000-0002-0467-2571>
2//
3// This program is free software: you can redistribute it and/or modify it under
4// the terms of the GNU Lesser General Public License as published by the Free
5// Software Foundation, either version 3 of the License, or (at your option) any
6// later version.
7//
8// This program is distributed in the hope that it will be useful, but WITHOUT
9// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11// details.
12//
13// You should have received a copy of the GNU Lesser General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15
16#ifndef _RMG_VERTEX_CONFINEMENT_HH_
17#define _RMG_VERTEX_CONFINEMENT_HH_
18
19#include <chrono>
20#include <memory>
21#include <optional>
22#include <regex>
23#include <string>
24#include <vector>
25
26#include "G4AutoLock.hh"
27#include "G4GenericMessenger.hh"
28#include "G4RotationMatrix.hh"
29#include "G4ThreeVector.hh"
30
31#include "RMGVVertexGenerator.hh"
32
34class G4VSolid;
35
38class RMGVertexConfinement : public RMGVVertexGenerator {
39
40 public:
41
44 kSphere,
45 kCylinder,
46 kBox,
47 };
48
51 GeometricalSolidType solid_type = GeometricalSolidType::kBox;
52 G4ThreeVector volume_center = G4ThreeVector(0, 0, 0);
53 double sphere_inner_radius = 0;
54 double sphere_outer_radius = -1;
55 double cylinder_inner_radius = 0;
56 double cylinder_outer_radius = -1;
57 double cylinder_height = -1;
58 double cylinder_starting_angle = 0;
59 double cylinder_spanning_angle = CLHEP::twopi;
60 double box_x_length = -1;
61 double box_y_length = -1;
62 double box_z_length = -1;
63 };
64
75 enum class SamplingMode {
76 kIntersectPhysicalWithGeometrical,
77 kUnionAll,
78 kSubtractGeometrical,
79 };
80
83 enum class VolumeType {
84 kPhysical,
85 kGeometrical,
86 kUnset,
87 };
88
90
91 void BeginOfRunAction(const G4Run* run) override;
92 void EndOfRunAction(const G4Run* run) override;
93
96 bool GenerateVertex(G4ThreeVector& v) override;
97
107 void AddPhysicalVolumeNameRegex(std::string name, std::string copy_nr = ".*");
108
109 void AddGeometricalVolume(GenericGeometricalSolidData& data) {
110 fGeomVolumeData.emplace_back(data);
111 }
112 void Reset();
113
114 void SetSamplingMode(SamplingMode mode) { fSamplingMode = mode; }
115 void SetFirstSamplingVolumeType(VolumeType type) { fFirstSamplingVolumeType = type; }
116 void SetWeightByMass(bool mode) { fWeightByMass = mode; }
117 void SetWeightByMassIsotope(int z, int n) {
118 fWeightByMass = true;
119 fWeightByMassIsotopeZ = z;
120 fWeightByMassIsotopeN = n;
121 }
122
123 std::vector<GenericGeometricalSolidData>& GetGeometricalSolidDataList() {
124 return fGeomVolumeData;
125 }
126
137 struct SampleableObject {
138
139 SampleableObject() = default;
140 SampleableObject(const SampleableObject&) = default;
141
153 SampleableObject(
154 G4VPhysicalVolume* physvol,
155 G4RotationMatrix rot,
156 G4ThreeVector trans,
157 G4VSolid* solid,
158 bool is_native_sampleable = false,
159 bool on_surface = false
160 );
161
162 // NOTE: G4 volume/solid pointers should be fully owned by G4, avoid trying to delete them
163 ~SampleableObject() = default;
164
170 [[nodiscard]] bool IsInside(const G4ThreeVector& vertex) const;
171
189 [[nodiscard]] bool Sample(
190 G4ThreeVector& vertex,
191 size_t max_attempts,
192 bool force_containment_check,
193 size_t& n_trials
194 ) const;
195
209 [[nodiscard]] bool GenerateSurfacePoint(
210 G4ThreeVector& vertex,
211 size_t max_attempts,
212 size_t max_intersections
213 ) const;
214
215 // methods for the generic surface sampling
230 [[nodiscard]] std::vector<G4ThreeVector> GetIntersections(
231 G4ThreeVector start,
232 G4ThreeVector dir
233 ) const;
234
245 void GetDirection(G4ThreeVector& dir, G4ThreeVector& pos) const;
246
247 void RecalcMass(int z, int n);
248
249 G4VPhysicalVolume* physical_volume = nullptr;
250 G4VSolid* sampling_solid = nullptr;
251 G4RotationMatrix rotation;
252 G4ThreeVector translation;
253
254 double volume = -1;
255 double mass = -1;
256 double surface = -1;
257
258 bool surface_sample = false;
259 bool native_sample = false;
260 size_t max_num_intersections = 0;
261 };
262
266 struct SampleableObjectCollection {
267
268 SampleableObjectCollection() = default;
269 ~SampleableObjectCollection() { data.clear(); }
270
274 [[nodiscard]] const SampleableObject& SurfaceWeightedRand() const;
275
280 [[nodiscard]] const SampleableObject& VolumeWeightedRand(bool weight_by_mass) const;
281 [[nodiscard]] bool IsInside(const G4ThreeVector& vertex) const;
282
283 // emulate @c std::vector
284 [[nodiscard]] size_t size() const { return data.size(); }
285 SampleableObject& at(size_t i) { return data.at(i); }
286 template<typename... Args> void emplace_back(Args&&... args);
287 [[nodiscard]] bool empty() const { return data.empty(); }
288 SampleableObject& back() { return data.back(); }
289 void clear() { data.clear(); }
290 void insert(SampleableObjectCollection& other) {
291 for (size_t i = 0; i < other.size(); ++i) this->emplace_back(other.at(i));
292 this->total_volume += other.total_volume;
293 this->total_mass += other.total_mass;
294 this->total_surface += other.total_surface;
295 }
296
297 void recalc_total(bool weigh_by_mass, int mass_isotope_z, int mass_istotope_n);
298
299 std::vector<SampleableObject> data;
300 double total_volume = 0;
301 double total_mass = 0;
302 double total_surface = 0;
303 };
304
305 private:
306
307 void InitializePhysicalVolumes();
308 void InitializeGeometricalVolumes(bool use_excluded_volumes);
309 bool ActualGenerateVertex(G4ThreeVector& v);
310
311 std::vector<std::string> fPhysicalVolumeNameRegexes;
312 std::vector<std::string> fPhysicalVolumeCopyNrRegexes;
313
314 std::vector<GenericGeometricalSolidData> fGeomVolumeData;
315 std::vector<GenericGeometricalSolidData> fExcludedGeomVolumeData;
316
317 static G4Mutex fGeometryMutex;
318 // the final geometry data is shared between all threads and protected by fGeometryMutex.
319 // this is to prevent problems in G4SolidStore, which is apparently not safe to mutate from
320 // multiple threads. note that some operations that just appear to read static data might also
321 // mutate the G4SolidStore temporarily, e.g. G4SubstractionSolid::GetCubicVolume()
322 static SampleableObjectCollection fPhysicalVolumes;
323 static SampleableObjectCollection fGeomVolumeSolids;
324 static SampleableObjectCollection fExcludedGeomVolumeSolids;
325
326 static bool fVolumesInitialized;
327
328 SamplingMode fSamplingMode = SamplingMode::kUnionAll;
329 VolumeType fFirstSamplingVolumeType = VolumeType::kUnset;
330 bool fWeightByMass = false;
331 int fWeightByMassIsotopeZ = 0;
332 int fWeightByMassIsotopeN = 0;
333
334 bool fOnSurface = false;
335 bool fForceContainmentCheck = false;
336 bool fLastSolidExcluded = false;
337 size_t fSurfaceSampleMaxIntersections = 0;
338
339 // counters used for the current run.
340 size_t fTrials = 0;
341 std::chrono::nanoseconds fVertexGenerationTime{};
342
343 std::vector<std::unique_ptr<G4GenericMessenger>> fMessengers;
344 void SetSamplingModeString(std::string mode);
345 void SetFirstSamplingVolumeTypeString(std::string type);
346
347 void AddGeometricalVolumeString(std::string solid);
348 void AddExcludedGeometricalVolumeString(std::string solid);
349
350 GenericGeometricalSolidData& SafeBack(
351 std::optional<GeometricalSolidType> solid_type = std::nullopt
352 );
353
354 // FIXME: there is no easy way to set the position vector all at once with
355 // G4GenericMessenger. Only ::DeclarePropertyWithUnit() accepts vectors and
356 // one cannot call functions with more than 2 arguments (3 coordinated + 1
357 // units needed). Ugly!
358 void SetGeomVolumeCenter(const G4ThreeVector& v) { this->SafeBack().volume_center = v; }
359 void SetGeomVolumeCenterX(double x) { this->SafeBack().volume_center.setX(x); }
360 void SetGeomVolumeCenterY(double y) { this->SafeBack().volume_center.setY(y); }
361 void SetGeomVolumeCenterZ(double z) { this->SafeBack().volume_center.setZ(z); }
362
363 void SetGeomSphereInnerRadius(double r) {
364 this->SafeBack(GeometricalSolidType::kSphere).sphere_inner_radius = r;
365 }
366 void SetGeomSphereOuterRadius(double r) {
367 this->SafeBack(GeometricalSolidType::kSphere).sphere_outer_radius = r;
368 }
369
370 void SetGeomCylinderInnerRadius(double r) {
371 this->SafeBack(GeometricalSolidType::kCylinder).cylinder_inner_radius = r;
372 }
373 void SetGeomCylinderOuterRadius(double r) {
374 this->SafeBack(GeometricalSolidType::kCylinder).cylinder_outer_radius = r;
375 }
376 void SetGeomCylinderHeight(double h) {
377 this->SafeBack(GeometricalSolidType::kCylinder).cylinder_height = h;
378 }
379 void SetGeomCylinderStartingAngle(double a) {
380 this->SafeBack(GeometricalSolidType::kCylinder).cylinder_starting_angle = a;
381 }
382 void SetGeomCylinderSpanningAngle(double a) {
383 this->SafeBack(GeometricalSolidType::kCylinder).cylinder_spanning_angle = a;
384 }
385
386 void SetGeomBoxXLength(double x) {
387 this->SafeBack(GeometricalSolidType::kBox).box_x_length = x;
388 }
389 void SetGeomBoxYLength(double y) {
390 this->SafeBack(GeometricalSolidType::kBox).box_y_length = y;
391 }
392 void SetGeomBoxZLength(double z) {
393 this->SafeBack(GeometricalSolidType::kBox).box_z_length = z;
394 }
395
396 void DefineCommands();
397};
398
399#endif
400
401// vim: tabstop=2 shiftwidth=2 expandtab
Class for generating vertices in physical or geometrical volumes.
Definition RMGVertexConfinement.hh:38
VolumeType
Types of volume to sample, either physical (a volume in the geometry), geometrical (defined by the us...
Definition RMGVertexConfinement.hh:83
GeometricalSolidType
Different types of geometrical (user) defined solids.
Definition RMGVertexConfinement.hh:43
void AddPhysicalVolumeNameRegex(std::string name, std::string copy_nr=".*")
Definition RMGVertexConfinement.cc:1075
SamplingMode
Strategy for sampling physical and geometrical volumes.
Definition RMGVertexConfinement.hh:75
bool GenerateVertex(G4ThreeVector &v) override
Generate the actual vertex, according to the sampling mode (see RMGVertexConfinement::SamplingMode).
Definition RMGVertexConfinement.cc:810
Information about the geometrical (user) defined solids.
Definition RMGVertexConfinement.hh:50
A collection of SampleableObject objects. It can be used to sample from by selecting a volume weighte...
Definition RMGVertexConfinement.hh:266
const SampleableObject & SurfaceWeightedRand() const
Select a SampleableObject from the collection, weighted by surface area.
Definition RMGVertexConfinement.cc:104
const SampleableObject & VolumeWeightedRand(bool weight_by_mass) const
Select a SampleableObject from the collection, weighted by volume.
Definition RMGVertexConfinement.cc:128
Definition RMGVertexConfinement.hh:137
bool Sample(G4ThreeVector &vertex, size_t max_attempts, bool force_containment_check, size_t &n_trials) const
Generate a sample from the solid.
Definition RMGVertexConfinement.cc:322
void GetDirection(G4ThreeVector &dir, G4ThreeVector &pos) const
Get a position and direction for the generic surface sampling algorithm.
Definition RMGVertexConfinement.cc:226
bool GenerateSurfacePoint(G4ThreeVector &vertex, size_t max_attempts, size_t max_intersections) const
Generate a point on the surface of the solid.
Definition RMGVertexConfinement.cc:265
std::vector< G4ThreeVector > GetIntersections(G4ThreeVector start, G4ThreeVector dir) const
Get the number of intersections between the solid and the line starting at start with direction dir.
Definition RMGVertexConfinement.cc:172
bool IsInside(const G4ThreeVector &vertex) const
Check if the vertex is inside the solid.
Definition RMGVertexConfinement.cc:158