DLG4::VolumeBuilders
A fluent interface for Geant4 geometry definition.
Loading...
Searching...
No Matches
VolumeBuilder.hh
Go to the documentation of this file.
1#pragma once
2#ifndef VOLUMEBUILDER_HH
3#define VOLUMEBUILDER_HH
4#include <optional>
5#include "Linkable.hh"
6#include "IVolumeBuilder.hh"
7#include "ISolidBuilder.hh"
9/*
10
11 * VolumeMaker.hh
12 *
13 * Created on: Jun 19, 2024
14 * Author: D. S. Leonard
15 * Implicit or explicit misrepresentation authorship is not protected under any license.
16 * See RZBuilder.hh for main documentation.
17 *
18 *s
19
20 */
21//#define SHARED_WRAPPER DLG4::i_shared_ptr
22#include <vector>
23#include "i_shared_ptr.hh"
25
26
27// #define FIXME(msg) static_assert(false, "FIXME: " msg)
28
29//#include "DetectorConstruction_includes.hh"
31#include <G4Material.hh>
32#include "G4Colour.hh" // why? It's in above.
33#include "G4VPhysicalVolume.hh"
34#include "G4UnionSolid.hh"
35#include <G4ThreeVector.hh>
36#include <mutex>
37#include <memory>
38#include <unordered_map>
39#include "Assembly.hh"
40
41//#include "VolumeBuilderReference.hh"
42
44
45 class VolumeBuilderReference;
46 template <typename U>
47 class VolumeBuilder;
48
59 template <typename U>
60 class VolumeBuilder: public ENABLE_SHARED_WRAPPER<U>, public ISolidBuilder
61 , public IVolumeBuilder {
65
66 // limit public(protected) API by using friendship.
67 // Much of this can't even be handledby protected.
68 // Specifically factories (normal) and the type-erasing pseudo-inheritance (StructureBuilder)
69 template <typename>
70 friend class VolumeBuilder;
72 friend class Assembly;
73 template <typename>
74 friend class StructureBuilder;
76 friend FromG4VSolidPtr VB::CreateFromG4VSolid(G4VSolid *solid);
77 friend AssemblyPtr VB::CreateAssembly(G4String names);
78 friend class RZBuilder;
79 friend class BoxBuilder;
80 friend class FromG4VSolid;
81
82 public:
90 [[nodiscard]] G4VPhysicalVolume *GetPlacement() final;
91
101
102
112 this->MakePlacement();
113 auto clone = this->ForkForPlacement(); // default/preset options
114 return clone;
115 }
116
125 [[nodiscard]] G4LogicalVolume *GetLogicalVolume() final;
126
137 [[nodiscard]] G4VSolid *GetBaseSolid() final;
138
145 [[nodiscard]] G4VSolid *GetFinalSolid() final;
146
147
159 DerivedPtr MakeLogicalVolume(
160 G4Material *material = nullptr, G4String name = std::string());
161
167 DerivedPtr MakeSolid();
168
174 DerivedPtr SetName(const G4String &name);
175
196 DerivedPtr AddUnion(const BuilderView &other,
197 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
198 G4RotationMatrix *rotation = nullptr);
200 DerivedPtr AddSubtraction(const BuilderView &other,
201 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
202 G4RotationMatrix *rotation = nullptr);
204 DerivedPtr AddIntersection(const BuilderView &other,
205 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
206 G4RotationMatrix *rotation = nullptr);
220 DerivedPtr AddBoolean(
221 const BuilderView &other,
222 bool is_subtraction = false,
223 bool is_intersection = false,
224 const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0},
225 G4RotationMatrix *rotation = nullptr
226 );
235 DerivedPtr SetMaterial(G4Material *material);
236
242 DerivedPtr SetColor(double r = 0.5, double g = 0.5, double b = 0.5, double alpha = 1.0);
243
250 DerivedPtr SetColor(const G4Colour &color);
251
258 DerivedPtr SetAlpha(G4double alpha);
259
265 DerivedPtr ForceSolid(bool x = true); // default if uncalled is false.
266
273 DerivedPtr SetVisibility(bool x = true);
274
275 // ... inside the VolumeBuilder class declaration ...
276
290 DerivedPtr SetLogicalVolume(G4LogicalVolume *logical_volume);
291
301 DerivedPtr SetBooleanName(const G4String &name);
302
310 DerivedPtr SetPhysRotation(const G4RotationMatrix &rot);
311
322 DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot);
323
340 DerivedPtr SetPhysOffset(const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0});
351 DerivedPtr StackPhysOffset(const Unit3Vec &offset = {CLHEP::mm, 0, 0, 0});
352
366 DerivedPtr SetPhysTransform(const UnitlessG4Transform3D &new_transform);
373 DerivedPtr StackPhysTransform(const UnitlessG4Transform3D &new_transform);
374
385 G4Transform3D GetPhysTransform() const final {
386 return {placement_configs_->rotation, placement_configs_->translation};
387 }
388
389
396 DerivedPtr OverridePlacementName(const G4String &pName);
397
398
405 DerivedPtr SetCopyNo(G4int pCopyNo);
406
413 DerivedPtr SetSurfaceCheck(G4bool pSurfChk);
414
415
427 DerivedPtr SetMother(const BuilderView &mother);
428
440 DerivedPtr SetAutoPlacementNaming(bool set);
441
442
453 DerivedPtr SetAutoCopyNo(bool set);
454
470 DerivedPtr ReflectZFinalSolid();
471
480 DerivedPtr ReflectZBaseSolid();
481
496 virtual DerivedPtr ForkAndReset(const G4String &new_name) const;
497
507 DerivedPtr ForkForFinalSolid(const G4String &new_name);
508
509
522 DerivedPtr ForkForLogicalVolume(const G4String &new_name);
523
524
539 DerivedPtr ForkForPlacement(
540 std::optional<int> copy_no = std::nullopt
541 , const G4String &name_override = ""
542 , bool parent_name_was_set = false
543 // in assembly/hierarchies, name change derives through parent
544 );
545
562 DerivedPtr CopyPlacementConfigsFrom(const BuilderView &other);
563
573 DerivedPtr CopyVolumeConfigsFrom(const BuilderView &other);
574
592 DerivedPtr SetDefaultUnit(G4double unit);
593
599 G4double GetEffectiveDefaultUnit() const;
609 DerivedPtr AddTo(BuilderViewList &list) const;
610
618 DerivedPtr AddTo(StructureViewList &list) const;
619
627 DerivedPtr AddTo(AssemblyPtr &assembly) const;
628
633 ~VolumeBuilder() override;
634
635 BuilderView ToBuilderView() const override;
636
637 StructureView ToStructureView() const override;
638
639 G4String GetBuilderName() const;
640
641 protected:
643 G4VSolid *SolidConstructor(const G4String &name) override = 0;
644
645 // base implementation of non-fluent clone.
647
648 private:
649 //Methods with basically protected intent
650 // But for now, keep them private and require explicit friend access
651 // ctors only useable through explicitly granted (friendship) inheritance...
652
653
655 DerivedPtr SetSolid(G4VSolid *solid);
656
657 DerivedPtr Clone() const {
658 // This call is NOT DIRECTLY polymorphic. It calls the VolumeBuilder base clone_impl().
659 // Internally THAT calls polymorphic clone to create the structure_ptr and recreate the view.
660 // We have to re-cast the result.
661 i_shared_ptr<IStructureBuilder> base_cloned_ptr = this->clone_impl();
662 return std::static_pointer_cast<U>(base_cloned_ptr);
663 }
664
665
666 template <typename T, typename std::enable_if_t<std::is_base_of_v<IStructureBuilder, T>,
667 int> = 0>
669
670 VolumeBuilder &operator=(const VolumeBuilder &other) = delete;
671 DerivedPtr MakeFinalSolid(G4String boolean_name = "");
672 VolumeBuilder(const VolumeBuilder &other);
673
674 VolumeBuilder(VolumeBuilder &&) noexcept = default;
675
676 G4VSolid *GetSolidPtr() const {
677 return this->solid_ptr_.get_mutable();
678 };
679
680 //Configs (re-linked by copy-ctors)
681 ONCE_MUTABLE Linkable<BuilderConfigs> builder_configs_{BuilderConfigs{}};
682 ONCE_MUTABLE Linkable<BooleanConfigs> boolean_configs_{BooleanConfigs{}};
683 ONCE_MUTABLE Linkable<VolumeConfigs> lv_configs_{VolumeConfigs{}};
684 ONCE_MUTABLE Linkable<PlacementConfigs> placement_configs_{PlacementConfigs{}};
685
686 //Products (sometimes copied by copy methods)
687 ONCE_MUTABLE Linkable<G4VSolid> solid_ptr_{}; // child can and should create the solid
688 ONCE_MUTABLE Linkable<G4VSolid> final_solid_ptr_{};
691
692
696 void StoreIStructurePtr(const IStructurePtr &istructure_ptr);
697
698 void StoreBuilderView(const BuilderView &builder_view);
699
700
701 //Unsaved data, left out of configs to be reset on all copy operations.
702 bool explicit_copyno_set_ = false;
703 bool explicit_physical_copy_name_set_ = false;
704 G4String placement_name_override_ = ""; // Will be derived from boolean_name_ by default
705
706 void SetSolid_impl(G4VSolid *solid);
707 void SetLogicalVolume_impl(G4LogicalVolume *logical_volume);
708
709 //Some hard baked settings
710 // let's pretend like we'd ever care about resource management:
711 static constexpr bool has_ownership_{false}; // for future resource control
712 static constexpr bool enable_full_lazy_builds{true};
713 // Allows full chain lazy building. Off for now.
714
715 //Methods with truly private intent.
716
717 // Propagate transforms
718 void PropagateTransform();
719
720
721 void ApplyAttributes_();
722 G4String GetPlacementBaseName() const;
723
724 [[nodiscard]] G4String GetLogicVolName() const; // should this be pulic?
725
726 // these validators may trigger lazy build of buildable products needed for the build:
727 void ValidateForPVBuild(std::string const &site = std::string());
728 void ValidateForVolumeBuild(std::string const &site = std::string());
729 void ValidateForBooleanBuild(std::string const &site = std::string());
730 // These helper validators just check that the product isn't already made:
731 void ValidateSolidNotBuilt(const std::string &operation) const;
732 void ValidateBooleanNotBuilt(const std::string &operation) const;
733 void ValidateLogicalNotBuilt(const std::string &operation) const;
734 void ValidatePlacementNotBuilt(const std::string &operation) const;
735
736 // For Geant, we need things left persistent, but this is a poor way even for this hack:
737 static void make_persistent(const std::shared_ptr<void> &obj);
738
739 G4ThreeVector ProvisionUnits(const Unit3Vec &vec) const;
740
741 // Private static helper
742 // method(s) used by the instance methods
743
744 static void NoNameCheck(const std::string &name, const std::string &site) {
745 if (name.empty()) {
746 throw std::runtime_error("Error in " + site + " ,"
747 "for builder named: " + name + "\n"
748 " Must provide a new name");
749 }
750 }
751 };
752} // namespace VolumeBuilder
753
754
755//The implementation:
756#include "VolumeBuilder.hpp"
757#endif
758
759/* TODO
760 * Need more derived classes for boxes and stuff!
761 * [] Propagate validators into all config methods.
762 * [] Validators needed in RZBuilder still.
763 * [] review make_persistent vs no-op deleters, and add upfront protection. make_persistent may need templating.
764 * [] use self-owned shared_ptr trick (intentional cycle) instead of make_peristent.
765 * [] A fill and copy would great.
766
767FromG4VSolid (rename?-> SolidAdapterBuilder)
768Bonus
769*
770* [] consider adding overlap check option to command line for easier use.
771* */
#define SET_LINK_TYPE
Definition Linkable.hh:62
#define ONCE_MUTABLE
A type-erased (data shared view) view of a builder or assembly, ie a "structure.".
Definition Assembly.hh:38
Builder class for simple Box solids.
A solid buider class that just wrap an existing G4VSolid.
Builder class for RZ mult-plane defined solids.
Definition RZBuilder.hh:131
A type-erased (data shared view) view of a builder or assembly, ie a "structure.".
A type-erased (data shared view) view of a builder or assembly, ie a "structure.".
A 3D vector that carries its own unit information.
A polymorphic, type-erased builder referencing any specialized builder.
VolumeBuilder: Common functionality for volume builder classes.
DerivedPtr ReflectZFinalSolid()
Configure final solid to be flipped in z.
~VolumeBuilder() override
Destructor Normally does not delete volume objects.
DerivedPtr SetName(const G4String &name)
SetName Sets name used for solid and derived product names.
SharedPtr< IStructureBuilder > clone_impl() const override
DerivedPtr StackPhysTransform(const UnitlessG4Transform3D &new_transform)
Like SetPhysTransform but stacks with previous transformations in order applied.
G4VSolid * SolidConstructor(const G4String &name) override=0
polymorphic access to solid construction
DerivedPtr MakePlacement()
Make a placed physical volume.
DerivedPtr AddTo(BuilderViewList &list) const
DerivedPtr StackPhysOffset(const Unit3Vec &offset={CLHEP::mm, 0, 0, 0})
Like SetPhysOffset but stacks with previous transformations in order applied.
DerivedPtr StackPhysRotation(const G4RotationMatrix &stacked_rot)
Like SetPhysRotation but stacks with previous transformations in order applied.
DerivedPtr MakeLogicalVolume(G4Material *material=nullptr, G4String name=std::string())
Basically never needed now.
DerivedPtr ReflectZBaseSolid()
Configure base solid to be flipped BEFORE applying booleans.
DerivedPtr CopyVolumeConfigsFrom(const BuilderView &other)
Copies the LogicalVolume configuration (material, VisAttributes, etc.) from another builder.
DerivedPtr CopyPlacementConfigsFrom(const BuilderView &other)
This may help if reusing placement configs for a different shape.
AssemblyPtr CreateAssembly(G4String name)
Assembly of strucures, ie builders and/or other assemblies.
Definition Assembly.cc:18
FromG4VSolidPtr CreateFromG4VSolid(G4VSolid *solid)
Constructor to make a builder from an Existing Geant solid.
DerivedPtr ForkForLogicalVolume(const G4String &new_name)
Makes final solid (including booleans) if unbuilt and copies builder with products cleared for furthe...
virtual DerivedPtr ForkAndReset(const G4String &new_name) const
Copy a configured/unbuilt Builder, with a new name.
DerivedPtr ForkForFinalSolid(const G4String &new_name)
Calls MakeSolid() and copies builder with products cleared for further construction.
DerivedPtr ForkForPlacement(std::optional< int > copy_no=std::nullopt, const G4String &name_override="", bool parent_name_was_set=false)
Calls MakeLogicalVolume() and creates a new builder instance with a copy of all placement-related con...
DerivedPtr SetColor(double r=0.5, double g=0.5, double b=0.5, double alpha=1.0)
DerivedPtr SetMaterial(G4Material *material)
DerivedPtr AddBoolean(const BuilderView &other, bool is_subtraction=false, bool is_intersection=false, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Add a boolean operation.
DerivedPtr SetAutoCopyNo(bool set)
Enable (disable for false) auto Physical Volume numbering, on by default.
DerivedPtr SetBooleanName(const G4String &name)
Pre-set base name for logical and physical volumes.
DerivedPtr SetLogicalVolume(G4LogicalVolume *logical_volume)
Directly Provide a Logical Volume Instead of using the builder.
DerivedPtr SetSurfaceCheck(G4bool pSurfChk)
Set the surface check flag for the placement.
DerivedPtr SetMother(const BuilderView &mother)
Set the mother volume with a builder, or G4VPhysicalVolume or G4VLogicalVolume through implicit conve...
DerivedPtr SetPhysOffset(const Unit3Vec &offset={CLHEP::mm, 0, 0, 0})
Set the translation vector for placement.
DerivedPtr SetPhysTransform(const UnitlessG4Transform3D &new_transform)
Set the G4Transform3D for placment The tranformation provided is meant to be UNITLESS unless you SetD...
DerivedPtr SetCopyNo(G4int pCopyNo)
Set the copy number for the placement.
DerivedPtr OverridePlacementName(const G4String &pName)
Set the placement name for the volume.
DerivedPtr SetPhysRotation(const G4RotationMatrix &rot)
Set the rotation matrix for placement.
DerivedPtr SetAutoPlacementNaming(bool set)
Enable auto Physical Volume naming.
G4Transform3D GetPhysTransform() const final
A helper to get the Physical Volume transform with units applied This is built from rotation and tran...
DerivedPtr PlaceAndFork()
An alias for MakePlacement and ForkForPlacement Used for one or many unaltered placments in sequence,...
G4VSolid * GetFinalSolid() final
Gets a complete final built Solid, including configured Boolean operaions if any.
G4LogicalVolume * GetLogicalVolume() final
Gets a built LogicalVolume, builds default if not built yet.
G4VPhysicalVolume * GetPlacement() final
Gets the (last) placed physical volume.
G4VSolid * GetBaseSolid() final
You probably want GetSolid() instead!!! This Gets a built Solid, BUT NOT final Boolean.
G4double GetEffectiveDefaultUnit() const
Get the builder default unit or global if not set.
DerivedPtr SetDefaultUnit(G4double unit)
Set the per-Builder default unit for all later non-factory offsets.
DerivedPtr AddSubtraction(const BuilderView &other, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Define combination another volume with present one, This does NOT immediately trigger a build on a pa...
DerivedPtr AddUnion(const BuilderView &other, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Define combination another volume with present one, This does NOT immediately trigger a build on a pa...
DerivedPtr AddIntersection(const BuilderView &other, const Unit3Vec &offset={CLHEP::mm, 0, 0, 0}, G4RotationMatrix *rotation=nullptr)
Define combination another volume with present one, This does NOT immediately trigger a build on a pa...
SharedPtr< VolumeBuilderReference > BuilderView
Common interface for all volume builder types.
SharedPtr< IStructureBuilder > IStructurePtr
True polymorphic class base view for all structures Mostly for internal use.
std::vector< StructureView > StructureViewList
a user type to hold many structures
std::vector< BuilderView > BuilderViewList
a user type to hold many builders