EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EICG4LumiDetector.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EICG4LumiDetector.cc
1 //____________________________________________________________________________..
2 //
3 // Far-Backward detector class
4 // includes: Luminosity exit window, direct photon CAL, e+e- conversion CAL,
5 // electron taggers
6 //
7 // Written by Dhevan Gangadharan, Aranya Giri
8 // Based on designs from Jaroslav Adam and Zhiwan Xu
9 //
10 // template generated by CreateG4Subsystem.pl
11 //____________________________________________________________________________..
12 
13 #include "EICG4LumiDetector.h"
14 
15 
16 #include <phparameter/PHParameters.h>
17 
18 #include <g4main/PHG4Detector.h>
19 #include <g4main/PHG4DisplayAction.h> // for PHG4DisplayAction
20 #include <g4main/PHG4Subsystem.h>
21 
22 #include <Geant4/G4Color.hh>
23 #include <Geant4/G4Box.hh>
24 #include <Geant4/G4LogicalVolume.hh>
25 #include <Geant4/G4Material.hh>
26 #include <Geant4/G4PVPlacement.hh>
27 #include <Geant4/G4SubtractionSolid.hh>
28 #include <Geant4/G4SystemOfUnits.hh>
29 #include <Geant4/G4Tubs.hh>
30 #include <Geant4/G4Box.hh>
31 #include <Geant4/G4Para.hh>
32 #include <Geant4/G4RotationMatrix.hh>
33 #include <Geant4/G4SystemOfUnits.hh>
34 #include <Geant4/G4ThreeVector.hh> // for G4ThreeVector
35 #include <Geant4/G4Transform3D.hh> // for G4Transform3D
36 #include <Geant4/G4Types.hh> // for G4double, G4int
37 #include <Geant4/G4VPhysicalVolume.hh> // for G4VPhysicalVolume
38 #include <TSystem.h>
39 #include <Geant4/G4UnionSolid.hh>
40 #include <Geant4/G4VisAttributes.hh>
41 #include <Geant4/G4TwoVector.hh>
42 #include <Geant4/G4ExtrudedSolid.hh>
43 #include <Geant4/G4Trd.hh>
44 
45 
46 #include <phool/recoConsts.h> //For rc WorldMaterial
47 
48 #include <cmath>
49 #include <iostream>
50 #include <cstdlib>
51 #include <fstream>
52 #include <sstream>
53 #include <utility>
54 //#include <stdio>
55 #include <TMath.h>
56 
57 //#include <Geant4/G4Trap.h>
58 
59 class G4VSolid;
60 class PHCompositeNode;
61 
62 using namespace std;
63 
64 //____________________________________________________________________________..
66  PHCompositeNode *Node,
68  const std::string &dnam, const int lyr)
69  : PHG4Detector(subsys, Node, dnam)
70  , m_Params(parameters)
71  , m_Layer(lyr)
72  , m_Name("Lumi")
73 {
74 }
75 
76 int EICG4LumiDetector::IsInDetector(G4VPhysicalVolume *volume) const
77 {
78 
79  if( m_ActivePhysicalVolumesSet.find( volume ) != m_ActivePhysicalVolumesSet.end() )
80  {
81  return 1;
82  }
83 
84  return 0;
85 
86 }
87 
88 //_______________________________________________________________
89 int EICG4LumiDetector::IsInVirtualDetector(G4VPhysicalVolume *volume) const
90 {
91 
92  if( m_VirtualPhysicalVolumesMap.find( volume ) != m_VirtualPhysicalVolumesMap.end() )
93  {
94  return 1;
95  }
96  return 0;
97 
98 }
99 
100 //_______________________________________________________________
101 int EICG4LumiDetector::GetDetId(G4VPhysicalVolume *volume) const
102 {
103 
104  if (IsInDetector(volume))
105  {
106  return 1;
107  }
108 
109  return -1;
110 }
111 
112 //_______________________________________________________________
113 void EICG4LumiDetector::ConstructMe(G4LogicalVolume *logicWorld)
114 {
115  //begin implement your own here://
116  // Do not forget to multiply the parameters with their respe Gctive CLHEP/G4 unit !
117  if (Verbosity() > 0)
118  {
119  std::cout << "EICG4LumiDetector: Begin Construction" << std::endl;
120  }
121 
122  //________________________________________PARAMETER INITIALISATION__________________________________________________________
123 
124  double enclosureCenter = m_Params->get_double_param( "FBenclosure_center" ) * cm;
125 
126  // Version # of the Luminosity Monitor Design.
127  int Version = m_Params->get_int_param( "Version" );
128 
129  // Primary Lumi Exit Window
130  double LumiWin_X = m_Params->get_double_param( "LumiWin_X" ) * cm;
131  double LumiWin_Y = m_Params->get_double_param( "LumiWin_Y" ) * cm;
132  double LumiWin_Z = m_Params->get_double_param( "LumiWin_Z" ) * cm - enclosureCenter;
133  double LumiWin_Tilt = m_Params->get_double_param( "LumiWin_Tilt" ) * rad;
134  double LumiWin_Thickness = m_Params->get_double_param( "LumiWin_Thickness" ) * cm;
135  double LumiWin_Height = m_Params->get_double_param( "LumiWin_Height" ) * cm;
136  double LumiWin_Length = m_Params->get_double_param( "LumiWin_Length" ) * cm;
137 
138  // Spectrometer dipole magnet
139  double LumiMag_Z = m_Params->get_double_param( "LumiMag_Z" ) * cm - enclosureCenter;
140  double LumiMag_inner = m_Params->get_double_param( "LumiMag_innerR" ) * cm;
141  double LumiMag_outer = m_Params->get_double_param( "LumiMag_outerR" ) * cm;
142  double LumiMag_DZ = m_Params->get_double_param( "LumiMag_DZ" ) * cm;
143  double LumiMag_B = m_Params->get_double_param( "LumiMag_B" ) * tesla;
144 
145  double LumiSpec_Z = m_Params->get_double_param( "LumiSpec_Z" ) * cm - enclosureCenter;
146  //double LumiSpec_XY = m_Params->get_double_param( "LumiSpec_XY" ) * cm;
147  //double LumiPhotonCAL_Z = m_Params->get_double_param( "LumiPhotonCAL_Z" ) * cm - enclosureCenter;
148  double LumiPhotonCAL_XY = m_Params->get_double_param( "LumiPhotonCAL_XY" ) * cm;
149 
150  // Lumi ee Spectrometer single tower (Calorimeter) dimensions
151  double LumiSpecTower_XY = m_Params->get_double_param( "LumiSpecTower_XY" ) * cm;
152  double LumiSpecTower_DZ = m_Params->get_double_param( "LumiSpecTower_DZ" ) * cm;
153  int TotalLumiSpecTower = m_Params->get_int_param( "TotalLumiSpecTower" );
154 
155  // Tracker1 Details
156  //double LumiTracker1Gap = m_Params->get_double_param( "LumiTracker1Gap" ) * cm; //Collimator dy dimension.
157 
158  // Tracker2 Details
159  double LumiTracker2_XY = m_Params->get_double_param( "LumiTracker2_XY" ) * cm;
160  double LumiTracker2_DZ = m_Params->get_double_param( "LumiTracker2_DZ" ) * cm;
161 
162  // LumiWin_Thickness*factor for different exit window versions.
163  double factorV1 = 1.0;
164  double factorV2 = 1.0;
165  double factorV3 = 1.0;
166 
167  // Initialisation of diff. volume region.
168  std::string LumiWin_Material = m_Params->get_string_param( "LumiWin_Material" );
169  std::string LumiMag_VesselMaterial = m_Params->get_string_param( "LumiMag_VesselMaterial" );
170 
171  std::string TrianTrapMaterial = "G4_AIR";
172  std::string CuboidMaterial = "G4_AIR";
173  std::string MagCoreMaterial = "G4_AIR";
174  std::string RecConeMaterial = "G4_AIR";
175  std::string ExitWinV2Material = "G4_AIR";
176  std::string ExitWinV3Material = "G4_AIR";
177  //std::string MidConvMaterial = "G4_AIR";
178 
179  //Change the material according to Version.
180  switch(Version){
181 
182  case 1: //No change in material def.
183  break;
184 
185  case 2: TrianTrapMaterial = "G4_Galactic";
186  CuboidMaterial = "G4_Galactic";
187  MagCoreMaterial = "G4_Galactic";
188  //MidConvMaterial = LumiWin_Material;
189  ExitWinV2Material = LumiWin_Material;
190  factorV1 = 0.1;
191  break;
192 
193  case 3: TrianTrapMaterial = "G4_Galactic";
194  CuboidMaterial = "G4_Galactic";
195  MagCoreMaterial = "G4_Galactic";
196  RecConeMaterial = "G4_Galactic";
197  ExitWinV2Material = "G4_Galactic";
198  //MidConvMaterial = LumiWin_Material;
199  ExitWinV3Material = LumiWin_Material;
200  factorV1 = 0.1;
201  break;
202 
203  default : std::cout<<"WRONG CHOICE (ONLY 1, 2 & 3)"<<endl;
204  break;
205 
206  }
207 
208  // sizes and positions (in mother volume coordinates)
209  // Main Lumi Window
210  G4ThreeVector size_lw = G4ThreeVector( LumiWin_Length, LumiWin_Height, factorV1*LumiWin_Thickness ); //thickness is factorised A/Version 1
211  G4ThreeVector pos_lw = G4ThreeVector( LumiWin_X, LumiWin_Y, LumiWin_Z );
212 
213  // Outer Vessel
214  G4ThreeVector size_ov = G4ThreeVector( LumiMag_inner, LumiMag_outer, LumiMag_DZ ); //x - inner radius, y - outer radius and z - length of cylinder vessel.
215  G4ThreeVector pos_ov = G4ThreeVector( LumiWin_X, LumiWin_Y, LumiMag_Z ); //same axis as the lumi window.
216 
217  // Spectrometer Magnet Core
218  G4ThreeVector size_mc = G4ThreeVector( 0., LumiMag_inner, LumiMag_DZ ); //x - inner radius, y - outer radius and z - length of cylindrical core.
219 
220  // Exit Windows for V2 and V3
221  // thickness is factorised
222  G4ThreeVector size_ewV2 = G4ThreeVector( LumiWin_Length, LumiWin_Height, factorV2*LumiWin_Thickness );
223  G4ThreeVector size_ewV3 = G4ThreeVector( LumiWin_Length, LumiWin_Height, factorV3*LumiWin_Thickness );
224 
225  // Spectrometer Tracker 2
226  G4ThreeVector size_tr2 = G4ThreeVector( LumiTracker2_XY, LumiTracker2_XY, LumiTracker2_DZ );
227  G4ThreeVector pos_tr2 = G4ThreeVector( LumiWin_X, pos_lw.y() + LumiPhotonCAL_XY/2.0 + size_tr2.y()/2.0 + 0.01*cm,
228  LumiSpec_Z + LumiSpecTower_DZ/2.0 + LumiWin_Thickness + LumiTracker2_DZ/2.0 ); //tracker 2 pos
229 
230  // Spectrometer Tracker 1
231  double LumiTracker1_XY = pos_tr2.y() - size_ewV2.y()/2.;
232  G4ThreeVector size_tr1 = G4ThreeVector( LumiTracker1_XY, LumiTracker1_XY, LumiTracker2_DZ );
233 
234  // Spectrometer Towers
235  G4ThreeVector size_st = G4ThreeVector(
236  TotalLumiSpecTower*LumiSpecTower_XY, TotalLumiSpecTower*LumiSpecTower_XY, LumiSpecTower_DZ );
237 
238  //
239  double dz_tr2_daughter = -1*pos_tr2.z() - (-1*pos_ov.z() + size_ov.z()/2.0);
240  G4ThreeVector pos_ewV2_daughter = G4ThreeVector( 0.0, 0.0, dz_tr2_daughter/2.0 - size_ewV2.z()/2.0);
241 
242  G4ThreeVector pos_tr2_top = G4ThreeVector( 0.0, LumiPhotonCAL_XY/2.0 + size_tr2.y()/2.0,
243  -1*(dz_tr2_daughter/2.0) + size_tr2.z()/2.0 ); //tracker2 pos in recCone;
244  G4ThreeVector pos_tr2_bot = G4ThreeVector( pos_tr2_top.x(), -1*pos_tr2_top.y(), pos_tr2_top.z() );
245 
246  G4ThreeVector pos_tr1_top = G4ThreeVector( 0.0, pos_tr2.y()/2.0, 0.0 ); //tracker 1 position in RecCone.
247  G4ThreeVector pos_tr1_bot = G4ThreeVector( pos_tr1_top.x() , -1*pos_tr1_top.y(), pos_tr1_top.z() );
248 
249  //-------------------------------------------------------
250  // Add Components of Lumi Detector
251  // magnet core material may be Air or Galactic depending on Version
252  AddLumiWindow( size_lw, pos_lw, LumiWin_Tilt, LumiWin_Material, logicWorld);
253  AddTriangularTrapezoid( size_lw, pos_lw, LumiWin_Tilt, TrianTrapMaterial, logicWorld);
254  AddCuboid( size_lw, pos_lw, size_ov, pos_ov, LumiWin_Tilt, CuboidMaterial, logicWorld);
255  AddLumiMag_OuterVessel( size_ov, pos_ov, LumiMag_VesselMaterial, logicWorld);
256  AddLumiMag_MagCore( size_mc, pos_ov, LumiMag_B, MagCoreMaterial, logicWorld);
257 
258  // sub-mother volume for trackers and V2/V3 exit windows
259  G4LogicalVolume* logicRecCone = AddRecCone( size_lw, pos_lw, size_ov, pos_ov,
260  size_tr2, pos_tr2, LumiWin_Tilt, RecConeMaterial, logicWorld );
261 
262  AddExitWindowForV2( size_ewV2, pos_ewV2_daughter, LumiWin_Tilt, ExitWinV2Material, logicRecCone );
263 
264  //-------------------------------------------------------
265  // Spectrometer Trackers
266  AddLumiTracker( "TopSpecTracker1", 0, size_tr1, pos_tr1_top, logicRecCone);
267  AddLumiTracker( "BotSpecTracker1", 1, size_tr1, pos_tr1_bot, logicRecCone);
268  AddLumiTracker( "TopSpecTracker2", 2, size_tr2, pos_tr2_top, logicRecCone);
269  AddLumiTracker( "BotSpecTracker2", 3, size_tr2, pos_tr2_bot, logicRecCone);
270 
271  AddExitWindowForV3( size_ewV3, pos_lw, size_tr2, pos_tr2, ExitWinV3Material, logicWorld );
272 
273  //-------------------------------------------------------
274  // Spectrometer Calorimeter Towers
275  AddCAL( "TopSpecTower", size_st, G4ThreeVector(LumiWin_X, pos_tr2.y(), LumiSpec_Z), TotalLumiSpecTower, logicWorld );
276  AddCAL( "BotSpecTower", size_st, G4ThreeVector(LumiWin_X, -1*pos_tr2.y(), LumiSpec_Z), TotalLumiSpecTower, logicWorld );
277 
278  return;
279 }
280 
281 //_______________________________________________________________
282 void EICG4LumiDetector::Print(const std::string &what) const
283 {
284  std::cout << "EICG4Lumi Detector:" << std::endl;
285  if (what == "ALL" || what == "VOLUME")
286  {
287  std::cout << "Version 0.1" << std::endl;
288  std::cout << "Parameters:" << std::endl;
289  m_Params->Print();
290  }
291  return;
292 }
293 
294 //______________________________________________________________
295 
297 {
298  return m_Params;
299 }
300 
301 //_____________________________________________________________________________________________________________________________________________
302 void EICG4LumiDetector::AddLumiWindow(G4ThreeVector size, G4ThreeVector pos, double angle, std::string material, G4LogicalVolume *logicWorld){
303 
304  std::string name = "LumiWindow";
305  G4Box *solid = new G4Box(name + "_solid", (size.x()/2.0) + 0.3*cm, size.y()/2.0, size.z()/2.0 );
306  //G4Para *solid = new G4Para(name + "_solid", size.x()/2.0, size.y()/2.0, factor*(size.z()/2.0) , angle , angle , 0.);
307 
308  G4LogicalVolume *logical = new G4LogicalVolume( solid, GetDetectorMaterial(material), name + "_logical");
309  G4VisAttributes *vis = new G4VisAttributes( G4Color(1, 0, 0, 1) );
310  vis->SetForceSolid( true );
311  logical->SetVisAttributes(vis);
312 
313  G4ThreeVector rot_axis = G4ThreeVector(0,1,0); //Y-axis
314  G4RotationMatrix *rot_matrix = new G4RotationMatrix(rot_axis , angle); //is typedef to CLHEP::HepRotation
315  //G4ThreeVector pos_new = G4ThreeVector(pos.x() - (size.z()/(2.0*TMath::Sin(angle))), pos.y() , pos.z() );
316  G4ThreeVector pos_new = G4ThreeVector(pos.x() - (size.z()/(2.0*TMath::Sin(angle)) ), pos.y(), pos.z() );
317  G4VPhysicalVolume *physical = new G4PVPlacement(rot_matrix, pos_new, logical, name+"_physical", logicWorld, 0, false, OverlapCheck());
318  //G4VPhysicalVolume *physical = new G4PVPlacement(0, pos, logical, name+"_physical", logicWorld, 0, false, OverlapCheck());
319 
320  m_PassivePhysicalVolumesSet.insert( physical );
321 
322 }
323 
324 //_____________________________________________________________________________________________________________________________________________
325 G4ThreeVector EICG4LumiDetector::AddLumiExitWindow(G4ThreeVector size, G4ThreeVector pos, double factor, double angle, std::string material, G4LogicalVolume *logicWorld){
326 
327  std::string name = "LumiExitWindow";
328 
329  //G4Box *solid = new G4Box(name + "_solid", size.x()/2.0, size.y()/2.0, factor*size.z()/2.0);
330  //G4Para *solid = new G4Para(name + "_solid", size.x()/2.0, size.y()/2.0, factor*(size.z()/2.0) - 0.01*cm, angle, angle, 0);
331  G4Box *solid = new G4Box(name + "_solid", size.x(), size.y(), size.z());
332 
333  G4LogicalVolume *logical = new G4LogicalVolume( solid, GetDetectorMaterial(material), name + "_logical");
334  G4VisAttributes *vis = new G4VisAttributes( G4Color(0, 1, 0, 1) );
335  vis->SetForceSolid( true );
336  logical->SetVisAttributes(vis);
337 
338  G4ThreeVector rot_axis = G4ThreeVector(0,1,0); //Y-axis
339  G4RotationMatrix *rot_matrix = new G4RotationMatrix(rot_axis , angle); //is typedef to CLHEP::HepRotation
340  G4ThreeVector pos_new = G4ThreeVector(pos.x(), pos.y(), pos.z() - size.z() - factor);
341  G4VPhysicalVolume *physical = new G4PVPlacement(rot_matrix, pos_new, logical, name+"_physical", logicWorld, 0, false, OverlapCheck());
342  m_PassivePhysicalVolumesSet.insert( physical );
343 
344  return pos_new;
345 
346 }
347 
348 //________________________________________________________________________________________________________________________________________
349 void EICG4LumiDetector::AddLumiMag_OuterVessel( G4ThreeVector size, G4ThreeVector pos, std::string material, G4LogicalVolume *logicWorld)
350 {
351  std::string name = "LumiMag_OuterVessel";
352 
353  //x - inner radius, y- outer radius and z - length of tube. Theta coverage 0 - 360 deg
354  G4Tubs *solid = new G4Tubs(name+"_solid", size.x(), size.y(), size.z()/2., 0., 360.*deg);
355 
356  G4LogicalVolume *logical = new G4LogicalVolume(solid, GetDetectorMaterial(material), name+"_logical");
357  G4VisAttributes *vis = new G4VisAttributes( G4Color(0, 1, 0, 0.5) );
358  vis->SetForceSolid( true );
359  logical->SetVisAttributes( vis );
360 
361  G4VPhysicalVolume *physical = new G4PVPlacement( 0, pos, logical, name+"_physical", logicWorld, 0, false, OverlapCheck() );
362  m_PassivePhysicalVolumesSet.insert( physical);
363 
364 }
365 
366 //______________________________________________________________________________________________________________________________________________
367 void EICG4LumiDetector::AddLumiMag_MagCore(G4ThreeVector size, G4ThreeVector pos, double Bx, std::string material, G4LogicalVolume *logicWorld)
368 {
369  std::string name = "LumiMag_MagCore";
370 
371  // x - inner radius, y - outer radius, z - length of the cylindrical core. Theta coverage 0- 360 deg
372  G4Tubs *solid = new G4Tubs(name, size.x(), size.y() - 0.01*cm, size.z()/2.0, 0., 360.*deg);
373 
374  G4LogicalVolume *logical = new G4LogicalVolume( solid, GetDetectorMaterial(material), name);
375  logical->SetVisAttributes( G4VisAttributes::GetInvisible() );
376 
377  G4UniformMagField *field = new G4UniformMagField( G4ThreeVector(Bx, 0, 0 ) ); //Mag field stregth along x-direction
378  G4FieldManager *fman = new G4FieldManager();
379  fman->SetDetectorField( field );
380  fman->CreateChordFinder( field );
381  logical->SetFieldManager(fman, true);
382 
383  G4VPhysicalVolume *physical = new G4PVPlacement( 0, pos, logical, name, logicWorld, 0, false, OverlapCheck() );
384  m_PassivePhysicalVolumesSet.insert( physical);
385 
386  //return logical;
387 }
388 
389 //______________________________________________________________________________________________________________________________________________
390 void EICG4LumiDetector::AddTriangularTrapezoid(G4ThreeVector size, G4ThreeVector pos, double angle, std::string material, G4LogicalVolume *logicWorld)
391 {
392  // Construct the triangle in x-y plane, extrude in the z-axis and finally rotate it by -90 deg via x -axis.
393 
394  std::string name = "LumiTrainTrap";
395  std::vector<G4TwoVector> polygon;
396 
397  double x1 = -1*(size.x()/2.0)*TMath::Cos(angle);
398  double y1 = -1*(size.x()/2.0)*TMath::Sin(angle);
399 
400  double x2 = (size.x()/2.0)*TMath::Cos(angle);
401  double y2 = -1*(size.x()/2.0)*TMath::Sin(angle);
402 
403  double x3 = (size.x()/2.0)*TMath::Cos(angle);
404  double y3 = (size.x()/2.0)*TMath::Sin(angle);
405 
406  polygon.push_back({x1, y1});
407  polygon.push_back({x2, y2});
408  polygon.push_back({x3, y3});
409 
410  // Extrude the triange - Solid-Volume
411  std::vector<G4ExtrudedSolid::ZSection> zsections = {
412  {-1*size.y()/2.0, {0,0}, 1.0}, {size.y()/2.0, {0,0}, 1.0} };
413 
414  G4ExtrudedSolid *solid = new G4ExtrudedSolid(name+"_ExtrudedSolid", polygon, zsections);
415 
416  // Logical-Volume{
417 
418  G4LogicalVolume *logical = new G4LogicalVolume(solid, GetDetectorMaterial(material), name+"_logical");
419  //G4LogicalVolume *logical = new G4LogicalVolume(solid, material, name+"_logical");
420 
421  G4VisAttributes *vis = new G4VisAttributes( G4Color(0, 1, 1, 0.3) ); // ( red , green , blue , transperancy ) all in percent.
422  vis->SetForceSolid(true);
423  logical->SetVisAttributes(vis);
424 
425  //Physical Volume (Rotate the volume by -90' about x-axis)
426  G4RotationMatrix *rot_matrix = new G4RotationMatrix( G4ThreeVector(1, 0, 0), -1*TMath::Pi()/2.0 );
427  //G4ThreeVector pos_new = G4ThreeVector(pos.x(), pos.y(), pos.z() - (size.z()/(2.0*TMath::Cos(angle))));
428  G4VPhysicalVolume *physical = new G4PVPlacement( rot_matrix, pos, logical, name+"_physical", logicWorld, 0, false, OverlapCheck());
429 
430  // Add it to the list of active volumes so the IsInDetector method picks them up
431  m_PassivePhysicalVolumesSet.insert(physical);
432 
433  //return pos_new;
434 }
435 
436 //_______________________________________________________________________________________________________
437 void EICG4LumiDetector::AddCuboid(G4ThreeVector Wsize, G4ThreeVector Wpos, G4ThreeVector Msize, G4ThreeVector Mpos, double angle, std::string material, G4LogicalVolume *logicWorld)
438 {
439  std::string name = "LumiCuboid";
440  double dz_cuboid = -1*Mpos.z() - (Msize.z()/2.0) - ( -1*Wpos.z() + ((Wsize.x()/2.0)*TMath::Sin(angle)));
441  G4Box *solid = new G4Box(name + "_solid",(Wsize.x()/2.0)*TMath::Cos(angle), Wsize.y()/2.0, dz_cuboid/2.0);
442 
443  G4LogicalVolume *logical = new G4LogicalVolume(solid, GetDetectorMaterial(material),name + "_logic");
444  G4VisAttributes *vis = new G4VisAttributes( G4Color(0, 1, 1, 0.3) );
445  vis->SetForceSolid( true );
446  logical->SetVisAttributes( vis );
447 
448  double zpos_cuboid = Wpos.z() - (Wsize.x()/2.0)*TMath::Sin(angle) - dz_cuboid/2.0 ;
449  G4ThreeVector pos_cuboid = G4ThreeVector( Wpos.x(), Wpos.y(), zpos_cuboid);
450  G4VPhysicalVolume *physical = new G4PVPlacement(0, pos_cuboid, logical, name + "_physical", logicWorld, 0, false, OverlapCheck());
451  m_PassivePhysicalVolumesSet.insert( physical);
452 
453  //return logical; //Used for Midway Convertor only.
454 }
455 
456 //_____________________________________________________________________________________________________________
457 
458 //_____________________________________________________________________________________________________________
459 G4LogicalVolume* EICG4LumiDetector::AddRecCone(G4ThreeVector Wsize, G4ThreeVector Wpos, G4ThreeVector Msize, G4ThreeVector Mpos, G4ThreeVector Tr2size, G4ThreeVector Tr2pos, double angle, std::string material, G4LogicalVolume *logicWorld)
460 {
461 
462  double dz_rec_cone = ( -1*Tr2pos.z() + Tr2size.z()/2.0 ) - (-1*Mpos.z() + Msize.z()/2.0);
463  G4Trd *solid = new G4Trd("solid", Tr2size.x()/2.0 + 1*cm,(Wsize.x()/2.0)*TMath::Cos(angle), Tr2pos.y() + Tr2size.y()/2.0 + 2.0*cm, Wsize.y()/2.0, dz_rec_cone/2.0); //2.0cm to adjust the overlap due to conical shape.
464 
465  G4LogicalVolume *logical = new G4LogicalVolume(solid, GetDetectorMaterial("G4_Galactic"), "Lumi_RectangularCone");
466  G4VisAttributes *vis = new G4VisAttributes( G4Color(0, 1, 1, 0.3) );
467  vis->SetForceSolid( true );
468  logical->SetVisAttributes( vis);
469 
470  G4ThreeVector pos_rec_cone = G4ThreeVector(Wpos.x(), Wpos.y(), Mpos.z() - Msize.z()/2.0 - dz_rec_cone/2.0);
471  G4VPhysicalVolume *physical = new G4PVPlacement(0, pos_rec_cone, logical, "Lumi_RectangularCone", logicWorld, 0, false, OverlapCheck());
472  m_PassivePhysicalVolumesSet.insert( physical);
473 
474  return logical;
475 }
476 
477 //______________________________________________________________________________________________________________________________
478 void EICG4LumiDetector::AddExitWindowForV2(G4ThreeVector Wsize, G4ThreeVector pos_daug, double angle, std::string material, G4LogicalVolume *logicWorld)
479 {
480  std::string name = "LumiExitWinV2";
481  G4Box *solid = new G4Box(name+"solid",(Wsize.x()/2.0)*TMath::Cos(angle), Wsize.y()/2.0, Wsize.z()/2.0);
482 
483  G4LogicalVolume *logical = new G4LogicalVolume( solid, GetDetectorMaterial(material), name+"logical");
484  G4VisAttributes *vis = new G4VisAttributes( G4Color(1, 0, 0, 1) );
485  vis->SetForceSolid( true );
486  logical->SetVisAttributes( vis );
487 
488  G4VPhysicalVolume *physical = new G4PVPlacement(0, pos_daug, logical, name+"physical", logicWorld, 0, false, OverlapCheck());
489  m_PassivePhysicalVolumesSet.insert( physical);
490 }
491 
492 //_______________________________________________________________________________________________________
493 void EICG4LumiDetector::AddLumiTracker( std::string name, int copyNum, G4ThreeVector size, G4ThreeVector pos, G4LogicalVolume *logicWorld )
494 {
495 
496  G4Box *solid = new G4Box(name + "_solid", size.x()/2.0 , size.y()/2.0 , size.z()/2.0);
497 
498  G4LogicalVolume *logical = new G4LogicalVolume( solid, G4NistManager::Instance()->FindOrBuildMaterial("G4_Si"), name + "_logical");
499 
500  G4VisAttributes *vis = new G4VisAttributes( G4Color(1.0, 1.0, 0.0, 1.0) );
501  vis->SetForceSolid(true);
502  logical->SetVisAttributes(vis);
503 
504  G4VPhysicalVolume *physical = new G4PVPlacement( 0, pos, logical, name + "_physical", logicWorld, false, copyNum, OverlapCheck() );
505 
506  m_ActivePhysicalVolumesSet.insert( physical );
507 
508 }
509 
510 //____________________________________________________________________________________________________________________________________
511 void EICG4LumiDetector::AddExitWindowForV3(G4ThreeVector Wsize, G4ThreeVector Wpos, G4ThreeVector Tr2size, G4ThreeVector Tr2pos, std::string material, G4LogicalVolume *logicWorld)
512 {
513 
514  std::string name = "LumiExitWinV3";
515  G4Box *solid = new G4Box(name+"_solid",Tr2size.x()/2.0 + 1*cm, Tr2size.y() + Tr2pos.y()/2.0 + 2.0*cm, Wsize.z()/2.0);//2.0cm to adjust the overlap due to conical shape.
516 
517  G4LogicalVolume *logical = new G4LogicalVolume( solid, GetDetectorMaterial(material),name+"logical");
518  G4VisAttributes *vis = new G4VisAttributes( G4Color(1, 0, 0, 1) );
519  vis->SetForceSolid( true );
520  logical->SetVisAttributes( vis );
521 
522  G4ThreeVector pos = G4ThreeVector(Wpos.x(), Wpos.y(), Tr2pos.z() - Tr2size.z()/2.0 - Wsize.z()/2.0);
523  G4VPhysicalVolume *physical = new G4PVPlacement(0,pos, logical, name+"physical", logicWorld, 0, false, OverlapCheck());
524  m_PassivePhysicalVolumesSet.insert( physical);
525 
526 }
527 
528 
529 //_______________________________________________________________________________________________________________________________
530 void EICG4LumiDetector::AddCAL( std::string name, G4ThreeVector size, G4ThreeVector pos, int total_tower, G4LogicalVolume *logicWorld )
531 {
532 
533  G4int nxy = total_tower; // 32
534  //dimensions for single tower
535  G4double towerSizeXY = size.x()/nxy;
536  //geo->GetOptD(nam, "towerSizeXY", towerSizeXY, GeoParser::Unit(mm));
537  G4double towerEMZ = size.z();
538  //geo->GetOptD(nam, "towerEMZ", towerEMZ, GeoParser::Unit(mm));
539  //G4double zpos = towerEMZ/2;
540  //G4double zpos = pos.z();
541  //geo->GetOptD(nam, "zpos", zpos, GeoParser::Unit(mm));
542 
543  //geo->GetOptI(nam, "nxy", nxy);
544 
545  //module size for tower assembly, increased to allow for tower rotation
546  G4double modxy = size.x(); // + 40*mm
547  G4double modz = size.z(); // + 6*mm
548 
549  //G4cout << " modxy: " << modxy << G4endl;
550  //G4cout << " modz: " << modz << G4endl;
551 
552  //top calorimeter volume
553  G4Box *mods = new G4Box(name+"_mod", modxy/2, modxy/2, modz/2);
554  G4LogicalVolume *modv = new G4LogicalVolume(mods, G4NistManager::Instance()->FindOrBuildMaterial("G4_Galactic"), name+"_mod");
555  new G4PVPlacement(0, G4ThreeVector(pos.x(), pos.y(), pos.z()), modv, name+"_mod", logicWorld, false, 0, OverlapCheck());
556  //modv->SetVisAttributes(new G4VisAttributes(G4Color(0, 0, 1)));
557  modv->SetVisAttributes( G4VisAttributes::GetInvisible() );
558 
559  // Construct individual towers
560  G4LogicalVolume *towv = MakeTower(towerSizeXY, towerEMZ);
561 
562  G4int tcnt = 0;
563  G4double xypos0 = -(nxy*towerSizeXY)/2 + towerSizeXY/2;
564  for(G4int ix=0; ix<nxy; ix++) {
565  for(G4int iy=0; iy<nxy; iy++) {
566  G4double xpos = xypos0 + ix*towerSizeXY;
567  G4double ypos = xypos0 + iy*towerSizeXY;
568  new G4PVPlacement(0, G4ThreeVector(xpos, ypos, 0), towv, towv->GetName(), modv, false, tcnt++, OverlapCheck());
569  }
570  }
571 
572 }
573 
574 //______________________________________________________________________________________________________________________________
575 G4LogicalVolume* EICG4LumiDetector::MakeTower(G4double calorSizeXY, G4double calorEMZ) {
576 
577  const double offset=0.5;//in mm
578  const double dist=1.0;
579  const double tot_len=calorSizeXY;
580  const double h=0.5*sqrt(3)*dist;
581 
582  const int nx1=int((tot_len-2*offset)/(dist/2))+1;
583  const int ny1=int((tot_len-offset)/(2*h))+1;
584  const int ny2=int((tot_len-offset-h)/(2*h))+1;
585 
586  const double x0=-((tot_len/2.0)-offset);
587  const double y01=((tot_len/2.0)-offset);
588  const double y02=((tot_len/2.0)-offset-h);
589 
590  G4Material* defaultMaterial = G4NistManager::Instance()->FindOrBuildMaterial("G4_Galactic");
591  G4Material* gapMaterial2 = G4NistManager::Instance()->FindOrBuildMaterial("G4_POLYSTYRENE");
592  G4double a = 183.85*g/mole;
593  G4Element* elW = new G4Element("Tungsten","W", 74., a);
594 
595  G4Material* EMCal_abs_mat = GetDetectorMaterial( "EMCal_fiber_mat", false ); // false suppress warnings
596  if( ! EMCal_abs_mat ) {
597  EMCal_abs_mat = new G4Material("EMCal_fiber_mat", 12.4*g/cm3, 2);
598  EMCal_abs_mat->AddElement(elW, 96.0*perCent);
599  EMCal_abs_mat->AddMaterial(gapMaterial2, 4.0*perCent);
600  }
601 
602  //EM
603  G4LogicalVolume* calorEM;
604  G4VSolid* calorimeterEM = new G4Box("CalorimeterEM_", calorSizeXY/2, calorSizeXY/2, calorEMZ/2);
605  calorEM=new G4LogicalVolume(calorimeterEM,defaultMaterial, m_Name+"_CalorEM");
606 
607  //absorber
608  G4LogicalVolume* absorberEMLV;
609  G4VSolid* absorberEM = new G4Box(m_Name+"_AbsoEM_solid", // its name
610  calorSizeXY/2, calorSizeXY/2, calorEMZ/2); // its size
611  absorberEMLV = new G4LogicalVolume(absorberEM,EMCal_abs_mat, m_Name+"_AbsoEM");
612  G4VPhysicalVolume *physical_absorber = new G4PVPlacement(0,G4ThreeVector(0.,0.,0.),absorberEMLV, m_Name+"_AbsoEM_p",calorEM,false,0, OverlapCheck());
613  m_PassivePhysicalVolumesSet.insert( physical_absorber );
614 
615  G4VSolid* gapEM = new G4Tubs(m_Name+"_GapEM", // its name0, pos, sheetLogic, name + "_g4physical", logicWorld, false, 0, OverlapCheck() );
616  0.0, 0.235*mm, calorEMZ/2,0.0,360.0 * deg); // its size//0.0 * deg, 360.0 * deg
617 
618  //Fibers
619  G4LogicalVolume* gapEMLV;
620  gapEMLV = new G4LogicalVolume(gapEM,gapMaterial2, m_Name);
621  int copynono=0;
622  double step_x=(dist/2.0)*mm;
623  double step_y=(2.0*h)*mm;
624  //G4cout<<"Nx: "<<nx1<<" Ny1: "<<ny1<<" Ny2: "<<ny2<<" step_x: "<<step_x<<" step_y: "<<step_y<<" x0: "<<x0<<" y01: "<<y01<<" y02: "<<y02<<G4endl;
625 
626  for(int i=0;i<nx1;i++){
627  G4double pos_x=x0*mm+i*step_x;
628  G4double pos_y=0.0;
629  //if(i==(nFibAr-1)) continue;
630  // if(i%2==0) pos_x=(-29.95+i*(0.05))*cm;
631  // if(i%2!=0) pos_x=(-29.9+i*(0.05))*cm;
632  // pos_x=(-29.95+i*(0.1))*cm;
633  int jend=(i%2==0) ? ny1 : ny2;
634  for(int j=0;j<jend;j++){
635 
636 
637  if(i%2==0) pos_y=y01*mm-j*step_y;
638  if(i%2!=0) pos_y=y02*mm-j*step_y;
639  G4VPhysicalVolume *physical_scint = new G4PVPlacement(0,G4ThreeVector(pos_x,pos_y, 0.),gapEMLV,m_Name+"_EMGapPhysical",absorberEMLV,false,copynono, OverlapCheck());
640 
641  // Add to active layers
642  m_ActivePhysicalVolumesSet.insert( physical_scint );
643 
644  //new G4PVPlacement(0,G4ThreeVector(pos_x,pos_y, 0.),gapEMLV,"EMGapPhysical",absorberEMLV,0,copynono);//first try
645  copynono++;
646  //G4cout<<"Point # "<<copynono<<" x: "<<pos_x<<" y: "<<pos_y<<G4endl;
647 
648  }
649  }
650 
651  absorberEMLV->SetVisAttributes( G4VisAttributes::GetInvisible() );
652  gapEMLV->SetVisAttributes( G4VisAttributes::GetInvisible() );
653 
654  G4VisAttributes* calorEMvis= new G4VisAttributes(G4Colour(1,0,1));//magenta calorimeter
655  calorEMvis->SetForceAuxEdgeVisible(true);
656  calorEM->SetVisAttributes(calorEMvis);
657 
658  return calorEM;
659 }
660