Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//==========================================================================
// AIDA Detector description implementation
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
// All rights reserved.
//
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
//
// Author : M.Frank
//
//==========================================================================
// Framework include files
#include <DD4hep/Volumes.h>
#include <DD4hep/Printout.h>
#include <DDG4/Geant4Helpers.h>
#include <DDG4/Geant4PlacementParameterisation.h>
// Geant4 include files
#include <G4Transform3D.hh>
/// Initializing constructor
dd4hep::sim::Geant4PlacementParameterisation::Geant4PlacementParameterisation(PlacedVolume pv)
: G4VPVParameterisation(), m_placement(pv), m_params(*pv.data()->params)
{
auto& dim = m_dimensions;
G4Transform3D start = g4Transform(m_params.start);
G4Transform3D tr(g4Transform(m_params.trafo1D.first));
m_start = {tr, 0UL};
m_have_rotation = false;
dim.emplace_back(Dimension(tr, m_params.trafo1D.second));
m_have_rotation |= dim.back().delta.getRotation().isIdentity();
if ( m_params.trafo2D.second > 0 ) {
tr = g4Transform(m_params.trafo2D.first);
dim.emplace_back(Dimension(tr, m_params.trafo2D.second));
m_have_rotation |= dim.back().delta.getRotation().isIdentity();
}
if ( m_params.trafo3D.second > 0 ) {
tr = g4Transform(m_params.trafo3D.first);
dim.emplace_back(Dimension(tr, m_params.trafo3D.second));
m_have_rotation |= dim.back().delta.getRotation().isIdentity();
}
if ( m_have_rotation ) {
auto callback = std::bind(&Geant4PlacementParameterisation::operator(),
*this, std::placeholders::_1);
if ( dim.size() == 1 )
generate_placements(start,
dim[0].delta, dim[0].count, callback);
else if ( dim.size() == 2 )
generate_placements(start,
dim[0].delta, dim[0].count,
dim[1].delta, dim[1].count, callback);
else if ( dim.size() == 3 )
generate_placements(start,
dim[0].delta, dim[0].count,
dim[1].delta, dim[1].count,
dim[2].delta, dim[2].count, callback);
}
}
/// Access number of replicas
std::size_t dd4hep::sim::Geant4PlacementParameterisation::count() const {
std::size_t ncell = 1;
for(const auto& d : m_dimensions) ncell *= d.count;
return ncell;
}
/// Callback to store resulting rotation
void dd4hep::sim::Geant4PlacementParameterisation::operator()(const G4Transform3D& transform) {
m_translations.emplace_back(transform.getTranslation());
if ( this->m_have_rotation ) {
G4RotationMatrix rot = transform.inverse().getRotation();
m_rotations.emplace_back(rot);
}
}
/// G4VPVParameterisation overload: Callback to place sub-volumes
void dd4hep::sim::Geant4PlacementParameterisation::ComputeTransformation(const G4int copy, G4VPhysicalVolume *pv) const {
const auto& dim = m_dimensions;
std::size_t nd = dim.size();
if ( !m_have_rotation ) {
G4ThreeVector tra = m_start.translation;
if ( nd >= 1 ) {
std::size_t dim1 = nd == 1 ? copy : (nd == 2 ? copy%dim[1].count : (nd == 3 ? copy%(dim[1].count*dim[2].count) : 0));
tra = dim[0].translation * dim1;
}
if ( nd >= 2 ) {
std::size_t dim2 = nd == 3 ? copy%dim[2].count / dim[0].count : (nd==2 ? copy / dim[0].count : 0);
tra = tra + dim[1].translation * dim2;
}
if ( nd >= 3 ) {
std::size_t dim3 = nd == 3 ? copy / (dim[0].count*dim[1].count) : 0;
tra = tra + dim[2].translation * dim3;
}
pv->SetTranslation(tra);
return;
}
G4RotationMatrix& rot = m_rotations.at(copy);
pv->SetTranslation(m_translations.at(copy));
pv->SetRotation(&rot);
}