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