CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DDPixBarTPGStackLayerAlgo.cc
Go to the documentation of this file.
1 // File: DDPixBarTPGStackLayerAlgo.cc
3 // Description: Make one layer of stacked pixel barrel detector
5 
6 #include <cmath>
7 #include <algorithm>
8 
17 #include "CLHEP/Units/PhysicalConstants.h"
18 #include "CLHEP/Units/SystemOfUnits.h"
19 
20 
22 // Constructor
24  LogDebug("PixelGeom") <<"DDPixBarTPGStackLayerAlgo info: Creating an instance";
25 }
26 
28 // Destructor
30 
32 // Initialization of algorithm
34  const DDVectorArguments & vArgs,
35  const DDMapArguments & ,
36  const DDStringArguments & sArgs,
37  const DDStringVectorArguments & vsArgs) {
38 
39 
40 // Retrieve the variables from the XML files
42  DDName parentName = parent().name();
43 
44  VolumeMaterial = sArgs["VolumeMaterial"];
45  number = int(nArgs["Ladders"]);
46  layerDz = nArgs["LayerDz"];
47  sensorEdge= nArgs["SensorEdge"];
48  coolDz = nArgs["CoolDz"];
49  coolWidth = nArgs["CoolWidth"];
50  coolSide = nArgs["CoolSide"];
51  coolThick = nArgs["CoolThick"];
52  coolZ = nArgs["CoolZ"];
53  coolNumber = int(nArgs["CoolNumber"]);
54  hybridThick = nArgs["HybridThick"];
55  moduleRadius = nArgs["ModuleRadius"];
56  coolMat = sArgs["CoolMaterial"];
57  tubeMat = sArgs["CoolTubeMaterial"];
58  ladderNameUp = sArgs["LadderNameUp"];
59  ladderNameDown = sArgs["LadderNameDown"];
60  ladderWidth = nArgs["LadderWidth"];
61  ladderThick = nArgs["LadderThick"];
62  module_offset = nArgs["ModuleOffset"];
63  layout = int(nArgs["LayoutType"]);
64  activeWidth = nArgs["ActiveWidth"];
65 
66 // Debug messages
67  //std::cout <<"\nStack sensor with sensorEdge = "<<sensorEdge<<"\tand width = "<<activeWidth<<"\t at R = "<<moduleRadius;
68  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo debug: Parent " << parentName
69  << " NameSpace " << idNameSpace << "\n"
70  << "\tLadders " << number << "\tGeneral Material "
71  << VolumeMaterial << "\tLength " << layerDz << "\tSensorEdge "
72  << sensorEdge << "\tSpecification of Cooling Pieces:\n"
73  << "\tLength " << coolDz << " Width " << coolWidth
74  << " Side " << coolSide << " Thickness of Shell "
75  << coolThick << " Radial distance " << moduleRadius
76  << " Materials " << coolMat << ", " << tubeMat;
77 
78  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo debug: Ladder "
79  << ladderNameUp << " width/thickness " << ladderWidth
80  << ", " << ladderThick;
81 }
82 
83 
85 // The algorithm itself
87  if ((number%2==1)&&(layout==1)) {
88  number+=1;
89  std::cout << "\nAsking for an invalid layout ... Adjusting the number of ladders to compensate.\n";
90  }
91  // Keep a running tally to check that there are no phi gaps.
92  double phi_coverage = 0.0; // Running total of Phi coverage
93  bool covered=0; // Set to 1 when there is at least 2Pi of coverage in phi
94  double dphi = CLHEP::twopi/number; // Phi difference between successive ladders
95  double phi_offset = module_offset; // Phi rotation of the ladders
96  double radius_offset = 0.0; // Distance from <R> that the stacks are shifted in or out
97  double deltaX, deltaY; // Offset to correct for ladder thickness
98  double deltaX2, deltaY2; // Offset for cooling tube 2
99  double r_vol_inner = 0.0; // Define the cylinder that the stacks are in
100  double r_vol_outer = 0.0; //
101  double phi_coverage_pinn =0.0; // phi coverage, phi_coverage_pinn = phi_left + phi_right
102  double phi_left = 0.0; //
103  double phi_right = 0.0; //
104 
105 
106  // Set parameters for the Phi Rotated Stacks as default
107  double d1 = (ladderThick)*tan(phi_offset);
108  double d2 = (ladderThick)/cos(phi_offset);
109  double d3 = (moduleRadius+d2);
110  double d4 = ((activeWidth/2.0)-d1);
111  double r_right = sqrt( d3*d3 + d4*d4 + 2*d3*d4*sin(phi_offset)) ; // Radius of the outer edge of the active area
112  phi_right=acos( (r_right*r_right + d3*d3 - d4*d4)/
113  (2*d3*r_right)
114  );
115  double d5 = sqrt(d1*d1+d2*d2);
116  double d6 = (moduleRadius-d5);
117  double r_left = sqrt ( d4*d4 + d6*d6 - 2*d4*d6*sin(phi_offset) ) ; // Radius of the inner edge of the active area
118  phi_left=acos( (r_left*r_left + d6*d6 - d4*d4)/
119  (2*d6*r_left)
120  );
121  if (r_right> r_left ) {r_vol_outer=r_right;r_vol_inner=r_left;}
122  if (r_left > r_right) {r_vol_outer=r_left;r_vol_inner=r_right;}
123 
124  phi_coverage_pinn=phi_left+phi_right;
125  //std::cout << "\nDetermining the radii, r_in="<<r_vol_inner <<" mod_R="<<moduleRadius<<" r_out="<<r_vol_outer;
126  // Set parameters if High-Low Stacks are requested
127  if(layout) {
128  phi_offset = 0.0;
129  phi_coverage_pinn = 0.0; // Determin for each ladder when placed
130  double R_Curvature = ((4*moduleRadius*moduleRadius)+(ladderWidth*ladderWidth/4))/(4*moduleRadius); // The radius of the ends of the inner stack
131  double r2 = (R_Curvature+ladderThick);
132  double r1 = sqrt((R_Curvature*R_Curvature)-(ladderWidth*ladderWidth/4.0))-(ladderThick);
133 
134  radius_offset = (r1-r2)/2.0;
135  r_vol_inner = r1-(ladderThick);
136  r_vol_outer = sqrt((ladderWidth*ladderWidth/4.0)+((r2+ladderThick)*(r2+ladderThick)));
137  // phi_left and phi_right depend on R so they will be determined later
138  // std::cout << "\nDetermining the radii, r_in="<<r_vol_inner <<" r1="<<r1<< " R_c="<<R_Curvature<<" r2="<<r2<<" r_out="<<r_vol_outer;
139  }
140 
141  double r_vol_innerT;
142  if(r_vol_inner>r_vol_outer) {
143  r_vol_innerT=r_vol_inner;
144  r_vol_inner=r_vol_outer-30;
145  r_vol_outer=r_vol_innerT+30;
146  }
147 
149 
150  int component_copy_no=1;
151  double phi0 = 90*CLHEP::deg;
152  double phi =0*CLHEP::deg;
153  double phix=0*CLHEP::deg;
154  double phiy=0*CLHEP::deg;
155  DDTranslation tran;
156  DDRotation rot;
157 
158 
159  //std::cout << "\nDDPixBarTPGStackLayerAlgo test: r_mid_L_inner/r_mid_L_outer " << r_vol_inner << ", " << r_vol_outer ;
160  //<< " d1/d2 " << d1 << ", " << d2
161  //<< " x1/x2 " << x1 << ", " << x2;
162 
163 
164 //------------------------------------------------------------------------------------------------------------
165 // Define the volume in which the layer exists
166 
167  DDName mother = parent().name();
168  std::string idName = DDSplit(mother).first;
169 
170  DDSolid solid = DDSolidFactory::tubs(DDName(idName, idNameSpace), 0.5*layerDz, r_vol_inner, r_vol_outer, 0, CLHEP::twopi);
171 
173  DDMaterial matter(matname);
174  DDLogicalPart layer(solid.ddname(), matter, solid);
175 
176  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: "
177  << DDName(idName, idNameSpace) << " Tubs made of "
178  << VolumeMaterial << " from 0 to " << CLHEP::twopi/CLHEP::deg
179  << " with Rin " << r_vol_inner << " Rout " << r_vol_outer
180  << " ZHalf " << 0.5*layerDz;
181 
182 //------------------------------------------------------------------------------------------------------------
183 // Define the cool tube
184 
185  name = idName + "CoolTube";
186  solid = DDSolidFactory::trap(DDName(name,idNameSpace), 0.5*coolDz, 0, 0, coolWidth/2, coolSide/2, coolSide/2, 0, coolWidth/2, coolSide/2, coolSide/2, 0);
187 
188  matter = DDMaterial(DDName(DDSplit(tubeMat).first, DDSplit(tubeMat).second));
189  DDLogicalPart coolTube(solid.ddname(), matter, solid);
190 
191  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " <<solid.name()
192  << " Trap made of " << tubeMat << " of dimensions "
193  << 0.5*coolDz << ", 0, 0, " << coolWidth/2 << ", " << coolSide/2
194  << ", " << coolSide/2 << ", 0, " << coolWidth/2 << ", " << coolSide/2 << ", "
195  << coolSide/2 << ", 0";
196 
197 
198 //------------------------------------------------------------------------------------------------------------
199 // Define the coolant within the cool tube = same as cooltube - wall thickness
200 
201  name = idName + "Coolant";
202 
204  matter = DDMaterial(DDName(DDSplit(coolMat).first, DDSplit(coolMat).second));
205  DDLogicalPart cool(solid.ddname(), matter, solid);
206 
207  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " <<solid.name()
208  << " Trap made of " << tubeMat << " of dimensions "
209  << 0.5*coolDz << ", 0, 0, " << coolWidth/2-coolThick << ", " << coolSide/2-coolThick
210  << ", " << coolSide/2-coolThick << ", 0, " << coolWidth/2-coolThick << ", " << coolSide/2-coolThick << ", "
211  << coolSide/2-coolThick << ", 0";
212 
213 
214 //------------------------------------------------------------------------------------------------------------
215 // Put coolant in the cool tube
216 
217  cpv.position (cool, coolTube, 1, DDTranslation(0.0, 0.0, 0.0), DDRotation());
218 
219  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " << cool.name()
220  << " number 1 positioned in " << coolTube.name()
221  << " at (0,0,0) with no rotation";
222 
223 //------------------------------------------------------------------------------------------------------------
224 // Define the ladder
225 
226  DDName ladderFullUp(DDSplit(ladderNameUp).first, DDSplit(ladderNameUp).second);
227  DDName ladderFullDown(DDSplit(ladderNameDown).first, DDSplit(ladderNameDown).second);
228 
229 //------------------------------------------------------------------------------------------------------------
230 
231 
232 // Iterate over the number of modules
233 
234  for (int i=0; i<number; i++) {
235 
236  double phi_coverage_i=0.0;
237  // First the modules
238  phi = phi0 + i*dphi;
239  phix = phi + (90*CLHEP::deg) - phi_offset ;
240  phiy = phix + (90*CLHEP::deg) ;
241 
242  deltaX= 0.5*ladderThick*cos(phi-phi_offset);
243  deltaY= 0.5*ladderThick*sin(phi-phi_offset);
244 
245  double radius;
246  if((i%2)==0) radius=moduleRadius-radius_offset;
247  else radius=moduleRadius+radius_offset;
248 
249  //inner layer of stack
250  tran = DDTranslation(radius*cos(phi)-deltaX, radius*sin(phi)-deltaY, 0);
251  name = idName + dbl_to_string(component_copy_no);
252  rot = DDrot(DDName(name,idNameSpace), 90*CLHEP::deg, phix, 90*CLHEP::deg, phiy, 0.,0.);
253 
254  cpv.position (ladderFullDown, layer, component_copy_no, tran, rot);
255 
256  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " << ladderFullDown
257  << " number " << component_copy_no
258  << " positioned in " << layer.name()
259  << " at " << tran
260  << " with " << rot;
261  component_copy_no++;
262 
263 
264  //outer layer of stack
265  tran = DDTranslation(radius*cos(phi)+deltaX, radius*sin(phi)+deltaY, 0);
266  name = idName + dbl_to_string(component_copy_no);
267  rot = DDrot(DDName(name,idNameSpace), 90*CLHEP::deg, phix, 90*CLHEP::deg, phiy, 0.,0.);
268 
269  cpv.position (ladderFullUp, layer, component_copy_no, tran, rot);
270 
271  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " << ladderFullUp
272  << " number " << component_copy_no
273  << " positioned in " << layer.name()
274  << " at " << tran
275  << " with " << rot;
276  component_copy_no++;
277  // Running total of phi coverage
278  phi_coverage_i=phi_coverage_pinn;
279  if(layout) {
280  phi_coverage_i=2*atan2((activeWidth/2.0),(radius+ladderThick));
281  }
282 
283  phi_coverage += phi_coverage_i;
284  //std::cout<<"\nLooking at phi = "<< phi<<"\tNumber "<<component_copy_no-1<<"\t with "<<phi_coverage_i<<"\trad of coverage for a total coverage of "<<phi_coverage;
285  if (phi_coverage>CLHEP::twopi&&covered==0) {
286  //std::cout<<"\nPhi coverage is achieved after "<<(component_copy_no-1)/2.0<<" ladders for R="<<radius/10.0<<" cm.\t and "<<number<<" ladders were asked for";
287  covered=1;
288  }
289 
290 
291  }
292  //std::cout<<"\nLayer covered "<<phi_coverage<<" radians in phi. (2Pi="<<CLHEP::twopi<<")";
293  if (phi_coverage<CLHEP::twopi) { throw cms::Exception("DDPixBarTPGStackLayerAlgo")
294  <<"\nAsking for a Geometry with gaps in phi.\n";}
295 
296 // Iterate over the number of ladders (now 2 cooltubes per ladder)
297 
298  DDTranslation tran2;
299  double coolOffset = 0.5*ladderWidth - hybridThick - 0.5*coolSide;
300  double coolOffset2 = -0.5*ladderWidth + 0.5*coolSide;
301 
302  for (int i=0; i<number; i++) {
303  phi = phi0 + i*dphi;
304  phix = phi + (90*CLHEP::deg) - phi_offset;
305  phiy = phix + (90*CLHEP::deg) ;
306 
307  deltaX= coolOffset*cos(90*CLHEP::deg-phi+phi_offset);
308  deltaY= coolOffset*sin(90*CLHEP::deg-phi+phi_offset);
309  deltaX2= coolOffset2*cos(90*CLHEP::deg-phi+phi_offset);
310  deltaY2= coolOffset2*sin(90*CLHEP::deg-phi+phi_offset);
311 
312  double radius;
313  if((i%2)==0) radius=moduleRadius-radius_offset;
314  else radius=moduleRadius+radius_offset;
315 
316  tran = DDTranslation(radius*cos(phi)-deltaX, radius*sin(phi)+deltaY, coolZ);
317  tran2 = DDTranslation(radius*cos(phi)-deltaX2, radius*sin(phi)+deltaY2, coolZ);
318 
319  name = idName + "xxx"+dbl_to_string(i+10000);
320 
321  rot = DDrot(DDName(name,idNameSpace), 90*CLHEP::deg, phix, 90*CLHEP::deg, phiy, 0.,0.);
322  cpv.position (coolTube, layer, i*2+1, tran, rot);
323  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " << coolTube.name()
324  << " number " << i*2+1 << " positioned in "
325  << layer.name() << " at " << tran << " with "<< rot;
326  cpv.position (coolTube, layer, i*2+2, tran2, rot);
327  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " << coolTube.name()
328  << " number " << i*2+2 << " positioned in "
329  << layer.name() << " at " << tran2 << " with "<< rot;
330  // check if ring layer and need cooling tubes on both sides
331  if(coolNumber == 2) {
332  tran = DDTranslation(radius*cos(phi)-deltaX, radius*sin(phi)+deltaY, -coolZ);
333  tran2 = DDTranslation(radius*cos(phi)-deltaX2, radius*sin(phi)+deltaY2, -coolZ);
334 
335  name = idName + "xxx2"+dbl_to_string(i+10000);
336 
337  rot = DDrot(DDName(name,idNameSpace), 90*CLHEP::deg, phix, 90*CLHEP::deg, phiy, 0.,0.);
338  cpv.position (coolTube, layer, number*2+i*2+1, tran, rot);
339  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " << coolTube.name()
340  << " number " << number*2+i*2+1 << " positioned in "
341  << layer.name() << " at " << tran << " with "<< rot;
342  cpv.position (coolTube, layer, number*2+i*2+2, tran2, rot);
343  LogDebug("PixelGeom") << "DDPixBarTPGStackLayerAlgo test: " << coolTube.name()
344  << " number " << number*2+i*2+2 << " positioned in "
345  << layer.name() << " at " << tran2 << " with "<< rot;
346  }
347  }
348 
349 
350  // End algorithm
351 }
#define LogDebug(id)
int i
Definition: DBlmapReader.cc:9
const N & name() const
Definition: DDBase.h:78
list parent
Definition: dbtoconf.py:74
DDMaterial is used to define and access material information.
Definition: DDMaterial.h:41
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
void initialize(const DDNumericArguments &nArgs, const DDVectorArguments &vArgs, const DDMapArguments &mArgs, const DDStringArguments &sArgs, const DDStringVectorArguments &vsArgs)
void position(const DDLogicalPart &self, const DDLogicalPart &parent, std::string copyno, const DDTranslation &trans, const DDRotation &rot, const DDDivision *div=NULL)
DDName is used to identify DDD entities uniquely.
Definition: DDName.h:14
static std::string & ns()
std::string dbl_to_string(const double &in)
Converts only the integer part of a double to a string.
Definition: DDutils.cc:12
type of data representation of DDCompactView
Definition: DDCompactView.h:77
A DDSolid represents the shape of a part.
Definition: DDSolid.h:35
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > DDTranslation
Definition: DDTranslation.h:7
Represents a uniquely identifyable rotation matrix.
Definition: DDTransform.h:66
U second(std::pair< T, U > const &p)
T sqrt(T t)
Definition: SSEVec.h:48
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Tan< T >::type tan(const T &t)
Definition: Tan.h:22
A DDLogicalPart aggregates information concerning material, solid and sensitveness ...
Definition: DDLogicalPart.h:88
static DDSolid tubs(const DDName &name, double zhalf, double rIn, double rOut, double startPhi, double deltaPhi)
Definition: DDSolid.cc:788
static DDSolid trap(const DDName &name, double pDz, double pTheta, double pPhi, double pDy1, double pDx1, double pDx2, double pAlp1, double pDy2, double pDx3, double pDx4, double pAlp2)
Definition: DDSolid.cc:723
DDRotation DDrot(const DDName &name, DDRotationMatrix *rot)
Definition of a uniquely identifiable rotation matrix named by DDName name.
Definition: DDRotation.cc:90
void execute(DDCompactView &cpv)
tuple cout
Definition: gather_cfg.py:121
std::pair< std::string, std::string > DDSplit(const std::string &n)
split into (name,namespace), separator = &#39;:&#39;
Definition: DDSplit.cc:4
const std::string & name() const
Returns the name.
Definition: DDName.cc:87
const N & ddname() const
Definition: DDBase.h:80