DD4hep  1.35.0
Detector Description Toolkit for High Energy Physics
FieldTypes.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 #include <DD4hep/FieldTypes.h>
15 #include <DD4hep/detail/Handle.inl>
16 #include <cmath>
17 
18 using namespace dd4hep;
19 
20 #ifndef INFINITY
21 #define INFINITY (numeric_limits<double>::max())
22 #endif
23 
24 
29 
31 void ConstantField::fieldComponents(const double* pos, double* field) {
32  if ( 0 == flag || nullptr == volume.ptr() ) {
33  field[0] += direction.X();
34  field[1] += direction.Y();
35  field[2] += direction.Z();
36  }
37  else if ( flag&FIELD_LOCAL ) {
38  Transform3D::Point p0(pos[0],pos[1],pos[2]);
39  Transform3D::Point p = this->inverse_pos * p0;
40  const Double_t coords[3] = {p.x(), p.y(), p.z()};
41  if( volume->Contains(coords) ) {
42  field[0] += direction.X();
43  field[1] += direction.Y();
44  field[2] += direction.Z();
45  }
46  }
48 }
49 
52  : innerField(0), outerField(0), minZ(-INFINITY), maxZ(INFINITY), innerRadius(0), outerRadius(INFINITY)
53 {
55 }
56 
58 void SolenoidField::fieldComponents(const double* pos, double* field) {
59  double z = pos[2] ;
60  // std::cout << " field z=" << z << " maxZ=" << maxZ << " minZ = " << minZ << std::endl ;
61  if( z > minZ && z < maxZ ){
62  double radius = std::sqrt(pos[0] * pos[0] + pos[1] * pos[1]);
63  if (radius < innerRadius)
64  field[2] += innerField;
65  else if (radius < outerRadius)
66  field[2] += outerField;
67  }
68 }
69 
73 }
74 
76 void DipoleField::fieldComponents(const double* pos, double* field) {
77  double z = pos[2], r = std::sqrt(pos[0] * pos[0] + pos[1] * pos[1]);
78  // Check if z coordinate is within dipole z bounds.
79  if (z > zmin && z < zmax && r < rmax) {
80  // Apply all coefficients to this z coordinate.
81  double pp = 1.0;
82  double abs_z = fabs(z);
83  double bx = coefficents[0];
84  for (size_t i = 1; i < coefficents.size(); ++i) {
85  pp *= abs_z;
86  bx += coefficents[i] * pp;
87  }
88  // Flip sign for negative z.
89  if (z < 0)
90  bx = -bx;
91  // Add Bx to the input field.
92  field[0] += bx;
93  }
94 }
95 
96 namespace {
97  constexpr static unsigned char FIELD_INITIALIZED = 1<<0;
98  constexpr static unsigned char FIELD_IDENTITY = 1<<1;
99  constexpr static unsigned char FIELD_ROTATION_ONLY = 1<<2;
100  constexpr static unsigned char FIELD_POSITION_ONLY = 1<<3;
101  constexpr static unsigned char FIELD_HAS_AABB = 1<<4;
102 }
103 
107 }
108 
110 void MultipoleField::fieldComponents(const double* pos, double* field) {
111  if ( 0 == flag ) {
112  constexpr static double eps = 1e-10;
113  double xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz;
114  transform.GetComponents(xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz);
115  flag |= FIELD_INITIALIZED;
116  if ( (xx + yy + zz) < (3e0 - eps) ) {
117  flag |= FIELD_ROTATION_ONLY;
118  }
119  else {
120  flag |= FIELD_POSITION_ONLY;
121  if ( (std::abs(dx) + std::abs(dy) + std::abs(dz)) < eps )
122  flag |= FIELD_IDENTITY;
123  }
124  this->inverse = this->transform.Inverse();
125  this->transform.GetRotation(this->rotation);
126  this->transform.GetTranslation(this->translation);
127  if ( volume.isValid() ) {
128  // Obtain the bounding box from the shape. TGeoBBox is the base class
129  // for most shapes, but not all.
130  TGeoShape* shape = volume.ptr();
131  auto* bbox = dynamic_cast<TGeoBBox*>(shape);
132  if ( bbox ) {
133  bbox->ComputeBBox();
134  const double* orig = bbox->GetOrigin();
135  double bdx = bbox->GetDX();
136  double bdy = bbox->GetDY();
137  double bdz = bbox->GetDZ();
138  // Transform the local bbox center to world frame
139  Transform3D::Point world_center =
140  this->transform * Transform3D::Point(orig[0], orig[1], orig[2]);
141  // World half-extents via rotation-matrix abs-sum formula (OBB -> AABB)
142  double hx = std::abs(xx)*bdx + std::abs(xy)*bdy + std::abs(xz)*bdz;
143  double hy = std::abs(yx)*bdx + std::abs(yy)*bdy + std::abs(yz)*bdz;
144  double hz = std::abs(zx)*bdx + std::abs(zy)*bdy + std::abs(zz)*bdz;
145  this->aabb_min[0] = world_center.X() - hx;
146  this->aabb_max[0] = world_center.X() + hx;
147  this->aabb_min[1] = world_center.Y() - hy;
148  this->aabb_max[1] = world_center.Y() + hy;
149  this->aabb_min[2] = world_center.Z() - hz;
150  this->aabb_max[2] = world_center.Z() + hz;
151  flag |= FIELD_HAS_AABB;
152  }
153  }
154  }
155  // AABB pre-filter: reject positions outside the world-frame bounding box
156  if ( (flag&FIELD_HAS_AABB) &&
157  (pos[0] < aabb_min[0] || pos[0] > aabb_max[0] ||
158  pos[1] < aabb_min[1] || pos[1] > aabb_max[1] ||
159  pos[2] < aabb_min[2] || pos[2] > aabb_max[2]) )
160  return;
161  // Transform the input position to the local frame of the field
162  Transform3D::Point p, p0(pos[0],pos[1],pos[2]);
163  if ( flag&FIELD_IDENTITY ) p = std::move(p0);
164  else if ( flag&FIELD_POSITION_ONLY ) p = p0 - this->translation;
165  else p = this->inverse * p0;
166 
167  double x = p.X(), y = p.Y(), z = p.Z();
168  double coord[3] = {x, y, z};
169  // Debug printout:
170  //::printf("Pos: %+15.8e %+15.8e %+15.8e Inverse: %+15.8e %+15.8e %+15.8e\n",
171  // pos[0]/dd4hep::cm,pos[1]/dd4hep::cm,pos[2]/dd4hep::cm, p.X()/dd4hep::cm, p.Y()/dd4hep::cm, p.Z()/dd4hep::cm);
172 
173  if ( 0 == volume.ptr() || volume->Contains(coord) ) {
174  double bx = 0.0;
175  double by = 0.0;
176  double xy = x*y;
177  double x2 = x*x;
178  double y2 = y*y;
179  switch(coefficents.size()) {
180  case 4: // Octupole momentum
181  by += (1./6.) * ( coefficents[3] * (x2*x - 3.0*x*y2) + skews[3]*(y2*y - 3.0*x2*y) );
182  bx += (1./6.) * ( coefficents[3] * (3.0*x2*y - y2*y) + skews[3]*(x2*x - 3.0*x*y2) );
183  [[fallthrough]];
184  case 3: // Sextupole momentum:
185  by += (1./2.) * ( coefficents[2] * (x2 - y2) - skews[2] * 2.0 * xy );
186  bx += (1./2.) * ( coefficents[2] * 2.0 * xy + skews[2] * (x2 - y2) );
187  [[fallthrough]];
188  case 2: // Quadrupole momentum:
189  bx += coefficents[1] * y + skews[1]*x;
190  by += coefficents[1] * x - skews[1]*y;
191  [[fallthrough]];
192  case 1: // Dipole momentum:
193  bx += skews[0];
194  by += coefficents[0];
195  [[fallthrough]];
196  case 0: // Nothing, but still valid
197  break;
198  default: // Error condition
199  throw std::runtime_error("Invalid multipole field definition!");
200  }
201  Transform3D::Point f = this->rotation * Transform3D::Point(bx, by, B_z);
202  field[0] += f.X();
203  field[1] += f.Y();
204  field[2] += f.Z();
205  }
206 }
INFINITY
#define INFINITY
Definition: FieldTypes.cpp:21
dd4hep::ConstantField::inverse_pos
Transform3D inverse_pos
If solid is set: allow for movement of the solid.
Definition: FieldTypes.h:42
dd4hep::DipoleField::zmin
double zmin
Definition: FieldTypes.h:87
dd4hep::ConstantField::FIELD_LOCAL
@ FIELD_LOCAL
Definition: FieldTypes.h:36
dd4hep::DipoleField::rmax
double rmax
Definition: FieldTypes.h:88
dd4hep::MultipoleField
Implementation object of a Multipole magnetic field.
Definition: FieldTypes.h:159
dd4hep::MultipoleField::aabb_min
double aabb_min[3]
Axis-aligned bounding box in world coordinates.
Definition: FieldTypes.h:182
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:126
dd4hep::CartesianField::MAGNETIC
@ MAGNETIC
Definition: Fields.h:43
dd4hep::DipoleField
Implementation object of a dipole magnetic field.
Definition: FieldTypes.h:84
dd4hep::ConstantField::fieldComponents
virtual void fieldComponents(const double *, double *field)
Call to access the field components at a given location.
Definition: FieldTypes.cpp:31
dd4hep::SolenoidField::maxZ
double maxZ
Definition: FieldTypes.h:65
dd4hep::ConstantField
Implementation object of a field with constant strength.
Definition: FieldTypes.h:34
dd4hep::DipoleField::zmax
double zmax
Definition: FieldTypes.h:86
dd4hep::SolenoidField::innerRadius
double innerRadius
Definition: FieldTypes.h:66
dd4hep::SolenoidField::fieldComponents
virtual void fieldComponents(const double *pos, double *field)
Call to access the field components at a given location.
Definition: FieldTypes.cpp:58
DD4HEP_INSTANTIATE_HANDLE
DD4HEP_INSTANTIATE_HANDLE(ConstantField)
dd4hep::DipoleField::coefficents
Coefficents coefficents
Definition: FieldTypes.h:89
dd4hep::DipoleField::fieldComponents
virtual void fieldComponents(const double *pos, double *field)
Call to access the field components at a given location.
Definition: FieldTypes.cpp:76
dd4hep::MultipoleField::B_z
double B_z
Constant Z field overlay.
Definition: FieldTypes.h:174
dd4hep::MultipoleField::aabb_max
double aabb_max[3]
Definition: FieldTypes.h:183
dd4hep::SolenoidField::minZ
double minZ
Definition: FieldTypes.h:64
dd4hep::ConstantField::direction
Direction direction
Field direction.
Definition: FieldTypes.h:38
dd4hep::MultipoleField::transform
Transform3D transform
Position transformation of the field. Only stored here for reference.
Definition: FieldTypes.h:168
dd4hep::DipoleField::DipoleField
DipoleField()
Initializing constructor.
Definition: FieldTypes.cpp:71
dd4hep::SolenoidField::SolenoidField
SolenoidField()
Initializing constructor.
Definition: FieldTypes.cpp:51
dd4hep::MultipoleField::fieldComponents
virtual void fieldComponents(const double *pos, double *field)
Call to access the field components at a given location.
Definition: FieldTypes.cpp:110
dd4hep::MultipoleField::rotation
Rotation3D rotation
The rotation part of the transformation. Need to rotate the field.
Definition: FieldTypes.h:172
dd4hep::CartesianField::TypedObject::field_type
int field_type
Field type.
Definition: Fields.h:56
dd4hep::MultipoleField::MultipoleField
MultipoleField()
Initializing constructor.
Definition: FieldTypes.cpp:105
dd4hep::SolenoidField::outerField
double outerField
Definition: FieldTypes.h:63
dd4hep::MultipoleField::skews
Coefficents skews
Multi-pole skews.
Definition: FieldTypes.h:164
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:151
dd4hep::MultipoleField::inverse
Transform3D inverse
Inverse position transformation of the field.
Definition: FieldTypes.h:170
dd4hep::MultipoleField::volume
Solid volume
Boundary volume (optional)
Definition: FieldTypes.h:166
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::MultipoleField::translation
Transform3D::Point translation
Translation of the transformation.
Definition: FieldTypes.h:180
dd4hep::MultipoleField::coefficents
Coefficents coefficents
Multi-pole coefficients.
Definition: FieldTypes.h:162
dd4hep::ConstantField::flag
unsigned char flag
The access to the field will be optimized. Remember properties.
Definition: FieldTypes.h:44
dd4hep::SolenoidField::outerRadius
double outerRadius
Definition: FieldTypes.h:67
FieldTypes.h
dd4hep::SolenoidField::innerField
double innerField
Definition: FieldTypes.h:62
dd4hep::MultipoleField::flag
unsigned char flag
The access to the field will be optimized. Remember properties.
Definition: FieldTypes.h:178
dd4hep::SolenoidField
Implementation object of a solenoidal magnetic field.
Definition: FieldTypes.h:60
dd4hep::ConstantField::volume
Solid volume
Boundary volume (optional)
Definition: FieldTypes.h:40