src/BDSElement.cc

00001 /* BDSIM code.    Version 1.0
00002    Author: John C. Carter, Royal Holloway, Univ. of London.
00003    Last modified 02.12.2004
00004    Copyright (c) 2004 by J.C.Carter.  ALL RIGHTS RESERVED. 
00005 */
00006 
00007 #include "BDSGlobalConstants.hh" // must be first in include list
00008 #include "BDSElement.hh"
00009 #include "G4Box.hh"
00010 #include "G4Tubs.hh"
00011 #include "G4Torus.hh"
00012 #include "G4Trd.hh"
00013 #include "G4VisAttributes.hh"
00014 #include "G4LogicalVolume.hh"
00015 #include "G4VPhysicalVolume.hh"
00016 #include "G4PVPlacement.hh"
00017 #include "G4UserLimits.hh"
00018 #include "G4Mag_UsualEqRhs.hh"
00019 #include "BDSHelixStepper.hh"
00020 #include "BDSQuadStepper.hh"
00021 #include "BDSOctStepper.hh"
00022 #include "BDSSextStepper.hh"
00023 #include "G4HelixImplicitEuler.hh"
00024 #include "G4HelixExplicitEuler.hh"
00025 #include "G4HelixMixedStepper.hh"
00026 #include "G4HelixSimpleRunge.hh"
00027 #include "G4HelixHeum.hh"
00028 #include "G4SimpleRunge.hh"
00029 #include "G4ExactHelixStepper.hh"
00030 #include "BDSAcceleratorComponent.hh"
00031 #include "BDS3DMagField.hh"
00032 #include "BDSXYMagField2.hh"
00033 #include "G4CashKarpRKF45.hh"
00034 
00035 // geometry drivers
00036 #include "parser/gmad.h"
00037 #include "ggmad.hh"
00038 #include "BDSGeometrySQL.hh"
00039 
00040 #ifdef USE_LCDD
00041 #include "BDSGeometryLCDD.hh"
00042 #endif
00043 
00044 #ifdef USE_GDML
00045 #include "BDSGeometryGDML.hh"
00046 #endif
00047 
00048 #include <map>
00049 
00050 using namespace std;
00051 
00052 //============================================================
00053 
00054 typedef std::map<G4String,int> LogVolCountMap;
00055 extern LogVolCountMap* LogVolCount;
00056 
00057 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00058 extern LogVolMap* LogVol;
00059 
00060 extern G4RotationMatrix* RotY90;
00061 
00062 //============================================================
00063 
00064 BDSElement::BDSElement(G4String aName, G4String geometry, G4String bmap,
00065                        G4double aLength, G4double bpRad, G4double outR, G4String aTunnelMaterial, G4double aTunnelRadius, G4double aTunnelOffsetX, G4String aTunnelCavityMaterial, G4int aPrecisionRegion):
00066   BDSAcceleratorComponent(
00067                           aName,
00068                           aLength,bpRad,0,0,
00069                           SetVisAttributes(), aTunnelMaterial, "", 0., 0., 0., 0., aTunnelRadius*m, aTunnelOffsetX*m, aTunnelCavityMaterial, aPrecisionRegion),
00070   fChordFinder(NULL), itsFStepper(NULL), itsFEquation(NULL), itsEqRhs(NULL), 
00071   itsField(NULL), itsMagField(NULL), itsUniformMagField(NULL)
00072 {
00073   itsFieldVolName="";
00074   itsFieldIsUniform=false;
00075   itsOuterR = outR;
00076   SetType(_ELEMENT);
00077 
00078   //Set marker volume lengths
00079   CalculateLengths();
00080 
00081   // WARNING: ALign in and out will only apply to the first instance of the
00082   //          element. Subsequent copies will have no alignment set.
00083   align_in_volume = NULL;
00084   align_out_volume = NULL;
00085 
00086   if(!(*LogVolCount)[itsName])
00087     {
00088 #ifdef DEBUG 
00089       G4cout<<"BDSElement : starting build logical volume "<<
00090         itsName<<G4endl;
00091 #endif
00092       BuildGeometry(); // build element box
00093       
00094 #ifdef DEBUG 
00095       G4cout<<"BDSElement : end build logical volume "<<
00096         itsName<<G4endl;
00097 #endif
00098 
00099       PlaceComponents(geometry,bmap); // place components (from file) and build filed maps
00100     }
00101   else
00102     {
00103       (*LogVolCount)[itsName]++;
00104       
00105       itsMarkerLogicalVolume=(*LogVol)[itsName];
00106     }
00107 }
00108 
00109 
00110 void BDSElement::BuildElementMarkerLogicalVolume(){
00111   
00112 #ifdef DEBUG 
00113   G4cout<<"BDSElement : creating logical volume"<<G4endl;
00114 #endif
00115   G4double elementSizeX=itsOuterR+BDSGlobalConstants::Instance()->GetLengthSafety()/2, elementSizeY = itsOuterR+BDSGlobalConstants::Instance()->GetLengthSafety()/2;
00116   
00117   
00118   elementSizeX = std::max(elementSizeX, this->GetTunnelRadius()+2*std::abs(this->GetTunnelOffsetX()) + BDSGlobalConstants::Instance()->GetTunnelThickness()+BDSGlobalConstants::Instance()->GetTunnelSoilThickness() + 4*BDSGlobalConstants::Instance()->GetLengthSafety() );   
00119   elementSizeY = std::max(elementSizeY, this->GetTunnelRadius()+2*std::abs(BDSGlobalConstants::Instance()->GetTunnelOffsetY()) + BDSGlobalConstants::Instance()->GetTunnelThickness()+BDSGlobalConstants::Instance()->GetTunnelSoilThickness()+4*BDSGlobalConstants::Instance()->GetLengthSafety() );
00120 
00121   G4double elementSize=std::max(elementSizeX, elementSizeY); 
00122   
00123 
00124   itsMarkerLogicalVolume = 
00125     new G4LogicalVolume(new G4Box(itsName+"generic_element",
00126                                   elementSize,
00127                                   elementSize,   
00128                                   itsLength/2.0),
00129                         BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial()),
00130                         itsName);
00131 
00132   
00133   //-------------------------------------------------------------------------------------------------------------
00134 
00135 
00136 #ifdef DEBUG 
00137   G4cout<<"marker volume : x/y="<<elementSize/m<<
00138     " m, l= "<<  (itsLength)/2/m <<" m"<<G4endl;
00139 #endif
00140 
00141 
00142     //-----------------------------
00143     /*
00144       G4RotationMatrix* rotMatrix1 = new G4RotationMatrix();
00145   rotMatrix1->rotateY(itsPhiAngleIn);
00146   G4RotationMatrix* rotMatrix2 = new G4RotationMatrix();
00147   rotMatrix1->rotateY(itsPhiAngleOut);
00148   G4ThreeVector transVec1(0, 0, itsLength
00149 
00150   itsMarkerLogicalVolume = new G4SubtactionSolid(itsName+"_generic_element",
00151                                                  new G4SubtactionSolid(itsName+"_tempSolid1",
00152                                                                        new G4Box(itsName+"tempSolid1a",
00153                                                                                  elementSize,
00154                                                                                  elementSize,   
00155                                                                                  itsLength/2),
00156                                                                        new G4Box(itsName+"tempSolid1b", 
00157                                                                                  sin(itsPhiAngleIn)*elementSize*2, //Make sure it is wider than the solid being subtracted from
00158                                                                                  elementSize,
00159                                                                                  itsLength/2),
00160                                                                        rotMatrix1,
00161                                                                        transVec1),
00162                                                  new  G4Box(itsName+"tempSolid2", 
00163                                                             sin(itsPhiAngleOut)*elementSize*2, //Make sure it is wider than the solid being subtracted from
00164                                                             elementSize,
00165                                                             itsLength/2),
00166                                                  rotMatrix2,
00167                                                  transVec2);
00168 
00169 
00170 
00171   G4LogicalVolume* tempBox1 = new G4LogicalVolume(new G4Box(itsName+"tempBox1", 
00172                                                             sin(itsPhiAngleIn)*elementSize,
00173                                                             elementSize,
00174                                                             itsLength/2),
00175                                                   BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial()),
00176                                                   itsName+"tempBox1Log"
00177                                                   );
00178   
00179 
00180     */
00181 
00182   /*
00183   G4double xHalfLengthPlus, xHalfLengthMinus;
00184   xHalfLengthMinus = (itsLength + (elementSize/2.0)*(tan(itsPhiAngleIn) -tan(itsPhiAngleOut)))/2.0;
00185   xHalfLengthPlus = (itsLength +  (elementSize/2.0)*(tan(itsPhiAngleOut)-tan(itsPhiAngleIn )))/2.0;
00186   
00187   
00188   if((xHalfLengthPlus<0) || (xHalfLengthMinus<0)){
00189     G4cerr << "Bend radius in " << itsName << " too small for this tunnel/component geometry. Exiting." << G4endl;
00190     exit(1);
00191   }
00192   
00193   itsMarkerSolidVolume = new G4Trd(itsName+"_marker",
00194                                    xHalfLengthPlus,     // x hlf lgth at +z
00195                                    xHalfLengthMinus,    // x hlf lgth at -z
00196                                    elementSize/2,           // y hlf lgth at +z
00197                                    elementSize/2,           // y hlf lgth at -z
00198                                    fabs(cos(itsAngle/2))*elementSize/2);// z hlf lgth
00199   
00200   G4String LocalLogicalName=itsName;
00201   
00202   itsMarkerLogicalVolume=    
00203     new G4LogicalVolume(itsMarkerSolidVolume,
00204                         BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial()),
00205                         LocalLogicalName+"_marker");
00206   */
00207   
00208   itsMarkerUserLimits = new G4UserLimits(DBL_MAX,DBL_MAX,DBL_MAX, BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00209   G4double  maxStepFactor=5;
00210   itsMarkerUserLimits->SetMaxAllowedStep(itsLength*maxStepFactor);
00211   itsMarkerLogicalVolume->SetUserLimits(itsMarkerUserLimits);
00212   
00213   
00214   //
00215   // zero field in the marker volume
00216   //
00217   itsMarkerLogicalVolume->
00218     SetFieldManager(BDSGlobalConstants::Instance()->GetZeroFieldManager(),false);
00219 }
00220 
00221 void BDSElement::BuildGeometry()
00222 {
00223   // multiple element instances not implemented yet!!!
00224 
00225   // Build the marker logical volume 
00226   BuildElementMarkerLogicalVolume();
00227 
00228 
00229   (*LogVolCount)[itsName] = 1;
00230   (*LogVol)[itsName] = itsMarkerLogicalVolume;
00231 #ifndef NOUSERLIMITS
00232   itsOuterUserLimits = new G4UserLimits();
00233   G4double stepfactor=5;
00234   itsOuterUserLimits->SetMaxAllowedStep(itsLength*stepfactor);
00235   itsOuterUserLimits->SetUserMaxTime(BDSGlobalConstants::Instance()->GetMaxTime());
00236   if(BDSGlobalConstants::Instance()->GetThresholdCutCharged()>0){
00237     itsOuterUserLimits->SetUserMinEkine(BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00238   }
00239   itsMarkerLogicalVolume->SetUserLimits(itsOuterUserLimits);
00240 #endif
00241 
00242   //Build the tunnel
00243   if(BDSGlobalConstants::Instance()->GetBuildTunnel()){
00244     BuildTunnel();
00245   }
00246 }
00247 
00248 // place components 
00249 void BDSElement::PlaceComponents(G4String geometry, G4String bmap)
00250 {
00251 
00252   G4String gFormat="", bFormat="";
00253   G4String gFile="", bFile="";
00254 
00255   // get geometry format and file
00256   if(geometry != ""){
00257     G4int pos = geometry.find(":");
00258     gFormat="none";
00259     if(pos<0) { 
00260       G4cerr<<"WARNING: invalid geometry reference format : "<<geometry<<endl;
00261     }
00262     else {
00263       gFormat = geometry.substr(0,pos);
00264       gFile = BDSGlobalConstants::Instance()->GetBDSIMHOME();
00265       G4String temp = geometry.substr(pos+1,geometry.length() - pos);     
00266       G4cout << "BDSElement::PlaceComponents SQL file is " << temp << G4endl;
00267       G4cout << "BDSElement::PlaceComponents Full path is " << gFile << G4endl;
00268       gFile+=temp;
00269       G4cout << "BDSElement::PlaceComponents Full path is " << gFile << G4endl;
00270     }
00271   }
00272 
00273   // get fieldmap format and file
00274   bFormat="none";
00275   if(bmap != ""){
00276     G4int pos = bmap.find(":");
00277     if(pos<0) {
00278       G4cerr<<"WARNING: invalid B map reference format : "<<bmap<<endl; 
00279     }
00280     else {
00281       bFormat = bmap.substr(0,pos);
00282       bFile = BDSGlobalConstants::Instance()->GetBDSIMHOME();
00283       bFile += bmap.substr(pos+1,bmap.length() - pos); 
00284       G4cout << "BDSElement::PlaceComponents bmap file is " << bFile << G4endl;
00285     }
00286   }
00287 
00288   G4cout<<"placing components:\n geometry format - "<<gFormat<<G4endl<<
00289     "file - "<<gFile<<G4endl;
00290 
00291   G4cout<<"bmap format - "<<bFormat<<G4endl<<
00292     "file - "<<bFile<<G4endl;
00293 
00294 
00295   // get the geometry for the driver
00296   // different drivers may interpret the fieldmap differently
00297   // so a field map without geometry is not allowed
00298 
00299   GGmadDriver *ggmad;
00300   BDSGeometrySQL *Mokka;
00301 
00302 #ifdef USE_LCDD
00303   BDSGeometryLCDD *LCDD;
00304 #endif
00305 #ifdef USE_GDML
00306   BDSGeometryGDML *GDML;
00307 #endif
00308 
00309   if(gFormat=="gmad") {
00310     
00311     ggmad = new GGmadDriver(gFile);
00312     ggmad->Construct(itsMarkerLogicalVolume);
00313 
00314     // set sensitive volumes
00315     //vector<G4LogicalVolume*> SensComps = ggmad->SensitiveComponents;
00316     //for(G4int id=0; id<SensComps.size(); id++)
00317     //  SetMultipleSensitiveVolumes(SensComps[id]);
00318 
00319     
00320     SetMultipleSensitiveVolumes(itsMarkerLogicalVolume);
00321 
00322     // attach magnetic field if present
00323     if(bFormat=="3D"){
00324       G4cout << "BDSElement.cc> Making BDS3DMagField..." << G4endl;
00325       itsMagField = new BDS3DMagField(bFile, 0);
00326       BuildMagField(true);
00327     }else if(bFormat=="XY"){
00328       G4cout << "BDSElement.cc> Making BDSXYMagField2..." << G4endl;
00329       itsMagField = new BDSXYMagField2(bFile);
00330       // build the magnetic field manager and transportation
00331       BuildMagField(true);
00332     }
00333     delete ggmad;
00334     ggmad = 0;
00335   }
00336   else if(gFormat=="lcdd") {
00337 #ifdef USE_LCDD
00338     LCDD = new BDSGeometryLCDD(gFile);
00339     //Make marker visible (temp debug)
00340     G4VisAttributes* VisAttLCDD = new G4VisAttributes(G4Colour(0.0, 1.0, 0.0));
00341     VisAttLCDD->SetForceSolid(true);  
00342     VisAttLCDD->SetVisibility(false);
00343     itsMarkerLogicalVolume->SetVisAttributes(VisAttLCDD);
00344 
00345     LCDD->Construct(itsMarkerLogicalVolume);
00346     SetMultipleSensitiveVolumes(itsMarkerLogicalVolume);
00347     if(bFormat=="XY"){
00348       itsMagField = new BDSXYMagField(bFile);
00349       // build the magnetic field manager and transportation
00350       BuildMagField(true);
00351     } else if ( bFormat == "mokka" ){
00352       G4ThreeVector uniField = G4ThreeVector(0,3.5*tesla,0);
00353       std::vector<G4ThreeVector> uniFieldVect;
00354       uniFieldVect.push_back(uniField);
00355       std::vector<G4double> nulld;
00356       std::vector<G4String> nulls;
00357       //      itsMagField = new BDSMagFieldSQL(bFile,itsLength,nulls, nulld, nulls, nulld, nulls, nulld, LCDD->FieldVol, uniFieldVect);
00358     } else if ( bFormat == "test" ){
00359     }
00360     else if ( bFormat == "none" ){
00361       itsFieldIsUniform=LCDD->GetFieldIsUniform();
00362       if(itsFieldIsUniform){
00363         G4cout << "BDSElement> using LCDD format uniform field..." << G4endl;
00364         itsUniformMagField=LCDD->GetUniformField();
00365       }else{
00366         itsMagField=LCDD->GetField();
00367       }
00368       itsFieldVolName=LCDD->GetFieldVolName();
00369       BuildMagField(true);
00370     }
00371 
00372     vector<G4LogicalVolume*> SensComps = LCDD->SensitiveComponents;
00373     for(G4int id=0; id<(G4int)SensComps.size(); id++)
00374       SetMultipleSensitiveVolumes(SensComps[id]);
00375     //    delete LCDD;
00376     //    LCDD = 0;
00377 #else
00378     G4cout << "LCDD support not selected during BDSIM configuration" << G4endl;
00379     G4Exception("Please re-compile BDSIM with USE_LCDD flag in Makefile", "-1", FatalException, "");
00380 #endif
00381   }
00382   else if(gFormat=="mokka") {
00383     G4cout << "BDSElement.cc: loading geometry sql file: BDSGeometrySQL(" << gFile << "," << itsLength << ")" << G4endl,
00384     Mokka = new BDSGeometrySQL(gFile,itsLength);
00385     Mokka->Construct(itsMarkerLogicalVolume);
00386     for(unsigned int i=0; i<Mokka->GetMultiplePhysicalVolumes().size(); i++){
00387       SetMultiplePhysicalVolumes(Mokka->GetMultiplePhysicalVolumes().at(i));
00388     }
00389 
00390     vector<G4LogicalVolume*> SensComps = Mokka->SensitiveComponents;
00391     for(G4int id=0; id<(G4int)SensComps.size(); id++)
00392       SetMultipleSensitiveVolumes(SensComps[id]);
00393 
00394     vector<G4LogicalVolume*> GFlashComps =Mokka->itsGFlashComponents;
00395     for(G4int id=0; id<(G4int)GFlashComps.size(); id++)
00396       SetGFlashVolumes(GFlashComps[id]);
00397 
00398     align_in_volume = Mokka->align_in_volume;
00399     align_out_volume = Mokka->align_out_volume;
00400     // attach magnetic field if present
00401 
00402     if(bFormat=="3D"){
00403       G4cout << "BDSElement.cc> Making BDS3DMagField..." << G4endl;
00404       itsMagField = new BDS3DMagField(bFile, 0);
00405       BuildMagField(true);
00406     } else if(bFormat=="XY"){
00407       G4cout << "BDSElement.cc> Making BDSXYMagField2..." << G4endl;
00408       itsMagField = new BDSXYMagField2(bFile);
00409       // build the magnetic field manager and transportation
00410       BuildMagField(true);
00411     } else if(bFormat=="mokka" || bFormat=="none")
00412       {
00413         if(Mokka->HasFields || bFile!="")
00414           // Check for field file or volumes with fields
00415           // as there may be cases where there are no bFormats given
00416           // in gmad file but fields might be set to volumes in SQL files
00417           {
00418             itsMagField = new BDSMagFieldSQL(bFile,itsLength,
00419                                              Mokka->QuadVolBgrad,
00420                                              Mokka->SextVolBgrad,
00421                                              Mokka->OctVolBgrad,
00422                                              Mokka->UniformFieldVolField,
00423                                              Mokka->nPoleField,
00424                                              Mokka->HasUniformField);
00425             
00426             
00427             // build the magnetic field manager and transportation
00428             BuildMagField(true);
00429           }
00430       }
00431     // delete Mokka;
00432     // Mokka = 0;
00433   }
00434   else if(gFormat=="gdml") {
00435 #ifdef USE_GDML
00436     GDML = new BDSGeometryGDML(gFile);
00437     GDML->Construct(itsMarkerLogicalVolume);
00438     delete GDML;
00439     GDML = 0;
00440 #else
00441     G4cout << "GDML support not selected during BDSIM configuration" << G4endl;
00442     G4Exception("Please re-compile BDSIM with USE_GDML flag in Makefile", "-1", FatalException, "");
00443 #endif
00444   }
00445   else {
00446     G4cerr<<"geometry format "<<gFormat<<" not supported"<<G4endl;
00447   }
00448 
00449 
00450 
00451 
00452   //   // test - dump field values
00453 //     G4cout<<"dumping field values..."<<G4endl;
00454 //     G4double Point[4];
00455 //     G4double BField[6];
00456 //     ofstream testf("fields.dat");
00457 
00458 //     for(G4double x=-1*m;x<1*m;x+=1*cm)
00459 //        for(G4double y=-1*m;y<1*m;y+=1*cm)
00460 //       for(G4double z=-1*m;z<1*m;z+=1*cm)
00461 //       {
00462 //      Point[0] = x;
00463 //      Point[1] = y;
00464 //      Point[2] = z;
00465 //      Point[3] = 0;
00466 //      itsMagField->GetFieldValue(Point,BField);
00467 //      testf<<Point[0]<<" "<<Point[1]<<" "<<Point[2]<<" "<<
00468 //        BField[0]<<" "<<BField[1]<<" "<<BField[2]<<G4endl;
00469 //       }
00470 
00471 //     testf.close();
00472 //     G4cout<<"done"<<G4endl;
00473 
00474 
00475 }
00476 
00477 
00478 
00479 G4VisAttributes* BDSElement::SetVisAttributes()
00480 {
00481   itsVisAttributes=new G4VisAttributes(G4Colour(0.5,0.5,1));
00482   return itsVisAttributes;
00483 }
00484 
00485 
00486 void BDSElement::BuildMagField(G4bool forceToAllDaughters)
00487 {
00488 #ifdef DEBUG
00489   G4cout << "BDSElement.cc::BuildMagField Building magnetic field...." << G4endl;
00490 #endif
00491   // create a field manager
00492   G4FieldManager* fieldManager = new G4FieldManager();
00493 
00494 
00495   if(!itsFieldIsUniform){
00496 #ifdef DEBUG
00497     G4cout << "BDSElement.cc> Building non-uniform magnetic field..." << endl;
00498 #endif
00499     itsEqRhs = new G4Mag_UsualEqRhs(itsMagField);
00500     if( (itsMagField->GetHasUniformField())&!(itsMagField->GetHasNPoleFields() || itsMagField->GetHasFieldMap())){
00501       //itsFStepper = new G4ExactHelixStepper(itsEqRhs); 
00502       itsFStepper = new G4HelixMixedStepper(itsEqRhs,6); 
00503     } else {
00504       //        itsFStepper = new G4HelixMixedStepper(itsEqRhs,6); 
00505       itsFStepper = new G4HelixImplicitEuler(itsEqRhs); 
00506       //    itsFStepper = new G4HelixSimpleRunge(itsEqRhs);
00507       //    itsFStepper = new G4HelixHeum(itsEqRhs);
00508       //    itsFStepper = new G4ClassicalRK4(itsEqRhs);
00509     }
00510     //    //  itsFStepper = new G4HelixSimpleRunge(itsEqRhs); 
00511     //  itsFStepper = new G4HelixExplicitEuler(itsEqRhs); 
00512     fieldManager->SetDetectorField(itsMagField );
00513   } else {
00514 #ifdef DEBUG
00515     G4cout << "BDSElement.cc> Building uniform magnetic field..." << endl;
00516 #endif
00517     itsEqRhs = new G4Mag_UsualEqRhs(itsUniformMagField);
00518     //    itsFStepper = new G4HelixImplicitEuler(itsEqRhs); 
00519     //  itsFStepper = new G4CashKarpRKF45(itsEqRhs); 
00520     itsFStepper = new G4HelixMixedStepper(itsEqRhs, 6); 
00521     fieldManager->SetDetectorField(itsUniformMagField );
00522   }
00523 
00524 #ifdef DEBUG
00525   G4cout << "BDSElement.cc> Setting stepping accuracy parameters..." << endl;
00526 #endif
00527   
00528   if(BDSGlobalConstants::Instance()->GetDeltaOneStep()>0){
00529     fieldManager->SetDeltaOneStep(BDSGlobalConstants::Instance()->GetDeltaOneStep());
00530   }
00531   if(BDSGlobalConstants::Instance()->GetMaximumEpsilonStep()>0){
00532     fieldManager->SetMaximumEpsilonStep(BDSGlobalConstants::Instance()->GetMaximumEpsilonStep());
00533   }
00534   if(BDSGlobalConstants::Instance()->GetMinimumEpsilonStep()>=0){
00535     fieldManager->SetMinimumEpsilonStep(BDSGlobalConstants::Instance()->GetMinimumEpsilonStep());
00536   }
00537   if(BDSGlobalConstants::Instance()->GetDeltaIntersection()>0){
00538     fieldManager->SetDeltaIntersection(BDSGlobalConstants::Instance()->GetDeltaIntersection());
00539   }
00540 
00541   G4MagInt_Driver* fIntgrDriver = new G4MagInt_Driver(BDSGlobalConstants::Instance()->GetChordStepMinimum(),
00542                                                       itsFStepper, 
00543                                                       itsFStepper->GetNumberOfVariables() );
00544   fChordFinder = new G4ChordFinder(fIntgrDriver);
00545   
00546   fChordFinder->SetDeltaChord(BDSGlobalConstants::Instance()->GetDeltaChord());
00547   
00548   fieldManager->SetChordFinder( fChordFinder ); 
00549 
00550   
00551   //  if(itsFieldVolName != ""){
00552   //    itsFieldVolName=itsFieldVolName+"_PhysiComp";
00553   //    G4cout << "Printing daughters... itsFieldVolName=" << itsFieldVolName << G4endl;
00554   //  for(int i=0;itsMarkerLogicalVolume->IsAncestor(itsMarkerLogicalVolume->GetDaughter(i)); i++){
00555   //    G4cout << itsMarkerLogicalVolume->GetDaughter(i)->GetName() << endl;
00556   //    if( itsMarkerLogicalVolume->GetDaughter(i)->GetName() == itsFieldVolName){
00557   //      itsMarkerLogicalVolume->GetDaughter(i)->GetLogicalVolume()->SetFieldManager(fieldManager,forceToAllDaughters);
00558   //      G4cout << "Field volume set..." << G4endl;
00559   //      break;
00560   //    }
00561   //  }
00562   //} else {
00563   //  }
00564   
00565 #ifdef DEBUG
00566   G4cout << "BDSElement.cc> Setting the logical volume " << itsMarkerLogicalVolume->GetName() << " field manager... force to all daughters = " << forceToAllDaughters << endl;
00567 #endif
00568   itsMarkerLogicalVolume->SetFieldManager(fieldManager,forceToAllDaughters);
00569 }
00570 
00571 // creates a field mesh in the reference frame of a physical volume
00572 // from  b-field map value list 
00573 // has to be called after the component is placed in the geometry
00574     void BDSElement::PrepareField(G4VPhysicalVolume *referenceVolume)
00575 {
00576   if(!itsMagField) return;
00577   itsMagField->Prepare(referenceVolume);
00578 }
00579 
00580 // Rotates and positions the marker volume before it is placed in
00581 // BDSDetectorConstruction. It aligns the marker volume so that the
00582 // the beamline goes through the specified daugther volume (e.g. for mokka)
00583 void BDSElement::AlignComponent(G4ThreeVector& TargetPos, 
00584                                 G4RotationMatrix *TargetRot, 
00585                                 G4RotationMatrix& globalRotation,
00586                                 G4ThreeVector& rtot,
00587                                 G4ThreeVector& rlast,
00588                                 G4ThreeVector& localX,
00589                                 G4ThreeVector& localY,
00590                                 G4ThreeVector& localZ)
00591 {
00592   
00593   
00594   if(align_in_volume == NULL)
00595     {
00596       if(align_out_volume == NULL)
00597         {
00598           // advance co-ords in usual way if no alignment volumes found
00599           
00600           rtot = rlast + localZ*(itsLength/2);
00601           rlast = rtot + localZ*(itsLength/2);
00602           return;
00603         }
00604       else 
00605         {
00606           G4cout << "BDSElement : Aligning outgoing to SQL element " 
00607                  << align_out_volume->GetName() << G4endl;
00608           G4RotationMatrix Trot = *TargetRot;
00609           G4RotationMatrix trackedRot;
00610           G4RotationMatrix outRot = *(align_out_volume->GetFrameRotation());
00611           trackedRot.transform(outRot.inverse());
00612           trackedRot.transform(Trot.inverse());
00613           globalRotation = trackedRot;
00614 
00615           G4ThreeVector outPos = align_out_volume->GetFrameTranslation();
00616           G4ThreeVector diff = outPos;
00617 
00618           G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00619 
00620           zHalfAngle.transform(globalRotation);
00621 
00622           //moving positioning to outgoing alignment volume
00623           rlast = TargetPos - ((outPos.unit()).transform(Trot.inverse()) )*diff.mag();
00624           localX.transform(outRot.inverse());
00625           localY.transform(outRot.inverse());
00626           localZ.transform(outRot.inverse());
00627 
00628           localX.transform(Trot.inverse());
00629           localY.transform(Trot.inverse());
00630           localZ.transform(Trot.inverse());
00631 
00632           //moving position in Z be at least itsLength/2 away
00633           rlast +=zHalfAngle*(itsLength/2 + diff.z());
00634           return;
00635         }
00636     }
00637 
00638   if(align_in_volume != NULL)
00639     {
00640       G4cout << "BDSElement : Aligning incoming to SQL element " 
00641              << align_in_volume->GetName() << G4endl;
00642       
00643       const G4RotationMatrix* inRot = align_in_volume->GetFrameRotation();
00644       TargetRot->transform((*inRot).inverse());
00645       
00646       G4ThreeVector inPos = align_in_volume->GetFrameTranslation();
00647       inPos.transform((*TargetRot).inverse());
00648       TargetPos+=G4ThreeVector(inPos.x(), inPos.y(), 0.0);
00649       
00650       if(align_out_volume == NULL)
00651         {
00652           // align outgoing (i.e. next component) to Marker Volume
00653           
00654           G4RotationMatrix Trot = *TargetRot;
00655           globalRotation.transform(Trot.inverse());
00656           
00657           G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00658           zHalfAngle.transform(Trot.inverse());
00659           
00660           rlast = TargetPos + zHalfAngle*(itsLength/2);
00661           localX.transform(Trot.inverse());
00662           localY.transform(Trot.inverse());
00663           localZ.transform(Trot.inverse());
00664           return;
00665         }
00666 
00667       else
00668         {
00669           G4cout << "BDSElement : Aligning outgoing to SQL element " 
00670                  << align_out_volume->GetName() << G4endl;
00671           G4RotationMatrix Trot = *TargetRot;
00672           G4RotationMatrix trackedRot;
00673           G4RotationMatrix outRot = *(align_out_volume->GetFrameRotation());
00674           trackedRot.transform(outRot.inverse());
00675           trackedRot.transform(Trot.inverse());
00676           globalRotation = trackedRot;
00677 
00678           G4ThreeVector outPos = align_out_volume->GetFrameTranslation();
00679           G4ThreeVector diff = outPos;
00680 
00681           G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00682 
00683           zHalfAngle.transform(globalRotation);
00684 
00685           //moving positioning to outgoing alignment volume
00686           rlast = TargetPos - ((outPos.unit()).transform(Trot.inverse()) )*diff.mag();
00687           localX.transform(outRot.inverse());
00688           localY.transform(outRot.inverse());
00689           localZ.transform(outRot.inverse());
00690 
00691           localX.transform(Trot.inverse());
00692           localY.transform(Trot.inverse());
00693           localZ.transform(Trot.inverse());
00694 
00695           //moving position in Z be at least itsLength/2 away
00696           rlast +=zHalfAngle*(itsLength/2 + diff.z());
00697           return;
00698         }
00699     }
00700   
00701 }
00702 
00703 BDSElement::~BDSElement()
00704 {
00705   delete itsVisAttributes;
00706   delete fChordFinder;
00707   delete itsFStepper;
00708   delete itsFEquation;
00709 }

Generated on 27 Aug 2013 for BDSIM by  doxygen 1.4.7