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