BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSGeometryFactorySQL.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSAcceleratorModel.hh"
20#include "BDSDebug.hh"
21#include "BDSException.hh"
22#include "BDSGeometryExternal.hh"
23#include "BDSGeometryFactorySQL.hh"
24#include "BDSGlobalConstants.hh"
25#include "BDSMaterials.hh"
26#include "BDSMySQLTable.hh"
27#include "BDSMySQLVariable.hh"
28#include "BDSMySQLWrapper.hh"
29#include "BDSSDSampler.hh"
30#include "BDSSampler.hh"
31#include "BDSSamplerRegistry.hh"
32#include "BDSSDManager.hh"
33#include "BDSUtilities.hh"
34
35#include "globals.hh"
36#include "G4Box.hh"
37#include "G4Cons.hh"
38#include "G4EllipticalCone.hh"
39#include "G4EllipticalTube.hh"
40#include "G4IntersectionSolid.hh"
41#include "G4LogicalVolume.hh"
42#include "G4Polycone.hh"
43#include "G4PVPlacement.hh"
44#include "G4RotationMatrix.hh"
45#include "G4String.hh"
46#include "G4SubtractionSolid.hh"
47#include "G4Torus.hh"
48#include "G4Trap.hh"
49#include "G4Tubs.hh"
50#include "G4UnionSolid.hh"
51#include "G4UserLimits.hh"
52#include "G4Version.hh"
53#include "G4VisAttributes.hh"
54#include "G4VPhysicalVolume.hh"
55
56#include <algorithm>
57#include <cstdlib>
58#include <cstring>
59#include <limits>
60#include <list>
61#include <map>
62#include <set>
63#include <string>
64#include <unordered_map>
65#include <vector>
66
67G4double BDSGeometryFactorySQL::defaultRigidity = std::numeric_limits<double>::max();
68
69BDSGeometryFactorySQL::BDSGeometryFactorySQL()
70{
71 CleanUpSQL();
72}
73
75{
76 CleanUpSQL();
78}
79
81{
82 NVariables = 0;
83 VisRed = 0;
84 VisGreen = 0;
85 VisBlue = 0;
86 VisAlpha = 0;
87 VisType = "";
88 Material = "";
89 TableName = "";
90 Name = "";
91 PosX = 0;
92 PosY = 0;
93 PosZ = 0;
94 RotPsi = 0;
95 RotTheta = 0;
96 RotPhi = 0;
97 K1 = 0;
98 K2 = 0;
99 K3 = 0;
100 K4 = 0;
101 PARENTNAME = "";
102 InheritStyle = "";
103 Parameterisation = "";
104 MagType = "";
105 align_in = 0;
106 align_out = 0;
107 SetSensitive = 0;
108 PrecisionRegion = 0;
109 ApproximationRegion = 0;
110 FieldX = 0;
111 FieldY = 0;
112 FieldZ = 0;
113 lengthUserLimit = 0;
114
115 unShiftedExtents.clear();
116
117 precisionRegionSQL = nullptr;
118 approximationRegionSQL = nullptr;
119 rotateComponent = nullptr;
120 itsMarkerVol = nullptr;
121
122 UniformField.clear();
123 Fieldvol.clear();
124 QuadBgrad.clear();
125 SextBgrad.clear();
126 Sextvol.clear();
127 OctBgrad.clear();
128 Octvol.clear();
129
130 VOL_LIST.clear();
131
132 itsSQLTable.clear();
133 samplerIDs.clear();
134
135 sensitiveComponents.clear();
136
137 alignInVolume = nullptr;
138 alignOutVolume = nullptr;
139
140 uniformFieldVolField.clear();
141 quadVolBgrad.clear();
142 sextVolBgrad.clear();
143 octVolBgrad.clear();
144}
145
147 G4String fileName,
148 std::map<G4String, G4Colour*>* colourMapping,
149 G4bool autoColour,
150 G4double suggestedLength,
151 G4double suggestedHorizontalWidth,
152 std::vector<G4String>* /*namedVolumeNames*/,
153 G4bool /*makeSensitive*/,
154 BDSSDType /*sensitivityType*/,
155 BDSSDType /*vacuumSensitivityType*/,
156 G4UserLimits* /*userLimitsToAttachToAllLVs*/)
157{
158 CleanUp();
159
160 // strip of the file name effectively
161 G4String containingDir = BDS::GetFullPath(fileName, true);
162#ifdef BDSDEBUG
163 G4cout << __METHOD_NAME__ << "loading SQL file: " << fileName << G4endl;
164 G4cout << __METHOD_NAME__ << "containing directory: " << containingDir << G4endl;
165#endif
166 std::ifstream ifs;
167 ifs.open(fileName);
168 if (!ifs.good())
169 {throw BDSException(__METHOD_NAME__, "Cannot open file \"" + fileName + "\"");}
170
171 //hasFields = false;
172 //nPoleField = 0;
173 //hasUniformField = false;
174
175 G4double outerR = suggestedHorizontalWidth*0.5;
176 G4VSolid* containerSolid = new G4Box("container_solid",
177 outerR,
178 outerR,
179 suggestedLength*0.5);
180
181 const G4String emptyMaterialName = BDSGlobalConstants::Instance()->EmptyMaterial();
182 G4Material* emptyMaterial = BDSMaterials::Instance()->GetMaterial(emptyMaterialName);
183
184 itsMarkerVol = new G4LogicalVolume(containerSolid,
185 emptyMaterial,
186 "container_lv");
187
188 //length=(dynamic_cast<G4Box*>(itsMarkerVol->GetSolid())->GetZHalfLength()*2.0);
189 VOL_LIST.push_back(itsMarkerVol);
190 G4String fileListLine;
191 char buffer[1000];
192 while (ifs >> fileListLine)
193 {
194 if (BDS::StrContains(fileListLine, "#"))
195 {ifs.getline(buffer,1000);} // a comment or info line - store it
196 else
197 {BuildSQLObjects(containingDir + fileListLine);} // a line with file to be parsed
198 }
199
200 // Close Geomlist file
201 ifs.close();
202
203 // update solid
204 /*delete containerSolid; // delete existing solid
205 containerSolid = new G4Box("container_solid",
206 (xmax - xmin)*0.5,
207 (xmax - xmin)*0.5,
208 (xmax - xmin)*0.5);
209 itsMarkerVol->SetSolid(containerSolid); // update container solid
210 */
211 std::set<G4LogicalVolume*> tempVols;
212 for (auto lv : VOL_LIST)
213 {tempVols.insert(lv);}
214 ApplyColourMapping(tempVols, colourMapping, autoColour);
215
216 BDSGeometryExternal* result = new BDSGeometryExternal(containerSolid, itsMarkerVol, Extent());
217 result->RegisterRotationMatrix(allRotationMatrices);
218 result->RegisterSolid(allSolids);
219 result->RegisterLogicalVolume(allLogicalVolumes);
220 result->RegisterPhysicalVolume(allPhysicalVolumes);
221 result->RegisterVisAttributes(allVisAttributes);
222
223 return result;
224}
225
226void BDSGeometryFactorySQL::BuildSQLObjects(G4String file)
227{
228#ifdef BDSDEBUG
229 G4cout << __METHOD_NAME__ << "loading single file " << file << G4endl;
230#endif
231
232 BDSMySQLWrapper sql(file);
233 itsSQLTable=sql.ConstructTable();
234
235 for (G4int i=0; i<(G4int)itsSQLTable.size(); i++)
236 {
237#ifdef BDSDEBUG
238 itsSQLTable[i]->Print();
239#endif
240 TableName = itsSQLTable[i]->GetName();
241#ifdef BDSDEBUG
242 G4cout << __METHOD_NAME__ << " i = " << i << ", TableName = " << TableName << G4endl;
243#endif
244 G4int pos = TableName.find("_");
245 std::string ObjectType = TableName.substr(pos+1,TableName.length() - pos);
246 NVariables = itsSQLTable[i]->GetVariable(0)->GetNVariables();
247 for (G4int k=0; k<NVariables; k++)
248 {
249 SetCommonParams(itsSQLTable[i], k);
250 G4LogicalVolume* logVol;
251 if(BDS::StrCompare(ObjectType, "CONE") == 0)
252 {logVol = BuildCone(itsSQLTable[i],k);}
253 else if(BDS::StrCompare(ObjectType, "ELLIPTICALCONE") == 0)
254 {logVol = BuildEllipticalCone(itsSQLTable[i],k);}
255 else if(BDS::StrCompare(ObjectType, "POLYCONE") == 0)
256 {logVol = BuildPolyCone(itsSQLTable[i],k);}
257 else if(BDS::StrCompare(ObjectType, "BOX") == 0)
258 {logVol = BuildBox(itsSQLTable[i],k);}
259 else if(BDS::StrCompare(ObjectType, "TRAP") == 0)
260 {logVol = BuildTrap(itsSQLTable[i],k);}
261 else if(BDS::StrCompare(ObjectType, "TORUS") == 0)
262 {logVol = BuildTorus(itsSQLTable[i],k);}
263 else if(BDS::StrCompare(ObjectType, "SAMPLER") == 0)
264 {logVol = BuildSampler(itsSQLTable[i],k);}
265 else if(BDS::StrCompare(ObjectType, "TUBE") == 0)
266 {logVol = BuildTube(itsSQLTable[i],k);}
267 else if(BDS::StrCompare(ObjectType, "ELLIPTICALTUBE") == 0)
268 {logVol = BuildEllipticalTube(itsSQLTable[i],k);}
269 //else if(BDS::StrCompare(ObjectType, "PCLTUBE", G4String::ignoreCase)==0)
270 // {logVol = BuildPCLTube(itsSQLTable[i],k);}
271 else
272 {throw BDSException(__METHOD_NAME__ + ObjectType + " not known.");}
273 //Set the user limits and visual attributes
274 SetLogVolAtt(logVol, lengthUserLimit);
275 VOL_LIST.push_back(logVol);
276 allLogicalVolumes.insert(logVol);
277 }
278 PlaceComponents(itsSQLTable[i], VOL_LIST);
279 }
280}
281
282template<>
283void BDSGeometryFactorySQL::AssignVariable<G4double>(BDSMySQLTable* aSQLTable, G4int k, G4String variableName, G4double& variable)
284{
285 BDSMySQLVariable* sqlVariable = aSQLTable->GetVariable(variableName);
286 if(sqlVariable)
287 {variable = sqlVariable->GetDblValue(k);}
288}
289
290template<>
291void BDSGeometryFactorySQL::AssignVariable<G4int>(BDSMySQLTable* aSQLTable, G4int k, G4String variableName, G4int& variable)
292{
293 BDSMySQLVariable* sqlVariable = aSQLTable->GetVariable(variableName);
294 if(sqlVariable)
295 {variable = sqlVariable->GetIntValue(k);}
296}
297
298template<>
299void BDSGeometryFactorySQL::AssignVariable<G4String>(BDSMySQLTable* aSQLTable, G4int k, G4String variableName, G4String& variable)
300{
301 BDSMySQLVariable* sqlVariable = aSQLTable->GetVariable(variableName);
302 if(sqlVariable)
303 {variable = sqlVariable->GetStrValue(k);}
304}
305
306void BDSGeometryFactorySQL::SetCommonParams(BDSMySQLTable* aSQLTable, G4int k)
307{
308 //Defaults
309 VisRed = VisGreen = VisBlue = 0.5;
310 VisAlpha = 0.5;
311 VisType = "S";
312 Material = BDSGlobalConstants::Instance()->VacuumMaterial();
313 Name="";
314 PrecisionRegion=0;
315 ApproximationRegion=0;
316
317 AssignVariable(aSQLTable,k,"RED" ,VisRed);
318 AssignVariable(aSQLTable,k,"BLUE" ,VisBlue);
319 AssignVariable(aSQLTable,k,"GREEN" ,VisGreen);
320 AssignVariable(aSQLTable,k,"ALPHA" ,VisAlpha);
321 AssignVariable(aSQLTable,k,"VISATT",VisType);
322 AssignVariable(aSQLTable,k,"MATERIAL",Material);
323 AssignVariable(aSQLTable,k,"PRECISIONREGION",PrecisionRegion);
324 AssignVariable(aSQLTable,k,"APPROXIMATIONREGION",ApproximationRegion);
325
326 AssignVariable(aSQLTable,k,"NAME",Name);
327 if(Name=="_SQL")
328 {Name = TableName+std::to_string(k) + "_SQL";}
329 if(Name.empty())
330 {Name = TableName+std::to_string(k);}
331 Name = itsMarkerVol->GetName()+"_"+Name;
332#ifdef BDSDEBUG
333 G4cout << __METHOD_NAME__ << " k = " << k << ", Name = " << Name << G4endl;
334#endif
335}
336
337void BDSGeometryFactorySQL::SetPlacementParams(BDSMySQLTable* aSQLTable, G4int k)
338{
339 //Defaults
340 PosX = PosY = PosZ = 0.;
341 RotPsi = RotTheta = RotPhi = 0.;
342 K1 = K2 = K3 = K4 = 0.;
343 PARENTNAME = "";
344 InheritStyle = "";
345 Parameterisation = "";
346 align_in=0;
347 align_out=0;
348 SetSensitive=0;
349 MagType = "";
350 FieldX = FieldY = FieldZ = 0.0;
351 Name="";
352
353 AssignVariable(aSQLTable,k,"PARENTNAME",PARENTNAME);
354 AssignVariable(aSQLTable,k,"POSX",PosX);
355 AssignVariable(aSQLTable,k,"POSY",PosY);
356 AssignVariable(aSQLTable,k,"POSZ",PosZ);
357 AssignVariable(aSQLTable,k,"ROTPSI",RotPsi);
358 AssignVariable(aSQLTable,k,"ROTTHETA",RotTheta);
359 AssignVariable(aSQLTable,k,"ROTPHI",RotPhi);
360 AssignVariable(aSQLTable,k,"K1",K1);
361 AssignVariable(aSQLTable,k,"K2",K2);
362 AssignVariable(aSQLTable,k,"K3",K3);
363 AssignVariable(aSQLTable,k,"K4",K4);
364 AssignVariable(aSQLTable,k,"MAGTYPE",MagType);
365 AssignVariable(aSQLTable,k,"FIELDX",FieldX);
366 AssignVariable(aSQLTable,k,"FIELDY",FieldY);
367 AssignVariable(aSQLTable,k,"FIELDZ",FieldZ);
368 AssignVariable(aSQLTable,k,"ALIGNIN",align_in);
369 AssignVariable(aSQLTable,k,"ALIGNOUT",align_out);
370 AssignVariable(aSQLTable,k,"SETSENSITIVE",SetSensitive);
371 AssignVariable(aSQLTable,k,"INHERITSTYLE",InheritStyle);
372 AssignVariable(aSQLTable,k,"PARAMETERISATION",Parameterisation);
373
374 // TODO
375 //if(PARENTNAME=="")
376 // {PosZ-=Length()/2.0;} //Move position to beginning of element
377
378 PARENTNAME= itsMarkerVol->GetName() + "_" + PARENTNAME;
379
380 AssignVariable(aSQLTable,k,"NAME",Name);
381 if(Name=="_SQL")
382 {Name = TableName+std::to_string(k) + "_SQL";}
383 if(Name.empty())
384 {Name = TableName+std::to_string(k);}
385
386 Name = itsMarkerVol->GetName()+"_"+Name;
387#ifdef BDSDEBUG
388 G4cout << __METHOD_NAME__ << " k = " << k << ", Name = " << Name << G4endl;
389#endif
390}
391
392G4VisAttributes* BDSGeometryFactorySQL::VisAtt()
393{
394 G4VisAttributes* va = new G4VisAttributes(G4Colour(VisRed, VisGreen, VisBlue, VisAlpha));
395 char testChar = VisType[0];
396 switch (testChar)
397 {
398 case 'W': va->SetForceWireframe(true); break;
399 case 'I': va->SetVisibility(false); break;
400 case 'S': va->SetForceSolid(true); break;
401 case 'w': va->SetForceWireframe(true); break;
402 case 'i': va->SetVisibility(false); break;
403 case 's': va->SetForceSolid(true); break;
404 }
405 allVisAttributes.insert(va);
406 return va;
407}
408
409G4UserLimits* BDSGeometryFactorySQL::UserLimits(G4double maxStepLength)
410{
411 return BDS::CreateUserLimits(BDSGlobalConstants::Instance()->DefaultUserLimits(), maxStepLength);
412}
413
414//Set logical volume attributes
415void BDSGeometryFactorySQL::SetLogVolAtt(G4LogicalVolume* logVol, G4double k)
416{
417 logVol->SetVisAttributes(VisAtt());
418 logVol->SetUserLimits(UserLimits(k));
419 SetLogVolRegion(logVol);
420}
421
422void BDSGeometryFactorySQL::SetLogVolRegion(G4LogicalVolume* logVol)
423{
424 G4Region* region = nullptr;
425 if(PrecisionRegion)
426 {
427 G4cout << "Approximation region should be define in gmad syntax now!" << G4endl;
428 region = BDSAcceleratorModel::Instance()->Region("precision");
429 }
430 if(ApproximationRegion)
431 {
432 G4cout << "Approximation region should be define in gmad syntax now!" << G4endl;
433 region = BDSAcceleratorModel::Instance()->Region("approximation");
434 }
435 if (region)
436 {
437 logVol->SetRegion(region);
438 region->AddRootLogicalVolume(logVol);
439 }
440}
441
442G4LogicalVolume* BDSGeometryFactorySQL::BuildCone(BDSMySQLTable* aSQLTable, G4int k)
443{
444 G4double length;
445 G4double rInnerStart;
446 G4double rInnerEnd;
447 G4double rOuterStart;
448 G4double rOuterEnd;
449 G4double sphi;
450 G4double dphi;
451
452 //Defaults
453 sphi =0.0;
454 dphi = CLHEP::twopi*CLHEP::radian;
455 length = rOuterStart = rOuterEnd = 10.*CLHEP::mm;
456 rInnerStart = rInnerEnd = 0.0;
457
458 AssignVariable(aSQLTable,k,"LENGTH",length);
459 AssignVariable(aSQLTable,k,"RINNERSTART",rInnerStart);
460 AssignVariable(aSQLTable,k,"RINNEREND" ,rInnerEnd);
461 AssignVariable(aSQLTable,k,"ROUTERSTART",rOuterStart);
462 AssignVariable(aSQLTable,k,"ROUTEREND" ,rOuterEnd);
463 AssignVariable(aSQLTable,k,"STARTPHI",sphi);
464 AssignVariable(aSQLTable,k,"DELTAPHI",dphi);
465
466 G4Cons* aCone = new G4Cons(Name+"_Cone",
467 rInnerStart,
468 rOuterStart,
469 rInnerEnd,
470 rOuterEnd,
471 length/2,
472 sphi,
473 dphi);
474 allSolids.insert(aCone);
475
476 G4double maxR = std::max(rOuterStart, rOuterEnd);
477 unShiftedExtents[aCone] = BDSExtent(maxR, maxR, length*0.5);
478
479 G4LogicalVolume* aConeVol = new G4LogicalVolume(aCone,
480 BDSMaterials::Instance()->GetMaterial(Material),
481 Name+"_LogVol");
482
483 lengthUserLimit=length;
484 return aConeVol;
485}
486
487G4LogicalVolume* BDSGeometryFactorySQL::BuildEllipticalCone(BDSMySQLTable* aSQLTable, G4int k)
488{
489 G4double lengthZ = 0;
490 G4double pxSemiAxis = 0;
491 G4double pySemiAxis = 0;
492 G4double pzTopCut = 0;
493
494 //Defaults
495 lengthZ = 10.*CLHEP::mm;
496
497 AssignVariable(aSQLTable,k,"LENGTHZ",lengthZ);
498 AssignVariable(aSQLTable,k,"XSEMIAXIS",pxSemiAxis);
499 AssignVariable(aSQLTable,k,"YSEMIAXIS",pySemiAxis);
500 AssignVariable(aSQLTable,k,"ZCUT",pzTopCut);
501
502 G4EllipticalCone* aEllipticalCone = new G4EllipticalCone(Name+"_EllipticalCone",
503 pxSemiAxis,
504 pySemiAxis,
505 lengthZ/2,
506 pzTopCut);
507 allSolids.insert(aEllipticalCone);
508
509 G4double maxX = pxSemiAxis*lengthZ*0.5;
510 G4double maxY = pySemiAxis*lengthZ*0.5;
511 unShiftedExtents[aEllipticalCone] = BDSExtent(maxX, maxY, lengthZ*0.5);
512
513 G4LogicalVolume* aEllipticalConeVol =
514 new G4LogicalVolume(aEllipticalCone,
515 BDSMaterials::Instance()->GetMaterial(Material),
516 Name+"_LogVol");
517
518 lengthUserLimit=lengthZ*0.5;
519 return aEllipticalConeVol;
520}
521
522G4LogicalVolume* BDSGeometryFactorySQL::BuildPolyCone(BDSMySQLTable* aSQLTable, G4int k)
523{
524 G4int numZplanes;
525 G4double sphi;
526 G4double dphi;
527
528 //Defaults
529 sphi = 0.0;
530 dphi = CLHEP::twopi*CLHEP::radian;
531 numZplanes = 0;
532
533 AssignVariable(aSQLTable,k,"NZPLANES",numZplanes);
534
535 std::vector<G4double> rInner = std::vector<G4double>(numZplanes+1);
536 std::vector<G4double> rOuter = std::vector<G4double>(numZplanes+1);
537 std::vector<G4double> zPos = std::vector<G4double>(numZplanes+1);
538
539 for (G4int planenum=0; planenum<numZplanes; planenum++)
540 {
541 G4String rInner_ID = "RINNER" + std::to_string(planenum+1);
542 G4String rOuter_ID = "ROUTER" + std::to_string(planenum+1);
543 G4String zPos_ID = "PLANEPOS" + std::to_string(planenum+1);
544
545 AssignVariable(aSQLTable,k,rInner_ID,rInner[planenum]);
546 AssignVariable(aSQLTable,k,rOuter_ID,rOuter[planenum]);
547 AssignVariable(aSQLTable,k,zPos_ID ,zPos[planenum]);
548 }
549
550 AssignVariable(aSQLTable,k,"STARTPHI",sphi);
551 AssignVariable(aSQLTable,k,"DELTAPHI",dphi);
552
553 G4Polycone* aPolyCone = new G4Polycone(Name+"_PolyCone",
554 sphi,
555 dphi,
556 numZplanes,
557 zPos.data(),
558 rInner.data(),
559 rOuter.data());
560 allSolids.insert(aPolyCone);
561
562 G4double maxR = *std::max_element(rOuter.begin(), rOuter.end());
563 G4double maxZ = *std::max_element(zPos.begin(), zPos.end());
564 unShiftedExtents[aPolyCone] = BDSExtent(maxR, maxR, maxZ);
565
566 G4LogicalVolume* aPolyConeVol =
567 new G4LogicalVolume(aPolyCone,
568 BDSMaterials::Instance()->GetMaterial(Material),
569 Name+"_LogVol");
570
571 lengthUserLimit=fabs(zPos[0]-zPos[numZplanes-1])/2;
572
573 return aPolyConeVol;
574}
575
576G4LogicalVolume* BDSGeometryFactorySQL::BuildBox(BDSMySQLTable* aSQLTable, G4int k)
577{
578 G4double lengthX;
579 G4double lengthY;
580 G4double lengthZ;
581
582 lengthX = lengthY = lengthZ = 1.*CLHEP::mm;
583
584 AssignVariable(aSQLTable,k,"LENGTHX",lengthX);
585 AssignVariable(aSQLTable,k,"LENGTHY",lengthY);
586 AssignVariable(aSQLTable,k,"LENGTHZ",lengthZ);
587
588 G4Box* aBox = new G4Box(Name+"_Box",
589 lengthX/2,
590 lengthY/2,
591 lengthZ/2);
592 allSolids.insert(aBox);
593
594 unShiftedExtents[aBox] = BDSExtent(lengthX*0.5, lengthY*0.5, lengthZ*0.5);
595
596 G4LogicalVolume* aBoxVol =
597 new G4LogicalVolume(aBox,
598 BDSMaterials::Instance()->GetMaterial(Material),
599 Name+"_LogVol");
600
601 lengthUserLimit = lengthZ;
602 return aBoxVol;
603}
604
605G4LogicalVolume* BDSGeometryFactorySQL::BuildTrap(BDSMySQLTable* aSQLTable, G4int k)
606{
607
608 G4double trapTheta = 0; //Angle between faces of trapezoid
609 G4double lengthXPlus = 0;
610 G4double lengthXMinus = 0;
611 G4double lengthYPlus = 0;
612 G4double lengthYMinus = 0;
613 G4double lengthZ = 0;
614
615 AssignVariable(aSQLTable,k,"TRAPTHETA",trapTheta);
616 AssignVariable(aSQLTable,k,"LENGTHXPLUS" ,lengthXPlus);
617 AssignVariable(aSQLTable,k,"LENGTHXMINUS",lengthXMinus);
618 AssignVariable(aSQLTable,k,"LENGTHYPLUS" ,lengthYPlus);
619 AssignVariable(aSQLTable,k,"LENGTHYMINUS",lengthYMinus);
620 AssignVariable(aSQLTable,k,"LENGTHZ",lengthZ);
621
622 G4Trap* aTrap = new G4Trap(Name+"_Trd",
623 lengthZ/2,
624 trapTheta, 0,
625 lengthYPlus/2,
626 lengthXPlus/2,
627 lengthXPlus/2,
628 0,
629 lengthYMinus/2,
630 lengthXMinus/2,
631 lengthXMinus/2,
632 0);
633 allSolids.insert(aTrap);
634 unShiftedExtents[aTrap] = BDSExtent();
635
636 G4LogicalVolume* aTrapVol =
637 new G4LogicalVolume(aTrap,
638 BDSMaterials::Instance()->GetMaterial(Material),
639 Name+"_LogVol");
640
641 lengthUserLimit = lengthZ*0.5;
642 return aTrapVol;
643}
644
645G4LogicalVolume* BDSGeometryFactorySQL::BuildTorus(BDSMySQLTable* aSQLTable, G4int k)
646{
647 G4double rInner;
648 G4double rOuter;
649 G4double rSwept;
650 G4double sphi;
651 G4double dphi;
652
653 //Defaults
654 rSwept = 20.*CLHEP::mm;
655 rOuter = 10.*CLHEP::mm;
656 rInner = 0.0;
657 sphi = 0.0;
658 dphi=2*CLHEP::pi*CLHEP::radian;
659
660 AssignVariable(aSQLTable,k,"RINNER",rInner);
661 AssignVariable(aSQLTable,k,"ROUTER",rOuter);
662 AssignVariable(aSQLTable,k,"RSWEPT",rSwept);
663 AssignVariable(aSQLTable,k,"ROUTER",rOuter);
664 AssignVariable(aSQLTable,k,"STARTPHI",sphi);
665 AssignVariable(aSQLTable,k,"DELTAPHI",dphi);
666
667 G4Torus* aTorus = new G4Torus(Name+"_Torus",
668 rInner,
669 rOuter,
670 rSwept,
671 sphi,
672 dphi);
673 allSolids.insert(aTorus);
674
675 G4LogicalVolume* aTorusVol =
676 new G4LogicalVolume(aTorus,
677 BDSMaterials::Instance()->GetMaterial(Material),
678 Name+"_LogVol");
679
680 lengthUserLimit = rOuter*0.5;
681 return aTorusVol;
682}
683
684G4LogicalVolume* BDSGeometryFactorySQL::BuildSampler(BDSMySQLTable* aSQLTable, G4int k)
685{
686 G4double length;
687 G4double rInnerStart;
688 G4double rInnerEnd;
689 G4double rOuterStart;
690 G4double rOuterEnd;
691
692 //Defaults
693 length = rOuterStart = rOuterEnd = 10.*CLHEP::mm;
694 rInnerStart = rInnerEnd = 0.0;
695
696 AssignVariable(aSQLTable,k,"LENGTH",length);
697 AssignVariable(aSQLTable,k,"RINNERSTART",rInnerStart);
698 AssignVariable(aSQLTable,k,"RINNEREND" ,rInnerEnd);
699 AssignVariable(aSQLTable,k,"ROUTERSTART",rOuterStart);
700 AssignVariable(aSQLTable,k,"ROUTEREND" ,rOuterEnd);
701
702 if (BDSMySQLVariable* sqlName = aSQLTable->GetVariable("NAME"))
703 {
704 Name = sqlName->GetStrValue(k);
705 sqlName->SetStrValue(k,Name+"_SQL");
706 Name = sqlName->GetStrValue(k);
707 }
708 if(Name=="_SQL")
709 {Name = TableName+std::to_string(k)+"_SQL";}
710 // make sure that each name is unique!
711 Name = itsMarkerVol->GetName()+"_"+Name;
712
713 G4Cons* aSampler = new G4Cons(Name+"_samp",
714 rInnerStart,
715 rOuterStart,
716 rInnerEnd,
717 rOuterEnd,
718 length/2,
719 0,
720 CLHEP::twopi*CLHEP::radian);
721 allSolids.insert(aSampler);
722 G4LogicalVolume* aSamplerVol =
723 new G4LogicalVolume(aSampler,
724 BDSMaterials::Instance()->GetMaterial(Material),
725 Name+"_LogVol");
726
727 lengthUserLimit = length*0.5;
728
729 aSamplerVol->SetSensitiveDetector(BDSSDManager::Instance()->SamplerPlane());
730
731 G4int samplerID = BDSSamplerRegistry::Instance()->RegisterSampler(Name,nullptr);
732
733 samplerIDs[aSamplerVol] = samplerID;
734
735 return aSamplerVol;
736}
737
738G4LogicalVolume* BDSGeometryFactorySQL::BuildTube(BDSMySQLTable* aSQLTable, G4int k)
739{
740 G4double rInner;
741 G4double rOuter;
742 G4double length;
743 G4double sphi;
744 G4double dphi;
745
746 //Defaults
747 length = 100.*CLHEP::mm;
748 rOuter = 10.*CLHEP::mm;
749 rInner = 0.0;
750 sphi = 0.0;
751 dphi=2*CLHEP::pi*CLHEP::radian;
752
753 AssignVariable(aSQLTable,k,"RINNER",rInner);
754 AssignVariable(aSQLTable,k,"ROUTER",rOuter);
755 AssignVariable(aSQLTable,k,"LENGTH",length);
756 AssignVariable(aSQLTable,k,"STARTPHI",sphi);
757 AssignVariable(aSQLTable,k,"DELTAPHI",dphi);
758
759 G4Tubs* aTubs = new G4Tubs(Name+"_Tubs",
760 rInner,
761 rOuter,
762 length/2,
763 sphi,
764 dphi);
765 allSolids.insert(aTubs);
766 G4LogicalVolume* aTubsVol =
767 new G4LogicalVolume(aTubs,
768 BDSMaterials::Instance()->GetMaterial(Material),
769 Name+"_LogVol");
770
771 lengthUserLimit = length*0.5;
772 return aTubsVol;
773}
774
775G4LogicalVolume* BDSGeometryFactorySQL::BuildEllipticalTube(BDSMySQLTable* aSQLTable, G4int k)
776{
777 G4double lengthX;
778 G4double lengthY;
779 G4double lengthZ;
780
781 //Defaults
782 lengthX = 100.*CLHEP::mm;
783 lengthY = 50.*CLHEP::mm;
784 lengthZ = 200.*CLHEP::mm;
785
786 AssignVariable(aSQLTable,k,"LENGTHX",lengthX);
787 AssignVariable(aSQLTable,k,"LENGTHY",lengthY);
788 AssignVariable(aSQLTable,k,"LENGTHZ",lengthZ);
789
790 G4EllipticalTube* aEllipticalTube = new G4EllipticalTube(Name+"_EllipticalTube",
791 lengthX/2,
792 lengthY/2,
793 lengthZ/2
794 );
795
796 allSolids.insert(aEllipticalTube);
797 G4LogicalVolume* aEllipticalTubeVol =
798 new G4LogicalVolume(aEllipticalTube,
799 BDSMaterials::Instance()->GetMaterial(Material),
800 Name+"_LogVol");
801 G4double maxLength = lengthX;
802 if (lengthY>lengthX&&lengthY>lengthZ)
803 {maxLength = lengthY;}
804 else if(lengthZ>lengthY&&lengthZ>lengthX)
805 {maxLength = lengthZ;}
806 lengthUserLimit = maxLength*0.5;
807 return aEllipticalTubeVol;
808}
809
810/*
811G4LogicalVolume* BDSGeometryFactorySQL::BuildPCLTube(BDSMySQLTable* aSQLTable, G4int k)
812{
813 G4double aperX;
814 G4double aperYUp;
815 G4double aperYDown;
816 G4double aperDy;
817 G4double thickness;
818 G4double length;
819
820 //Defaults
821 aperX = 100.*CLHEP::mm;
822 aperYUp = 50.*CLHEP::mm;
823 aperYDown = 200.*CLHEP::mm;
824 aperDy = 0.*CLHEP::mm;
825 thickness = BDSGlobalConstants::Instance()->DefaultBeamPipeModel()->beamPipeThickness;
826 length = 200.0*CLHEP::mm;
827
828 if(aSQLTable->GetVariable("APERX")!=nullptr)
829 aperX = aSQLTable->GetVariable("APERX")->GetDblValue(k);
830 if(aSQLTable->GetVariable("APERYUP")!=nullptr)
831 aperYUp = aSQLTable->GetVariable("APERYUP")->GetDblValue(k);
832 if(aSQLTable->GetVariable("APERYDOWN")!=nullptr)
833 aperYDown = aSQLTable->GetVariable("APERYDOWN")->GetDblValue(k);
834 if(aSQLTable->GetVariable("APERDY")!=nullptr)
835 aperDy = aSQLTable->GetVariable("APERDY")->GetDblValue(k);
836 if(aSQLTable->GetVariable("THICKNESS")!=nullptr)
837 thickness = aSQLTable->GetVariable("THICKNESS")->GetDblValue(k);
838 if(aSQLTable->GetVariable("LENGTH")!=nullptr)
839 length = aSQLTable->GetVariable("LENGTH")->GetDblValue(k);
840
841 BDSPCLTube* aPCLTubeBuilder = new BDSPCLTube(aperX, aperYUp, aperYDown, aperDy, thickness, length, Name+"_PCLTube");
842 G4VSolid* aPCLTube = aPCLTubeBuilder->GetSolid();
843 delete aPCLTubeBuilder;
844
845 G4LogicalVolume* aPCLTubeVol =
846 new G4LogicalVolume(aPCLTube,
847 BDSMaterials::Instance()->GetMaterial(Material),
848 Name+"_LogVol");
849 G4double totalYLength = aperDy+aperYUp+aperYDown+thickness;
850 G4double totalXLength = aperX+thickness;
851 G4double maxLength = length;
852 if (totalYLength>length&&totalYLength>totalXLength){
853 maxLength = totalYLength;
854 }
855 else if(totalXLength>totalYLength&&totalXLength>length){
856 maxLength = totalXLength;
857 }
858 lengthUserLimit = maxLength*0.5;
859 return aPCLTubeVol;
860}
861*/
862
863G4RotationMatrix* BDSGeometryFactorySQL::RotateComponent(G4double psi,G4double phi,G4double theta)
864{
865 rotateComponent = new G4RotationMatrix;
866 if(psi==0 && phi==0 && theta==0)
867 {return rotateComponent;}
868
869 G4RotationMatrix* LocalRotation = new G4RotationMatrix;
870 G4ThreeVector* localX = new G4ThreeVector(1.,0.,0.);
871 G4ThreeVector* localY = new G4ThreeVector(0.,1.,0.);
872 G4ThreeVector* localZ = new G4ThreeVector(0.,0.,1.);
873
874 LocalRotation->rotate(psi,*localZ);
875 localX->rotate(psi,*localZ);
876 localY->rotate(psi,*localZ);
877
878 LocalRotation->rotate(phi,*localY);
879 localX->rotate(phi,*localY);
880 localZ->rotate(phi,*localY);
881
882 LocalRotation->rotate(theta,*localX);
883 localY->rotate(theta,*localX);
884 localZ->rotate(theta,*localX);
885
886 rotateComponent->transform(*LocalRotation);
887 rotateComponent->invert();
888
889 return rotateComponent;
890}
891
893 std::vector<G4LogicalVolume*> VOL_LISTIn)
894{
895 for (G4int k=0; k<NVariables; k++) // Now run through and place according to
896 {
897 SetPlacementParams(aSQLTable, k);
898 G4int PARENTID=0;
899 if(!PARENTNAME.empty())
900 {
901 PARENTNAME+="_LogVol";
902 for (G4int i=0; i<(G4int)VOL_LISTIn.size(); i++)
903 {
904#if G4VERSION_NUMBER > 1099
905 if (G4StrUtil::icompare(PARENTNAME, VOL_LISTIn[i]->GetName()) == 0)
906#else
907 if(PARENTNAME.compareTo(VOL_LISTIn[i]->GetName(), G4String::ignoreCase)==0)
908#endif
909 {
910 PARENTID = i;
911 continue;
912 }
913 }
914 }
915
916 // to being in line with logvol names (needed for name checking loop
917 G4String tmpname = Name+"_LogVol";
918 G4int ID=0;
919 for (G4int i=0; i<(G4int)VOL_LISTIn.size(); i++)
920 {
921#if G4VERSION_NUMBER > 1099
922 if (G4StrUtil::icompare(tmpname, VOL_LISTIn[i]->GetName()) == 0)
923#else
924 if(tmpname.compareTo(VOL_LISTIn[i]->GetName(), G4String::ignoreCase)==0)
925#endif
926 {
927 ID = i;
928 continue;
929 }
930 }
931
932 if(SetSensitive)
933 {sensitiveComponents.insert(VOL_LISTIn[ID]);}
934 G4ThreeVector PlacementPoint(PosX,PosY,PosZ);
935
936 if(!InheritStyle.empty())
937 { //True if InheritStyle is set
938#if G4VERSION_NUMBER > 1099
939 if (G4StrUtil::icompare(InheritStyle, "SUBTRACT") == 0)
940#else
941 if(InheritStyle.compareTo("SUBTRACT", G4String::ignoreCase)==0)
942#endif
943 {
944 G4VSolid* original = VOL_LISTIn[PARENTID]->GetSolid();
945 G4VSolid* sub = VOL_LISTIn[ID]->GetSolid();
946 VOL_LISTIn[PARENTID]->SetSolid(new G4SubtractionSolid(VOL_LISTIn[PARENTID]->GetName(),
947 original,
948 sub,
949 RotateComponent(RotPsi,RotPhi,RotTheta),
950 PlacementPoint));
951
952 }
953#if G4VERSION_NUMBER > 1099
954 if (G4StrUtil::icompare(InheritStyle, "INTERSECT") == 0)
955#else
956 else if(InheritStyle.compareTo("INTERSECT", G4String::ignoreCase)==0)
957#endif
958 {
959 G4VSolid* original = VOL_LISTIn[PARENTID]->GetSolid();
960 G4VSolid* sub = VOL_LISTIn[ID]->GetSolid();
961 VOL_LISTIn[PARENTID]->SetSolid(new G4IntersectionSolid(VOL_LISTIn[PARENTID]->GetName(),
962 original,
963 sub,
964 RotateComponent(RotPsi,RotPhi,RotTheta),
965 PlacementPoint));
966
967 }
968#if G4VERSION_NUMBER > 1099
969 if (G4StrUtil::icompare(InheritStyle, "UNION") == 0)
970#else
971 else if(InheritStyle.compareTo("UNION", G4String::ignoreCase)==0)
972#endif
973 {
974 G4VSolid* original = VOL_LISTIn[PARENTID]->GetSolid();
975 G4VSolid* sub = VOL_LISTIn[ID]->GetSolid();
976 VOL_LISTIn[PARENTID]->SetSolid(new G4UnionSolid(VOL_LISTIn[PARENTID]->GetName(),
977 original,
978 sub,
979 RotateComponent(RotPsi,RotPhi,RotTheta),
980 PlacementPoint));
981 }
982 }
983
984#ifdef BDSDEBUG
985 G4cout << __METHOD_NAME__ << " k = " << k << ", volume = " << VOL_LISTIn[ID]->GetName() << G4endl;
986#endif
987
988 G4LogicalVolume* volume = VOL_LISTIn[ID];
989 G4int copyNumber = 0;
990 auto result = samplerIDs.find(volume);
991 if (result != samplerIDs.end())
992 {copyNumber = result->second;}
993
995 G4VSolid* solid = volume->GetSolid();
996 BDSExtent ext = unShiftedExtents[solid];
997 BDSExtent extShifted = ext.Translate(PlacementPoint);
998 ExpandExtent(extShifted);
999
1000 G4VPhysicalVolume* PhysiComp =
1001 new G4PVPlacement(RotateComponent(RotPsi,RotPhi,RotTheta),
1002 PlacementPoint,
1003 VOL_LISTIn[ID],
1004 Name,
1005 VOL_LISTIn[PARENTID],
1006 false,
1007 copyNumber,
1008 BDSGlobalConstants::Instance()->CheckOverlaps());
1009 if(align_in)
1010 {
1011 // Make sure program stops and informs user if more than one alignment vol.
1012 if(alignInVolume)
1013 {
1014 G4cerr<<"\nBDSGeometryFactorySQL.cc:486: Trying to align in-beam to SQL volume to " << PhysiComp->GetName() << " but alignment already set to " << alignInVolume->GetName() << G4endl;
1015 G4Exception("Aborting Program", "-1", FatalException, "");
1016
1017 }
1018 else
1019 {alignInVolume = PhysiComp;}
1020 }
1021
1022 if(align_out)
1023 {
1024 if(alignOutVolume)
1025 {
1026 G4cerr<<"\nBDSGeometryFactorySQL.cc:486: Trying to align out-beam to SQL volume to " << PhysiComp->GetName() << " but alignment already set to " << alignOutVolume->GetName() << G4endl;
1027 G4Exception("Aborting Program", "-1", FatalException, "");
1028 }
1029 else
1030 {alignOutVolume = PhysiComp;}
1031 }
1032
1033 // magnetic rigidity brho
1034 G4double brho = defaultRigidity;
1035#if G4VERSION_NUMBER > 1099
1036 if (G4StrUtil::icompare(MagType, "QUAD") == 0)
1037#else
1038 if(MagType.compareTo("QUAD", G4String::ignoreCase)==0)
1039#endif
1040 {
1041 //hasFields = true;
1042 //nPoleField = 1;
1043 QuadBgrad.push_back(- brho * K1 / CLHEP::m2);
1044 Quadvol.push_back(PhysiComp->GetName());
1045 quadVolBgrad[PhysiComp->GetName()]=(- brho * K1 / CLHEP::m2);
1046 }
1047#if G4VERSION_NUMBER > 1099
1048 if (G4StrUtil::icompare(MagType, "SEXT") == 0)
1049#else
1050 if(MagType.compareTo("SEXT", G4String::ignoreCase)==0)
1051#endif
1052 {
1053 //hasFields = true;
1054 //nPoleField = 2;
1055 SextBgrad.push_back(- brho * K2 / CLHEP::m3);
1056 Sextvol.push_back(PhysiComp->GetName());
1057 sextVolBgrad[PhysiComp->GetName()]=(- brho * K2 / CLHEP::m3);
1058 }
1059#if G4VERSION_NUMBER > 1099
1060 if (G4StrUtil::icompare(MagType, "OCT") == 0)
1061#else
1062 if(MagType.compareTo("OCT", G4String::ignoreCase)==0)
1063#endif
1064 {
1065 //hasFields = true;
1066 //nPoleField = 3;
1067 OctBgrad.push_back(- brho * K3 / (CLHEP::m2*CLHEP::m2));
1068 Octvol.push_back(PhysiComp->GetName());
1069 octVolBgrad[PhysiComp->GetName()]=(- brho * K3 / (CLHEP::m2*CLHEP::m2));
1070 }
1071
1072 if(FieldX || FieldY || FieldZ) //if any vols have non-zero field components
1073 {
1074 //hasFields = true;
1075 //hasUniformField=true;
1076#ifdef BDSDEBUG
1077 G4cout << "BDSGeometryFactorySQL> volume " << PhysiComp->GetName() << " has the following uniform field: " << FieldX << " " << FieldY << " " << FieldZ << " " << G4endl;
1078#endif
1079 UniformField.emplace_back(G4ThreeVector(FieldX*CLHEP::tesla,
1080 FieldY*CLHEP::tesla,
1081 FieldZ*CLHEP::tesla));
1082 Fieldvol.push_back(PhysiComp->GetName());
1083 uniformFieldVolField[PhysiComp->GetName()]=G4ThreeVector(FieldX*CLHEP::tesla,
1084 FieldY*CLHEP::tesla,
1085 FieldZ*CLHEP::tesla);
1086 }
1087 }
1088}
G4Region * Region(const G4String &name) const
Access region information. Will exit if not found.
General exception with possible name of object and message.
Definition: BDSException.hh:35
Holder for +- extents in 3 dimensions.
Definition: BDSExtent.hh:39
BDSExtent Translate(const G4ThreeVector &offset) const
Provide a new copy of this extent with an offset applied.
Definition: BDSExtent.hh:125
void RegisterRotationMatrix(G4RotationMatrix *rotationMatrix)
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
void RegisterPhysicalVolume(G4VPhysicalVolume *physicalVolume)
void RegisterVisAttributes(G4VisAttributes *visAttribute)
void RegisterSolid(G4VSolid *solid)
A loaded piece of externally provided geometry.
void ExpandExtent(const BDSExtent &extent)
Expand the acuumulated extents using a (possibly asymmetric) extent instance.
virtual void CleanUp()
Virtual clean up that derived classes can override that calls CleanUpBase().
virtual std::set< G4VisAttributes * > ApplyColourMapping(std::set< G4LogicalVolume * > &lvs, std::map< G4String, G4Colour * > *mapping, G4bool autoColour, const G4String &preprocessPrefix="")
void PlaceComponents(BDSMySQLTable *aSQLTable, std::vector< G4LogicalVolume * > VOL_LIST)
void CleanUpSQL()
Non-virtual clean up as used in constructor.
virtual BDSGeometryExternal * Build(G4String componentName, G4String fileName, std::map< G4String, G4Colour * > *colourMapping=nullptr, G4bool autoColour=true, G4double suggestedLength=0, G4double suggestedHorizontalWidth=0, std::vector< G4String > *vacuumBiasVolumeNames=nullptr, G4bool makeSensitive=true, BDSSDType sensitivityType=BDSSDType::energydep, BDSSDType vacuumSensitivityType=BDSSDType::energydepvacuum, G4UserLimits *userLimitsToAttachToAllLVs=nullptr)
void AssignVariable(BDSMySQLTable *aSQLTable, G4int k, G4String variableName, T &variable)
Search SQL table for variableName and if exists assign to variable.
virtual void CleanUp()
Clean up members.
static G4double defaultRigidity
Cache of default rigidity for possibly constructing fields (only SQL)
std::map< G4LogicalVolume *, G4int > samplerIDs
static BDSGlobalConstants * Instance()
Access method.
static BDSMaterials * Instance()
Singleton pattern access.
Definition: BDSMaterials.cc:39
G4Material * GetMaterial(G4String material) const
Get material by name.
Representation of a mysql table.
A variable representation for mysql loader.
G4double GetDblValue(G4int itemN) const
Accessor.
G4int GetIntValue(G4int itemN) const
Accessor.
G4String GetStrValue(G4int itemN) const
Accessor.
Wrapper for mysql file handling.
static BDSSamplerRegistry * Instance()
Accessor for registry.
G4int RegisterSampler(const G4String &name, BDSSampler *sampler, const G4Transform3D &transform=G4Transform3D(), G4double S=-1000, const BDSBeamlineElement *element=nullptr, BDSSamplerType type=BDSSamplerType::plane, G4double radius=0)
Improve type-safety of native enum data type in C++.
G4bool StrContains(const G4String &str, const G4String &test)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
Definition: BDSUtilities.cc:66
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4UserLimits * CreateUserLimits(G4UserLimits *defaultUL, G4double length, G4double fraction=1.6)
G4int StrCompare(const G4String &str, const G4String &, G4String::caseCompare mode=G4String::ignoreCase)
Utility function to simplify lots of syntax changes for pedantic g4 changes.
Definition: BDSUtilities.cc:75