00001
00002
00003
00004
00005
00006
00007 #include "BDSAcceleratorComponent.hh"
00008 #include "BDSDebug.hh"
00009 #include "BDSExecOptions.hh"
00010 #include "BDSElement.hh"
00011 #include "BDSGlobalConstants.hh"
00012 #include "BDS3DMagField.hh"
00013 #include "BDSXYMagField.hh"
00014 #include "BDSMagFieldSQL.hh"
00015 #include "G4Box.hh"
00016 #include "G4Tubs.hh"
00017 #include "G4Torus.hh"
00018 #include "G4Trd.hh"
00019 #include "G4VisAttributes.hh"
00020 #include "G4LogicalVolume.hh"
00021 #include "G4VPhysicalVolume.hh"
00022 #include "G4PVPlacement.hh"
00023 #include "G4UserLimits.hh"
00024 #include "G4Mag_UsualEqRhs.hh"
00025
00026 #include "G4NystromRK4.hh"
00027
00028
00029 #include "ggmad.hh"
00030 #include "BDSGeometrySQL.hh"
00031
00032 #ifdef USE_LCDD
00033 #include "BDSGeometryLCDD.hh"
00034 #endif
00035
00036 #ifdef USE_GDML
00037 #include "BDSGeometryGDML.hh"
00038 #endif
00039
00040 #include <vector>
00041
00042 class BDSTiltOffset;
00043
00044 BDSElement::BDSElement(G4String name,
00045 G4double length,
00046 G4String geometry,
00047 G4String bmap,
00048 G4double bmapZOffset,
00049 BDSTiltOffset tiltOffset):
00050 BDSAcceleratorComponent(name, length, 0, "element", tiltOffset),
00051 itsGeometry(geometry), itsBmap(bmap),
00052 fChordFinder(NULL), itsFStepper(NULL), itsFEquation(NULL), itsEqRhs(NULL),
00053 itsMagField(NULL), itsCachedMagField(NULL), itsUniformMagField(NULL)
00054 {
00055 itsFieldVolName="";
00056 itsFieldIsUniform=false;
00057 itsBmapZOffset = bmapZOffset;
00058
00059
00060
00061 align_in_volume = NULL;
00062 align_out_volume = NULL;
00063 }
00064
00065 void BDSElement::BuildContainerLogicalVolume()
00066 {
00067 #ifdef BDSDEBUG
00068 G4cout << __METHOD_NAME__ << " building geometry of element named: \""
00069 << name << "\"" << G4endl;
00070 #endif
00071 BuildGeometry();
00072
00073 #ifdef BDSDEBUG
00074 G4cout << __METHOD_NAME__ << "completed geometry construction " << G4endl;
00075 #endif
00076
00077 PlaceComponents(itsGeometry,itsBmap);
00078 }
00079
00080 void BDSElement::BuildElementMarkerLogicalVolume()
00081 {
00082 #ifdef BDSDEBUG
00083 G4cout << __METHOD_NAME__ <<G4endl;
00084 #endif
00085
00086
00087
00088 G4double outerDiameter = 10*CLHEP::m;
00089 G4double elementSizeX = outerDiameter*0.5 + lengthSafety;
00090 G4double elementSizeY = outerDiameter*0.5 + lengthSafety;
00091
00092 G4double elementSize=std::max(elementSizeX, elementSizeY);
00093
00094 containerSolid = new G4Box(name + "_container_solid",
00095 elementSize,
00096 elementSize,
00097 chordLength*0.5);
00098
00099 containerLogicalVolume = new G4LogicalVolume(containerSolid,
00100 emptyMaterial,
00101 name + "_container_lv");
00102
00103 #ifdef BDSDEBUG
00104 G4cout << __METHOD_NAME__ << "container volume dimensions: x, y = "<< elementSize/CLHEP::m
00105 <<" m, l = "<< chordLength/CLHEP::m <<" m"<<G4endl;
00106 #endif
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 G4UserLimits* itsMarkerUserLimits = new G4UserLimits(DBL_MAX,DBL_MAX,DBL_MAX, BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00171 G4double maxStepFactor=5;
00172 itsMarkerUserLimits->SetMaxAllowedStep(chordLength*maxStepFactor);
00173 containerLogicalVolume->SetUserLimits(itsMarkerUserLimits);
00174
00175
00176
00177
00178
00179 containerLogicalVolume->
00180 SetFieldManager(BDSGlobalConstants::Instance()->GetZeroFieldManager(),false);
00181 }
00182
00183 void BDSElement::BuildGeometry()
00184 {
00185
00186
00187
00188 BuildElementMarkerLogicalVolume();
00189
00190 #ifndef NOUSERLIMITS
00191 G4UserLimits* itsOuterUserLimits = new G4UserLimits();
00192 G4double stepfactor=5;
00193 itsOuterUserLimits->SetMaxAllowedStep(chordLength*stepfactor);
00194 itsOuterUserLimits->SetUserMaxTime(BDSGlobalConstants::Instance()->GetMaxTime());
00195 if(BDSGlobalConstants::Instance()->GetThresholdCutCharged()>0){
00196 itsOuterUserLimits->SetUserMinEkine(BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00197 }
00198 containerLogicalVolume->SetUserLimits(itsOuterUserLimits);
00199 #endif
00200 }
00201
00202
00203 void BDSElement::PlaceComponents(G4String geometry, G4String bmap)
00204 {
00205
00206 G4String gFormat="", bFormat="";
00207 G4String gFile="", bFile="";
00208
00209
00210 if(geometry != ""){
00211 G4int pos = geometry.find(":");
00212 gFormat="none";
00213 if(pos<0) {
00214 G4cerr<<"WARNING: invalid geometry reference format : "<<geometry<<G4endl;
00215 }
00216 else {
00217 gFormat = geometry.substr(0,pos);
00218 gFile = BDSExecOptions::Instance()->GetBDSIMPATH() + geometry.substr(pos+1,geometry.length() - pos);
00219 }
00220 }
00221
00222
00223 bFormat="none";
00224 if(bmap != ""){
00225 G4int pos = bmap.find(":");
00226 if(pos<0) {
00227 G4cerr<<"WARNING: invalid B map reference format : "<<bmap<<G4endl;
00228 }
00229 else {
00230 bFormat = bmap.substr(0,pos);
00231 bFile = BDSExecOptions::Instance()->GetBDSIMPATH() + bmap.substr(pos+1,bmap.length() - pos);
00232 #ifdef BDSDEBUG
00233 G4cout << "BDSElement::PlaceComponents bmap file is " << bFile << G4endl;
00234 #endif
00235 }
00236 }
00237
00238 #ifdef BDSDEBUG
00239 G4cout<<"placing components:\n geometry format - "<<gFormat<<G4endl<<
00240 "file - "<<gFile<<G4endl;
00241 G4cout<<"bmap format - "<<bFormat<<G4endl<<
00242 "file - "<<bFile<<G4endl;
00243 #endif
00244
00245
00246
00247
00248
00249
00250 if(gFormat=="gmad") {
00251 GGmadDriver *ggmad = new GGmadDriver(gFile);
00252 ggmad->Construct(containerLogicalVolume);
00253
00254
00255
00256 RegisterSensitiveVolume(containerLogicalVolume);
00257
00258
00259 if(bFormat=="3D"){
00260 #ifdef BDSDEBUG
00261 G4cout << "BDSElement.cc> Making BDS3DMagField..." << G4endl;
00262 #endif
00263
00264 itsMagField = new BDS3DMagField(bFile, itsBmapZOffset);
00265 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00266 BuildMagField(true);
00267 }else if(bFormat=="XY"){
00268 itsMagField = new BDSXYMagField(bFile);
00269 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00270
00271
00272 BuildMagField(true);
00273 }
00274 delete ggmad;
00275 }
00276 else if(gFormat=="lcdd") {
00277 #ifdef USE_LCDD
00278 BDSGeometryLCDD *LCDD = new BDSGeometryLCDD(gFile);
00279
00280 G4VisAttributes* VisAttLCDD = new G4VisAttributes(G4Colour(0.0, 1.0, 0.0));
00281 VisAttLCDD->SetForceSolid(true);
00282 VisAttLCDD->SetVisibility(false);
00283 containerLogicalVolume->SetVisAttributes(VisAttLCDD);
00284
00285 LCDD->Construct(containerLogicalVolume);
00286 RegisterSensitiveVolume(containerLogicalVolume);
00287 if(bFormat=="XY"){
00288 itsMagField = new BDSXYMagField(bFile);
00289 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00290
00291
00292 BuildMagField(true);
00293 } else if ( bFormat == "mokka" ){
00294 G4ThreeVector uniField = G4ThreeVector(0,3.5*CLHEP::tesla,0);
00295 std::vector<G4ThreeVector> uniFieldVect;
00296 uniFieldVect.push_back(uniField);
00297 std::vector<G4double> nulld;
00298 std::vector<G4String> nulls;
00299
00300 } else if ( bFormat == "test" ){
00301 }
00302 else if ( bFormat == "none" ){
00303 itsFieldIsUniform=LCDD->GetFieldIsUniform();
00304 if(itsFieldIsUniform){
00305 G4cout << "BDSElement> using LCDD format uniform field..." << G4endl;
00306 itsUniformMagField=LCDD->GetUniformField();
00307 }else{
00308 itsMagField=LCDD->GetField();
00309 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00310
00311 }
00312 itsFieldVolName=LCDD->GetFieldVolName();
00313 BuildMagField(true);
00314 }
00315
00316 RegisterSensitiveVolumes(LCDD->SensitiveComponents);
00317 delete LCDD;
00318 #else
00319 G4cout << "LCDD support not selected during BDSIM configuration" << G4endl;
00320 G4Exception("Please re-compile BDSIM with USE_LCDD flag", "-1", FatalException, "");
00321 #endif
00322 }
00323 else if(gFormat=="mokka") {
00324 #ifdef BDSDEBUG
00325 G4cout << "BDSElement.cc: loading geometry sql file: BDSGeometrySQL(" << gFile << "," << chordLength << ")" << G4endl;
00326 #endif
00327 BDSGeometrySQL *Mokka = new BDSGeometrySQL(gFile,chordLength,containerLogicalVolume);
00328 for(unsigned int i=0; i<Mokka->GetMultiplePhysicalVolumes().size(); i++){
00329 SetMultiplePhysicalVolumes(Mokka->GetMultiplePhysicalVolumes().at(i));
00330 }
00331
00332 RegisterSensitiveVolumes(Mokka->SensitiveComponents);
00333
00334 std::vector<G4LogicalVolume*> GFlashComps =Mokka->itsGFlashComponents;
00335 for(G4int id=0; id<(G4int)GFlashComps.size(); id++)
00336 SetGFlashVolumes(GFlashComps[id]);
00337
00338 align_in_volume = Mokka->align_in_volume;
00339 align_out_volume = Mokka->align_out_volume;
00340
00341
00342 if(bFormat=="3D"){
00343 #ifdef BDSDEBUG
00344 G4cout << "BDSElement.cc> Making BDS3DMagField..." << G4endl;
00345 #endif
00346 itsMagField = new BDS3DMagField(bFile, 0);
00347 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00348
00349 BuildMagField(true);
00350 } else if(bFormat=="XY"){
00351 itsMagField = new BDSXYMagField(bFile);
00352 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00353
00354
00355 BuildMagField(true);
00356 } else if(bFormat=="mokka" || bFormat=="none")
00357 {
00358 if(Mokka->HasFields || bFile!="")
00359
00360
00361
00362 {
00363 itsMagField = new BDSMagFieldSQL(bFile,chordLength,
00364 Mokka->QuadVolBgrad,
00365 Mokka->SextVolBgrad,
00366 Mokka->OctVolBgrad,
00367 Mokka->UniformFieldVolField,
00368 Mokka->nPoleField,
00369 Mokka->HasUniformField);
00370 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00371
00372
00373
00374 BuildMagField(true);
00375 }
00376 }
00377 delete Mokka;
00378 }
00379 else if(gFormat=="gdml") {
00380 #ifdef USE_GDML
00381 BDSGeometryGDML *GDML = new BDSGeometryGDML(gFile);
00382 GDML->Construct(containerLogicalVolume);
00383 delete GDML;
00384 #else
00385 G4cout << "GDML support not selected during BDSIM configuration" << G4endl;
00386 G4Exception("Please re-compile BDSIM with USE_GDML flag", "-1", FatalException, "");
00387 #endif
00388 }
00389 else {
00390 G4cerr<<"geometry format "<<gFormat<<" not supported"<<G4endl;
00391 }
00392 }
00393
00394 void BDSElement::BuildMagField(G4bool forceToAllDaughters)
00395 {
00396 #ifdef BDSDEBUG
00397 G4cout << "BDSElement.cc::BuildMagField Building magnetic field...." << G4endl;
00398 #endif
00399
00400 G4FieldManager* fieldManager = new G4FieldManager();
00401
00402
00403 if(!itsFieldIsUniform){
00404 #ifdef BDSDEBUG
00405 G4cout << "BDSElement.cc> Building magnetic field..." << G4endl;
00406 #endif
00407 itsEqRhs = new G4Mag_UsualEqRhs(itsCachedMagField);
00408 if( (itsMagField->GetHasUniformField())&!(itsMagField->GetHasNPoleFields() || itsMagField->GetHasFieldMap())){
00409 itsFStepper = new G4NystromRK4(itsEqRhs);
00410 } else {
00411 itsFStepper = new G4NystromRK4(itsEqRhs);
00412 }
00413 fieldManager->SetDetectorField(itsCachedMagField );
00414 } else {
00415 #ifdef BDSDEBUG
00416 G4cout << "BDSElement.cc> Building uniform magnetic field..." << G4endl;
00417 #endif
00418 itsEqRhs = new G4Mag_UsualEqRhs(itsUniformMagField);
00419 itsFStepper = new G4NystromRK4(itsEqRhs);
00420 fieldManager->SetDetectorField(itsUniformMagField );
00421 }
00422
00423 #ifdef BDSDEBUG
00424 G4cout << "BDSElement.cc> Setting stepping accuracy parameters..." << G4endl;
00425 #endif
00426
00427 if(BDSGlobalConstants::Instance()->GetDeltaOneStep()>0){
00428 fieldManager->SetDeltaOneStep(BDSGlobalConstants::Instance()->GetDeltaOneStep());
00429 }
00430 if(BDSGlobalConstants::Instance()->GetMaximumEpsilonStep()>0){
00431 fieldManager->SetMaximumEpsilonStep(BDSGlobalConstants::Instance()->GetMaximumEpsilonStep());
00432 }
00433 if(BDSGlobalConstants::Instance()->GetMinimumEpsilonStep()>=0){
00434 fieldManager->SetMinimumEpsilonStep(BDSGlobalConstants::Instance()->GetMinimumEpsilonStep());
00435 }
00436 if(BDSGlobalConstants::Instance()->GetDeltaIntersection()>0){
00437 fieldManager->SetDeltaIntersection(BDSGlobalConstants::Instance()->GetDeltaIntersection());
00438 }
00439
00440 G4MagInt_Driver* fIntgrDriver = new G4MagInt_Driver(BDSGlobalConstants::Instance()->GetChordStepMinimum(),
00441 itsFStepper,
00442 itsFStepper->GetNumberOfVariables() );
00443 fChordFinder = new G4ChordFinder(fIntgrDriver);
00444
00445 fChordFinder->SetDeltaChord(BDSGlobalConstants::Instance()->GetDeltaChord());
00446
00447 fieldManager->SetChordFinder( fChordFinder );
00448
00449 #ifdef BDSDEBUG
00450 G4cout << "BDSElement.cc> Setting the logical volume " << containerLogicalVolume->GetName() << " field manager... force to all daughters = " << forceToAllDaughters << G4endl;
00451 #endif
00452 containerLogicalVolume->SetFieldManager(fieldManager,forceToAllDaughters);
00453 }
00454
00455
00456
00457
00458 void BDSElement::PrepareField(G4VPhysicalVolume *referenceVolume)
00459 {
00460 if(!itsMagField) return;
00461 itsMagField->Prepare(referenceVolume);
00462 itsCachedMagField = new G4CachedMagneticField(itsMagField, 1*CLHEP::um);
00463 }
00464
00465
00466
00467
00468 void BDSElement::AlignComponent(G4ThreeVector& TargetPos,
00469 G4RotationMatrix *TargetRot,
00470 G4RotationMatrix& globalRotation,
00471 G4ThreeVector& rtot,
00472 G4ThreeVector& rlast,
00473 G4ThreeVector& localX,
00474 G4ThreeVector& localY,
00475 G4ThreeVector& localZ)
00476 {
00477
00478
00479 if(align_in_volume == NULL)
00480 {
00481 if(align_out_volume == NULL)
00482 {
00483
00484
00485 rtot = rlast + localZ*(chordLength/2);
00486 rlast = rtot + localZ*(chordLength/2);
00487 return;
00488 }
00489 else
00490 {
00491 #ifdef BDSDEBUG
00492 G4cout << "BDSElement : Aligning outgoing to SQL element "
00493 << align_out_volume->GetName() << G4endl;
00494 #endif
00495 G4RotationMatrix Trot = *TargetRot;
00496 G4RotationMatrix trackedRot;
00497 G4RotationMatrix outRot = *(align_out_volume->GetFrameRotation());
00498 trackedRot.transform(outRot.inverse());
00499 trackedRot.transform(Trot.inverse());
00500 globalRotation = trackedRot;
00501
00502 G4ThreeVector outPos = align_out_volume->GetFrameTranslation();
00503 G4ThreeVector diff = outPos;
00504
00505 G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00506
00507 zHalfAngle.transform(globalRotation);
00508
00509
00510 rlast = TargetPos - ((outPos.unit()).transform(Trot.inverse()) )*diff.mag();
00511 localX.transform(outRot.inverse());
00512 localY.transform(outRot.inverse());
00513 localZ.transform(outRot.inverse());
00514
00515 localX.transform(Trot.inverse());
00516 localY.transform(Trot.inverse());
00517 localZ.transform(Trot.inverse());
00518
00519
00520 rlast +=zHalfAngle*(chordLength/2 + diff.z());
00521 return;
00522 }
00523 }
00524
00525 if(align_in_volume != NULL)
00526 {
00527 #ifdef BDSDEBUG
00528 G4cout << "BDSElement : Aligning incoming to SQL element "
00529 << align_in_volume->GetName() << G4endl;
00530 #endif
00531
00532 const G4RotationMatrix* inRot = align_in_volume->GetFrameRotation();
00533 TargetRot->transform((*inRot).inverse());
00534
00535 G4ThreeVector inPos = align_in_volume->GetFrameTranslation();
00536 inPos.transform((*TargetRot).inverse());
00537 TargetPos+=G4ThreeVector(inPos.x(), inPos.y(), 0.0);
00538
00539 if(align_out_volume == NULL)
00540 {
00541
00542
00543 G4RotationMatrix Trot = *TargetRot;
00544 globalRotation.transform(Trot.inverse());
00545
00546 G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00547 zHalfAngle.transform(Trot.inverse());
00548
00549 rlast = TargetPos + zHalfAngle*(chordLength/2);
00550 localX.transform(Trot.inverse());
00551 localY.transform(Trot.inverse());
00552 localZ.transform(Trot.inverse());
00553 return;
00554 }
00555
00556 else
00557 {
00558 #ifdef BDSDEBUG
00559 G4cout << "BDSElement : Aligning outgoing to SQL element "
00560 << align_out_volume->GetName() << G4endl;
00561 #endif
00562 G4RotationMatrix Trot = *TargetRot;
00563 G4RotationMatrix trackedRot;
00564 G4RotationMatrix outRot = *(align_out_volume->GetFrameRotation());
00565 trackedRot.transform(outRot.inverse());
00566 trackedRot.transform(Trot.inverse());
00567 globalRotation = trackedRot;
00568
00569 G4ThreeVector outPos = align_out_volume->GetFrameTranslation();
00570 G4ThreeVector diff = outPos;
00571
00572 G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00573
00574 zHalfAngle.transform(globalRotation);
00575
00576
00577 rlast = TargetPos - ((outPos.unit()).transform(Trot.inverse()) )*diff.mag();
00578 localX.transform(outRot.inverse());
00579 localY.transform(outRot.inverse());
00580 localZ.transform(outRot.inverse());
00581
00582 localX.transform(Trot.inverse());
00583 localY.transform(Trot.inverse());
00584 localZ.transform(Trot.inverse());
00585
00586
00587 rlast +=zHalfAngle*(chordLength/2 + diff.z());
00588 return;
00589 }
00590 }
00591 }
00592
00593 BDSElement::~BDSElement()
00594 {
00595 delete fChordFinder;
00596 delete itsFStepper;
00597 delete itsFEquation;
00598 }