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