EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EtmVacuumChamber.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EtmVacuumChamber.cc
1 
2 #include <iostream>
3 #include <fstream>
4 
5 #include <unistd.h>
6 
7 #include <TObjString.h>
8 
9 #ifdef _VGM_
10 #include "Geant4GM/volumes/Factory.h"
11 #include "RootGM/volumes/Factory.h"
12 #endif
13 
14 #ifdef _ETM2GEANT_
15 #include "G4SystemOfUnits.hh"
16 #include "G4Tubs.hh"
17 #include "G4LogicalVolume.hh"
18 #include "G4VPhysicalVolume.hh"
19 #include "G4SubtractionSolid.hh"
20 #endif
21 
22 #include <EtmVacuumChamber.h>
23 #include <EicToyModel.h>
24 
25 // ---------------------------------------------------------------------------------------
26 // ---------------------------------------------------------------------------------------
27 
29  mTGeoModel(0), mHadronBeamPipeOpening(0.0), mActualCrossingAngle(0.0),
30  mStandaloneMode(false), g4Factory(0)
31 {
32 } // EtmVacuumChamber::EtmVacuumChamber()
33 
34 // ---------------------------------------------------------------------------------------
35 // ---------------------------------------------------------------------------------------
36 
37 void EtmVacuumChamber::CreateMedium(const char *name, double A, double Z, double density)
38 {
39  // FIXME: do it better;
40  static unsigned counter;
41 
42  new TGeoMedium (name, ++counter, new TGeoMaterial(name, A, Z, density));
43 } // EtmVacuumChamber::CreateMedium()
44 
45 // ---------------------------------------------------------------------------------------
46 
48 {
49  auto eic = EicToyModel::Instance();
50 
51  // Sanity checks;
52  if (mTGeoModel && !mStandaloneMode) return;
53 
54  // First see whether gGeoManager is available;
55  if (!mTGeoModel && gGeoManager)
56  mTGeoModel = gGeoManager;
57  else {
58  if (mTGeoModel) delete mTGeoModel;
59 
60  // Create a standalone instance otherwise;
61  mTGeoModel = new TGeoManager("VC.ROOT", "Simplified IR vacuum chamber geometry");
62 
63  // ROOT media database is rather lousy compared to GEANT; just create everything
64  // from scratch by hand;
65  CreateMedium(_ACCELERATOR_VACUUM_, 1.008, 1, 1E-10);
66  CreateMedium( _UNIVERSE_VACUUM_, 1.008, 1, 1E-10);
67  CreateMedium( "Be", 9.01, 4, 1.85);
68  CreateMedium( "Al", 26.98, 13, 2.70);
69 
70  // FIXME: could do this better of course;
71  //printf("GetIrRegionLength(): %f\n", GetIrRegionLength());
72 #if 1//_OLD_
73  auto world = mTGeoModel->MakeBox("World", mTGeoModel->GetMedium(_UNIVERSE_VACUUM_),
74  // FIXME: GetIrRegionLength() here returns default value
75  // rather than the one encoded in the .root dump;
76  200., 200., eic->GetIrRegionLength() + 100.);
77  mTGeoModel->SetTopVolume(world);
78 #else
79  auto world = new TGeoVolumeAssembly("World");
80  mTGeoModel->SetTopVolume(world);
81 #endif
82  world->SetVisibility(kFALSE);
83 
84  mStandaloneMode = true;
85  } //if
86 } // EtmVacuumChamber::CreateWorld()
87 
88 // ---------------------------------------------------------------------------------------
89 
91 {
92  // So: either geometry can be tuned dynamically or the requested value
93  // matches the geometry; even if flexible, only a single change is allowed
94  // in a non-standalone mode (otherwise why would one like to erase the whole
95  // geometry tree because of a change in the vacuum chamber); FIXME: may want to
96  // erase these nodes selectively later;
97  return (ConfigurableCrossingAngle() || (FixedCrossingAngle() == value)) &&
99 } // EtmVacuumChamber::CrossingAngleResetPossible()
100 
101 // ---------------------------------------------------------------------------------------
102 
104 {
105  double crossing_angle = EicToyModel::Instance()->GetCrossingAngle();
106 
107  //printf("EtmVacuumChamber::CheckGeometry(): %f\n", crossing_angle);
108  // Rebuild only if the crossing angle changed; FIXME: it is assumed of course that
109  // EicToyModel ctor sets mCrossingAngle to 25mrad;
110  if (mActualCrossingAngle != crossing_angle || force) {
111  CreateWorld();
112  CreateGeometry();
113 
114  mActualCrossingAngle = crossing_angle;
115  } //if
116 } // EtmVacuumChamber::CheckGeometry()
117 
118 // ---------------------------------------------------------------------------------------
119 
120 void EtmVacuumChamber::Export(const char *fname)
121 {
122  CheckGeometry();
123 
124  mTGeoModel->CloseGeometry();
125  mTGeoModel->CheckOverlaps(0.0001);
126 
127  // FIXME: a warning otherwise;
128  if (mStandaloneMode) mTGeoModel->Export(fname);
129 } // EtmVacuumChamber::Export()
130 
131 // ---------------------------------------------------------------------------------------
132 
134 {
135  CheckGeometry();
136 
137  if (mStandaloneMode) {
138  // Create GDML file first; FIXME: pipe(), shm, tmpfs or such?; PID tag, perhaps?;
139  const char *fname = "/tmp/tmp.gdml";
140 
141  mTGeoModel->Export(fname);
142 
143  // Create input stream; read the file in; write it out as a wrapper class instance,
144  // which can be accessed without ETM library, if needed (TObjString);
145  {
146  std::ifstream fin(fname);
147 
148  TString str;
149  str.ReadFile(fin);
150 
151  TObjString ostr; ostr.SetString(str);
152  // FIXME: hardcoded;
153  ostr.Write("VC.GDML");
154 
155  // Remove the temporary file;
156  unlink(fname);
157  }
158  } //if
159 } // EtmVacuumChamber::StoreGDMLdump()
160 
161 // ---------------------------------------------------------------------------------------
162 //
163 // Assume that certain parts of the vacuum chamber design will simply move
164 // together with the IP;
165 //
166 
167 void EtmVacuumChamber::DrawMe( void ) //const
168 {
169  CheckGeometry();
170 
171  auto eic = EicToyModel::Instance();
172 
173  int gray = kGray+1;
174  // FIXME: step hardcoded;
175  double step = 5.0 * etm::cm, zcurr = -eic->GetIrRegionLength()/2, rprev[2] = {0.0, 0.0};
176  double dphi = eic->GetCurrentView() == EicToyModel::kHorizontal ? 0.0 : M_PI/2;
177 
178  for( ; zcurr <= eic->GetIrRegionLength()/2; zcurr += step) {
179  double rcurr[2] = {GetRadialSize(zcurr, dphi+M_PI), GetRadialSize(zcurr, dphi)};
180  if (rprev[0] && rprev[1] && rcurr[0] && rcurr[1]) {
181  double xx[4] = { zcurr-step, zcurr, zcurr, zcurr-step};
182  double yy[4] = { -rprev[0], -rcurr[0], rcurr[1], rprev[1]};
183 
184  eic->DrawPolygon(4, xx, yy, gray, false);
185  } //if
186  for(unsigned du=0; du<2; du++)
187  rprev[du] = rcurr[du];
188  } //for inf
189 } // EtmVacuumChamber::DrawMe()
190 
191 // ---------------------------------------------------------------------------------------
192 
193 //
194 // FIXME: unify with the azimuthal scan; FIXME: this assumes that the electron beam
195 // pipe is aligned with Z axis, therefore point (0,0) is *inside* the vacuum
196 // chamber, no matter what;
197 //
198 
199 double EtmVacuumChamber::GetRadialSize(double z, double phi) //const
200 {
201  CheckGeometry();
202 
203  // Assume that the beam pipe is positioned in the World volume already (in other
204  // words the IP shift is taken into account); then 'z' does not require any
205  // further shifts, obviously;
206  double xx[3] = {0.0, 0.0, z};
207  double nn[3] = {cos(phi), sin(phi), 0.0}, outerR = 0.0;
208 
209  mTGeoModel->SetCurrentPoint (xx);
210  mTGeoModel->SetCurrentDirection(nn);
211 
212  for(auto node = mTGeoModel->GetCurrentNode(); ; ) {
213  auto material = node->GetVolume()->GetMaterial();
214 
215  mTGeoModel->FindNextBoundary();
216  // Switch to next node along {xx, nn[]} 3D line;
217  node = mTGeoModel->Step();
218 
219  // If it was NOT a vacuum volume, record the radius at the boundary;
220  //if (material != mTGeoModel->GetMaterial("Vacuum")) {
221  if (material != mTGeoModel->GetMaterial(_ACCELERATOR_VACUUM_) &&
222  material != mTGeoModel->GetMaterial(_UNIVERSE_VACUUM_)) {
223  const double *pt = mTGeoModel->GetCurrentPoint();
224  outerR = sqrt(pt[0]*pt[0] + pt[1]*pt[1]);
225  } //if
226 
227  //assert(model->IsEntering());
228 
229  // Once out of volume, break;
230  if (mTGeoModel->IsOutside()) break;
231  } //for inf
232 
233  return outerR;
234 } // EtmVacuumChamber::GetRadialSize()
235 
236 // ---------------------------------------------------------------------------------------
237 
238 G4VSolid *EtmVacuumChamber::CutThisSolid(G4VSolid *solid, double dz)
239 {
240 #if defined(_ETM2GEANT_) && defined(_VGM_)
241  // Do this once upon startup: switch TGeoManager pointer -> calculate vacuum chamber
242  // TGeo geometry dynamically -> convert to G4 geometry -> switch TGeoManager pointer back;
243  if (!g4Factory) {
244  g4Factory = new Geant4GM::Factory();
245 
246  // Switch TGeoManager pointer;
247  TGeoManager *saveGeoManager = gGeoManager; gGeoManager = 0;
248  CheckGeometry();
249 
250  RootGM::Factory rtFactory;
251  rtFactory.Import(gGeoManager->GetTopNode());
252 
253  //++g4Factory.SetDebug(1);
254  rtFactory.Export((Geant4GM::Factory*)g4Factory);
255 
256  // Return TGeoManager pointer back;
257  delete gGeoManager; gGeoManager = saveGeoManager;
258  } //if
259 
260  {
261  G4VSolid *ptr = solid;
262  G4VPhysicalVolume *gcut = ((Geant4GM::Factory*)g4Factory)->World();
263  auto glog = gcut->GetLogicalVolume();
264 
265  for(int iq=0; iq<glog->GetNoDaughters(); iq++) {
266  auto daughter = glog->GetDaughter(iq);
267 
268  // Hope the algebra is correct here?;
269  CLHEP::Hep3Vector vv(0, 0, dz);//, uu = daughter->GetRotation() ? (*daughter->GetRotation() * vv) : vv;
270 
271  //ptr->DumpInfo();
272  ptr = new G4SubtractionSolid(ptr->GetName(), ptr, daughter->GetLogicalVolume()->GetSolid(),
273  daughter->GetRotation(), daughter->GetTranslation() - vv);
274  } //for iq
275 
276  return ptr;
277  }
278 #else
279  return solid;
280 #endif
281 } // EtmVacuumChamber::CutThisSolid()
282 
283 // ---------------------------------------------------------------------------------------
284 // ---------------------------------------------------------------------------------------
285