/scratch0/jsnuveri/BDSIM/BDSIMgit/bdsim/src/BDSComponentFactory.cc

00001 #include "BDSComponentFactory.hh"
00002 
00003 // elements
00004 #include "BDSAwakeScintillatorScreen.hh"
00005 #include "BDSCollimatorElliptical.hh"
00006 #include "BDSCollimatorRectangular.hh"
00007 #include "BDSDrift.hh"
00008 #include "BDSDump.hh"
00009 #include "BDSElement.hh"
00010 #include "BDSKicker.hh"
00011 #include "BDSLaserWire.hh"
00012 #include "BDSLine.hh"
00013 #include "BDSMuSpoiler.hh"
00014 #include "BDSOctupole.hh"
00015 #include "BDSQuadrupole.hh"
00016 #include "BDSRBend.hh"
00017 #include "BDSRfCavity.hh"
00018 #include "BDSSampler.hh"
00019 #include "BDSSamplerCylinder.hh"
00020 #include "BDSScintillatorScreen.hh"
00021 #include "BDSSectorBend.hh"
00022 #include "BDSSextupole.hh"
00023 #include "BDSSolenoid.hh"
00024 #include "BDSTerminator.hh"
00025 #include "BDSTeleporter.hh"
00026 #include "BDSMultipole.hh"
00027 #include "BDSTransform3D.hh"
00028 
00029 // general
00030 #include "BDSBeamline.hh"
00031 #include "BDSBeamPipeType.hh"
00032 #include "BDSBeamPipeInfo.hh"
00033 #include "BDSDebug.hh"
00034 #include "BDSExecOptions.hh"
00035 #include "BDSMagnetOuterInfo.hh"
00036 #include "BDSMagnetGeometryType.hh"
00037 #include "BDSTunnelInfo.hh"
00038 
00039 #include "parser/enums.h"
00040 #include "parser/elementlist.h"
00041 
00042 #include <cmath>
00043 #include <sstream>
00044 #include <string>
00045 
00046 #ifdef BDSDEBUG
00047 bool debug1 = true;
00048 #else
00049 bool debug1 = false;
00050 #endif
00051 
00052 BDSComponentFactory::BDSComponentFactory(){
00053   verbose = BDSExecOptions::Instance()->GetVerbose();
00054   lengthSafety = BDSGlobalConstants::Instance()->GetLengthSafety();
00055   //
00056   // compute magnetic rigidity brho
00057   // formula: B(Tesla)*rho(m) = p(GeV)/(0.299792458 * |charge(e)|)
00058   //
00059   // charge (in e units)
00060   _charge = BDSGlobalConstants::Instance()->GetParticleDefinition()->GetPDGCharge();
00061   // momentum (in GeV/c)
00062 
00063   _momentum = BDSGlobalConstants::Instance()->GetBeamMomentum()/CLHEP::GeV;
00064   // rigidity (in T*m)
00065   _brho = BDSGlobalConstants::Instance()->GetFFact()*( _momentum / 0.299792458);
00066   
00067   // rigidity (in Geant4 units)
00068   _brho *= (CLHEP::tesla*CLHEP::m);
00069 
00070   if (verbose || debug1) G4cout << "Rigidity (Brho) : "<< fabs(_brho)/(CLHEP::tesla*CLHEP::m) << " T*m"<<G4endl;
00071 }
00072 
00073 BDSComponentFactory::~BDSComponentFactory(){
00074 }
00075 
00076 BDSAcceleratorComponent* BDSComponentFactory::createComponent(std::list<struct Element>::iterator elementIter, ElementList& beamline_list){
00077 #ifdef BDSDEBUG
00078   G4cout << "BDSComponentFactory::createComponent() making iterators" << G4endl;  
00079 #endif
00080   _elementIter = elementIter;
00081   _previousElementIter = elementIter; 
00082   _nextElementIter= elementIter; 
00083   if(_elementIter != beamline_list.begin()){
00084 #ifdef BDSDEBUG
00085     G4cout << "BDSComponentFactory::createComponent() moving to previous element" << G4endl;  
00086 #endif
00087     _previousElementIter--;
00088   } 
00089 
00090   _nextElementIter++;
00091   if(_nextElementIter == beamline_list.end()){
00092 #ifdef BDSDEBUG
00093     G4cout << "BDSComponentFactory::createComponent() at the end, not moving to next element" << G4endl;  
00094 #endif
00095     _nextElementIter--;
00096   } 
00097 #ifdef BDSDEBUG
00098   G4cout << "BDSComponentFactory::createComponent() creating and returning component..." << G4endl;  
00099 #endif
00100   return createComponent(*_elementIter, *_previousElementIter, *_nextElementIter);
00101 }
00102 
00103 BDSAcceleratorComponent* BDSComponentFactory::createComponent(Element& aElement, Element& previousElement, Element& nextElement){
00104 #ifdef BDSDEBUG
00105   G4cout << "BDSComponentFactory::createComponent() creating element..." << G4endl;  
00106 #endif
00107   _element = aElement;
00108 #ifdef BDSDEBUG
00109   G4cout << "BDSComponentFactory::createComponent() creating previous element..." << G4endl;  
00110 #endif
00111   _previousElement = previousElement;  
00112 #ifdef BDSDEBUG
00113   G4cout << "BDSComponentFactory::createComponent() creating next element..." << G4endl;  
00114 #endif
00115   _nextElement = nextElement;
00116   return createComponent();
00117 }
00118 
00119 BDSAcceleratorComponent* BDSComponentFactory::createComponent(){
00120 #ifdef BDSDEBUG
00121   G4cout << "BDSComponentFactory::createComponent() element name = " << _element.name << G4endl;  
00122 #endif
00123   BDSAcceleratorComponent* element = NULL;
00124 
00125   switch(_element.type){
00126   case _SAMPLER:
00127 #ifdef BDSDEBUG
00128     G4cout << "BDSComponentFactory  - creating sampler" << G4endl;
00129 #endif
00130     element = createSampler(); break;
00131   case _DRIFT:
00132 #ifdef BDSDEBUG
00133     G4cout << "BDSComponentFactory  - creating drift" << G4endl;
00134 #endif
00135     element = createDrift(); break; 
00136   case _RF:
00137 #ifdef BDSDEBUG
00138     G4cout << "BDSComponentFactory  - creating rf" << G4endl;
00139 #endif
00140     element = createRF(); break; 
00141   case _SBEND:
00142 #ifdef BDSDEBUG
00143     G4cout << "BDSComponentFactory  - creating sbend" << G4endl;
00144 #endif
00145     element = createSBend(); break; 
00146   case _RBEND:
00147 #ifdef BDSDEBUG
00148     G4cout << "BDSComponentFactory  - creating rbend" << G4endl;
00149 #endif
00150     element = createRBend(); break; 
00151   case _HKICK:
00152 #ifdef BDSDEBUG
00153     G4cout << "BDSComponentFactory  - creating hkick" << G4endl;
00154 #endif
00155     element = createHKick(); break; 
00156   case _VKICK:
00157 #ifdef BDSDEBUG
00158     G4cout << "BDSComponentFactory  - creating vkick" << G4endl;
00159 #endif
00160     element = createVKick(); break; 
00161   case _QUAD:
00162 #ifdef BDSDEBUG
00163     G4cout << "BDSComponentFactory  - creating quadrupole" << G4endl;
00164 #endif
00165     element = createQuad(); break; 
00166   case _SEXTUPOLE:
00167 #ifdef BDSDEBUG
00168     G4cout << "BDSComponentFactory  - creating sextupole" << G4endl;
00169 #endif
00170     element = createSextupole(); break; 
00171   case _OCTUPOLE:
00172 #ifdef BDSDEBUG
00173     G4cout << "BDSComponentFactory  - creating octupole" << G4endl;
00174 #endif
00175     element = createOctupole(); break; 
00176   case _MULT:
00177 #ifdef BDSDEBUG
00178     G4cout << "BDSComponentFactory  - creating multipole" << G4endl;
00179 #endif
00180     element = createMultipole(); break; 
00181   case _ELEMENT:    
00182 #ifdef BDSDEBUG
00183     G4cout << "BDSComponentFactory  - creating element" << G4endl;
00184 #endif
00185     element = createElement(); break; 
00186   case _CSAMPLER:
00187 #ifdef BDSDEBUG
00188     G4cout << "BDSComponentFactory  - creating csampler" << G4endl;
00189 #endif
00190     element = createCSampler(); break; 
00191   case _DUMP:
00192 #ifdef BDSDEBUG
00193     G4cout << "BDSComponentFactory  - creating dump" << G4endl;
00194 #endif
00195     element = createDump(); break; 
00196   case _SOLENOID:
00197 #ifdef BDSDEBUG
00198     G4cout << "BDSComponentFactory  - creating solenoid" << G4endl;
00199 #endif
00200     element = createSolenoid(); break; 
00201   case _ECOL:
00202 #ifdef BDSDEBUG
00203     G4cout << "BDSComponentFactory  - creating ecol" << G4endl;
00204 #endif
00205     element = createEllipticalCollimator(); break; 
00206   case _RCOL:
00207 #ifdef BDSDEBUG
00208     G4cout << "BDSComponentFactory  - creating rcol" << G4endl;
00209 #endif
00210     element = createRectangularCollimator(); break; 
00211   case _MUSPOILER:    
00212 #ifdef BDSDEBUG
00213     G4cout << "BDSComponentFactory  - creating muspoiler" << G4endl;
00214 #endif
00215     element = createMuSpoiler(); break; 
00216   case _LASER:
00217 #ifdef BDSDEBUG
00218     G4cout << "BDSComponentFactory  - creating laser" << G4endl;
00219 #endif
00220     element = createLaser(); break; 
00221   case _SCREEN:
00222 #ifdef BDSDEBUG
00223     G4cout << "BDSComponentFactory  - creating screen" << G4endl;
00224 #endif
00225     element = createScreen(); break; 
00226   case _AWAKESCREEN:
00227 #ifdef BDSDEBUG
00228     G4cout << "BDSComponentFactory  - creating awake screen" << G4endl;
00229 #endif
00230     element = createAwakeScreen(); break; 
00231   case _TRANSFORM3D:
00232 #ifdef BDSDEBUG
00233     G4cout << "BDSComponentFactory  - creating transform3d" << G4endl;
00234 #endif
00235     element = createTransform3D(); break;
00236   case _TELEPORTER:
00237 #ifdef BDSDEBUG
00238     G4cout << "BDSComponentFactory  - creating teleporter" << G4endl;
00239 #endif
00240     element = createTeleporter(); break;
00241   case _TERMINATOR:
00242 #ifdef BDSDEBUG
00243     G4cout << "BDSComponentFactory  - creating terminator" << G4endl;
00244 #endif
00245     element = createTerminator(); break;
00246 
00247     // common types, but nothing to do here
00248   case _MARKER:
00249   case _LINE:
00250   case _REV_LINE:
00251   case _MATERIAL:
00252   case _ATOM:
00253   case _SEQUENCE:
00254   case _GAS:
00255   case _TUNNEL:
00256   case _COLLIMATOR:
00257     element = NULL;
00258     break;
00259   default:
00260 #ifdef BDSDEBUG
00261     G4cout << "BDSComponentFactory: type: " << _element.type << G4endl; 
00262 #endif
00263     G4Exception("Error: BDSComponentFactory: type not found.", "-1", FatalErrorInArgument, "");   
00264     exit(1);
00265     break;
00266   }
00267 
00268   if (element)
00269     {element->Initialise();}
00270   
00271   return element;
00272 }
00273 
00274 BDSAcceleratorComponent* BDSComponentFactory::createSampler(){
00275   return (new BDSSampler(_element.name, BDSGlobalConstants::Instance()->GetSamplerLength()));
00276 }
00277 
00278 BDSAcceleratorComponent* BDSComponentFactory::createCSampler(){
00279   if( _element.l < 1.E-4 ) _element.l = 1.0 ;
00280   return (new BDSSamplerCylinder( _element.name,
00281                                   _element.l * CLHEP::m,
00282                                   _element.r * CLHEP::m ));
00283 }
00284 
00285 BDSAcceleratorComponent* BDSComponentFactory::createDump(){
00286   return (new BDSDump( _element.name,
00287                        BDSGlobalConstants::Instance()->GetSamplerLength()));
00288 }
00289 
00290 BDSAcceleratorComponent* BDSComponentFactory::createTeleporter(){
00291   // This relies on things being added to the beamline immediately
00292   // after they've been created
00293   G4double teleporterlength = BDSGlobalConstants::Instance()->GetTeleporterLength();
00294   G4String name = "teleporter";
00295 #ifdef BDSDEBUG
00296     G4cout << "---->creating Teleporter,"
00297            << " name = " << name
00298            << ", l = " << teleporterlength/CLHEP::m << "m"
00299            << G4endl;
00300 #endif
00301 
00302     return( new BDSTeleporter(name,
00303                               teleporterlength ));
00304   
00305 }
00306 
00307 BDSAcceleratorComponent* BDSComponentFactory::createDrift()
00308 {
00309   if(!HasSufficientMinimumLength(_element))
00310     {return NULL;}
00311 
00312 #ifdef BDSDEBUG
00313   G4cout << "---->creating Drift,"
00314          << " name= " << _element.name
00315          << " l= " << _element.l << "m"
00316          << G4endl;
00317 #endif
00318   
00319   return (new BDSDrift( _element.name,
00320                         _element.l*CLHEP::m,
00321                         PrepareBeamPipeInfo(_element) ));
00322 }
00323 
00324 BDSAcceleratorComponent* BDSComponentFactory::createRF()
00325 {
00326   if(!HasSufficientMinimumLength(_element))
00327     {return NULL;}
00328   
00329   return (new BDSRfCavity( _element.name,
00330                            _element.l * CLHEP::m,
00331                            _element.gradient,
00332                            PrepareBeamPipeInfo(_element),
00333                            PrepareMagnetOuterInfo(_element)));
00334 }
00335 
00336 BDSAcceleratorComponent* BDSComponentFactory::createSBend()
00337 {
00338   if(!HasSufficientMinimumLength(_element))
00339     {return NULL;}
00340   
00341   // arc length
00342   G4double length = _element.l*CLHEP::m;
00343   G4double magFieldLength = length;
00344   
00345   // magnetic field
00346   // MAD conventions:
00347   // 1) a positive bend angle represents a bend to the right, i.e.
00348   // towards negative x values (even for negative _charges??)
00349   // 2) a positive K1 = 1/|Brho| dBy/dx means horizontal focusing of
00350   // positive charges
00351   // CHECK SIGNS 
00352   
00353   G4double bField;
00354   if(_element.B != 0) {
00355     bField = _element.B * CLHEP::tesla;
00356     G4double rho = _brho/bField;
00357     //    _element.angle  = - 2.0*asin(magFieldLength/2.0/rho);
00358     _element.angle  = - magFieldLength/rho;
00359   }
00360   else {
00361     _element.angle *= -1;
00362     //    bField = - 2 * _brho * sin(_element.angle/2.0) / magFieldLength;
00363     // charge in e units
00364     // multiply once more with ffact to not flip fields in bends
00365     bField = - _brho * _element.angle/magFieldLength * _charge * BDSGlobalConstants::Instance()->GetFFact();
00366     _element.B = bField/CLHEP::tesla;
00367   }
00368   
00369   // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00370   // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00371   G4double bPrime = - _brho * (_element.k1 / CLHEP::m2);
00372 
00373   //calculate number of sbends to split parent into
00374   //if maximum distance between arc path and straight path larger than 1mm, split sbend into N chunks,
00375   //this also works when maximum distance is less than 1mm as there will just be 1 chunk!
00376   double aperturePrecision = 1.0; // in mm
00377   // from formula: L/2 / N tan (angle/N) < precision. (L=physical length)
00378   int nSbends = (int) ceil(std::sqrt(std::abs(length*_element.angle/2/aperturePrecision)));
00379   //nSbends = 1;   //use for debugging
00380 #ifdef BDSDEBUG
00381   G4cout << __METHOD_NAME__ << " splitting sbend into " << nSbends << " sbends" << G4endl;
00382 #endif
00383   //calculate their angle and length
00384   double semiangle = _element.angle / (double) nSbends;
00385   double semilength = length / (double) nSbends;
00386   //create Line to put them in
00387   BDSLine* sbendline = new BDSLine("sbendline");
00388   //create sbends and put them in the line
00389   BDSBeamPipeInfo* bpInfo    = PrepareBeamPipeInfo(_element);
00390   BDSMagnetOuterInfo moInfo = PrepareMagnetOuterInfo(_element);
00391   for (int i = 0; i < nSbends; ++i)
00392     {
00393       std::stringstream name;
00394       name << _element.name << "_" << i;
00395       std::string itsname = name.str();
00396       sbendline->addComponent( new BDSSectorBend( itsname,
00397                                                   semilength,
00398                                                   semiangle,
00399                                                   bField,
00400                                                   bPrime,
00401                                                   bpInfo,
00402                                                   moInfo) );
00403     }
00404   return sbendline;
00405 }
00406 
00407 BDSAcceleratorComponent* BDSComponentFactory::createRBend()
00408 {
00409   if(!HasSufficientMinimumLength(_element))
00410     {return NULL;}
00411   
00412   // calculate length of central straight length and edge sections
00413   // unfortunately, this has to be duplicated here as we need to
00414   // calculated the magnetic field length (less than the full length)
00415   // in case we need to calculate the field
00416   G4double outerRadius = PrepareOuterDiameter(_element)*0.5;
00417   G4double angle       = _element.angle;
00418   G4double chordLength = _element.l*CLHEP::m;
00419   G4double straightSectionChord = outerRadius / (tan(0.5*fabs(angle)) + tan((0.5*CLHEP::pi) - (0.5*fabs(angle))) );
00420   G4double magFieldLength = chordLength - (2.0*straightSectionChord);
00421 
00422   // magnetic field
00423   // CHECK SIGNS OF B, B', ANGLE
00424   G4double bField;
00425   if(_element.B != 0){
00426   // angle = arc length/radius of curvature = L/rho = (B*L)/(B*rho)
00427     bField = _element.B * CLHEP::tesla;
00428     G4double rho = _brho/bField;
00429     //_element.angle  = - bField * length / brho;
00430     _element.angle  = - 2.0*asin(magFieldLength/2.0/rho);
00431 #ifdef BDSDEBUG
00432     G4cout << "calculated angle from field - now " << _element.angle << G4endl;
00433 #endif
00434   }
00435   else{
00436     _element.angle *= -1;
00437     // arc length = radius*angle
00438     //            = (geometrical length/(2.0*sin(angle/2))*angle
00439     G4double arclength = 0.5*magFieldLength * fabs(_element.angle) / sin(fabs(_element.angle)*0.5);
00440     // B = Brho/rho = Brho/(arc length/angle)
00441     // charge in e units
00442     // multiply once more with ffact to not flip fields in bends
00443     bField = - _brho * _element.angle / arclength * _charge * BDSGlobalConstants::Instance()->GetFFact();
00444     _element.B = bField/CLHEP::tesla;
00445 #ifdef BDSDEBUG
00446     G4cout << "calculated field from angle - angle,field = " << _element.angle << " " << _element.B << G4endl;
00447 #endif
00448   }
00449   
00450   // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00451   // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00452   G4double bPrime = - _brho * (_element.k1 / CLHEP::m2);
00453 
00454   return (new BDSRBend( _element.name,
00455                         _element.l*CLHEP::m,
00456                         bField,
00457                         bPrime,
00458                         _element.angle,
00459                         PrepareBeamPipeInfo(_element),
00460                         PrepareMagnetOuterInfo(_element)));
00461 }
00462 
00463 BDSAcceleratorComponent* BDSComponentFactory::createHKick()
00464 {
00465   if(!HasSufficientMinimumLength(_element))
00466     {return NULL;}  
00467   
00468   G4double length = _element.l*CLHEP::m;
00469   
00470   // magnetic field
00471   G4double bField;
00472   if(_element.B != 0){
00473     // angle = arc length/radius of curvature = L/rho = (B*L)/(B*rho)
00474     bField = _element.B * CLHEP::tesla;
00475     _element.angle  = -bField * length / _brho;
00476   }
00477   else{
00478     // B = Brho/rho = Brho/(arc length/angle)
00479     // charge in e units
00480     // multiply once more with ffact to not flip fields in kicks defined with angle
00481     bField = - _brho * _element.angle / length * _charge * BDSGlobalConstants::Instance()->GetFFact(); // charge in e units
00482     _element.B = bField/CLHEP::tesla;
00483   }
00484   
00485   // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00486   // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00487   G4double bPrime = - _brho * (_element.k1 / CLHEP::m2);
00488 
00489   // LN I think we should build it anyway and the stepper should deal
00490   // with this - ie so we still have the outer geometry
00491   /*
00492   if( fabs(_element.angle) < 1.e-7 * CLHEP::rad ) {
00493     G4cerr << "---->NOT creating Hkick,"
00494            << " name= " << _element.name
00495            << ", TOO SMALL ANGLE"
00496            << " angle= " << _element.angle << "rad"
00497            << ": REPLACED WITH Drift,"
00498            << " l= " << length/CLHEP::m << "m"
00499            << " aper= " << aper/CLHEP::m << "
00500            << G4endl;
00501     return createDrift();
00502   }
00503   */
00504   return (new BDSKicker( _element.name,
00505                          _element.l * CLHEP::m,
00506                          bField,
00507                          bPrime,
00508                          _element.angle,
00509                          false,   // it's a horizontal kicker
00510                          PrepareBeamPipeInfo(_element),
00511                          PrepareMagnetOuterInfo(_element)));
00512 }
00513 
00514 BDSAcceleratorComponent* BDSComponentFactory::createVKick()
00515 {
00516   if(!HasSufficientMinimumLength(_element))
00517     {return NULL;}
00518   
00519   G4double length = _element.l*CLHEP::m;
00520   
00521   // magnetic field
00522   G4double bField;
00523   if(_element.B != 0){
00524     // angle = arc length/radius of curvature = L/rho = (B*L)/(B*rho)
00525     bField = _element.B * CLHEP::tesla;
00526     _element.angle  = -bField * length / _brho;
00527   }
00528   else{
00529     // B = Brho/rho = Brho/(arc length/angle)
00530     // charge in e units
00531     // multiply once more with ffact to not flip fields in kicks
00532     bField = - _brho * _element.angle / length * _charge * BDSGlobalConstants::Instance()->GetFFact();
00533     _element.B = bField/CLHEP::tesla;
00534   }
00535   // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00536   // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00537   G4double bPrime = - _brho * (_element.k1 / CLHEP::m2);
00538 
00539   // LN I think we should build it anyway and the stepper should deal
00540   // with this - ie so we still have the outer geometry
00541   /*
00542   if( fabs(_element.angle) < 1.e-7 * CLHEP::rad ) {
00543     G4cerr << "---->NOT creating Vkick,"
00544            << " name= " << _element.name
00545            << ", TOO SMALL ANGLE"
00546            << " angle= " << _element.angle << "rad"
00547            << ": REPLACED WITH Drift,"
00548            << " l= " << _element.l << "m"
00549            << " aper= " << aper/CLHEP::m << "
00550            << G4endl;
00551 
00552     return createDrift();
00553   }
00554   */
00555   return (new BDSKicker( _element.name,
00556                          _element.l * CLHEP::m,
00557                          bField,
00558                          bPrime,
00559                          _element.angle,
00560                          true,   // it's a vertical kicker
00561                          PrepareBeamPipeInfo(_element),
00562                          PrepareMagnetOuterInfo(_element)
00563                          ));
00564 }
00565 
00566 BDSAcceleratorComponent* BDSComponentFactory::createQuad()
00567 {
00568   if(!HasSufficientMinimumLength(_element))
00569     {return NULL;}
00570   
00571   // magnetic field
00572   // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00573   // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00574   G4double bPrime = - _brho * (_element.k1 / CLHEP::m2);
00575 
00576   return (new BDSQuadrupole( _element.name,
00577                              _element.l * CLHEP::m,
00578                              bPrime,
00579                              PrepareBeamPipeInfo(_element),
00580                              PrepareMagnetOuterInfo(_element)));
00581 }  
00582   
00583 BDSAcceleratorComponent* BDSComponentFactory::createSextupole()
00584 {
00585   if(!HasSufficientMinimumLength(_element))
00586     {return NULL;}
00587   
00588   // magnetic field 
00589   // B'' = d^2By/dx^2 = Brho * (1/Brho d^2By/dx^2) = Brho * k2
00590   // brho is in Geant4 units, but k2 is not -> multiply k2 by m^-3
00591   G4double bDoublePrime = - _brho * (_element.k2 / CLHEP::m3);
00592   
00593 #ifdef BDSDEBUG 
00594   G4cout << "---->creating Sextupole,"
00595          << " name= " << _element.name
00596          << " l= " << _element.l << "m"
00597          << " k2= " << _element.k2 << "m^-3"
00598          << " brho= " << fabs(_brho)/(CLHEP::tesla*CLHEP::m) << "T*m"
00599          << " B''= " << bDoublePrime/(CLHEP::tesla/CLHEP::m2) << "T/m^2"
00600          << " tilt= " << _element.tilt << "rad"
00601          << " material= " << _element.outerMaterial
00602          << G4endl;
00603 #endif
00604   
00605   return (new BDSSextupole( _element.name,
00606                             _element.l * CLHEP::m,
00607                             bDoublePrime,
00608                             PrepareBeamPipeInfo(_element),
00609                             PrepareMagnetOuterInfo(_element)));
00610 }
00611 
00612 BDSAcceleratorComponent* BDSComponentFactory::createOctupole()
00613 {
00614   if(!HasSufficientMinimumLength(_element))
00615     {return NULL;}
00616   
00617   // magnetic field  
00618   // B''' = d^3By/dx^3 = Brho * (1/Brho d^3By/dx^3) = Brho * k3
00619   // brho is in Geant4 units, but k3 is not -> multiply k3 by m^-4
00620   G4double bTriplePrime = - _brho * (_element.k3 / (CLHEP::m3*CLHEP::m));
00621   
00622 #ifdef BDSDEBUG 
00623   G4cout << "---->creating Octupole,"
00624          << " name= " << _element.name
00625          << " l= " << _element.l << "m"
00626          << " k3= " << _element.k3 << "m^-4"
00627          << " brho= " << fabs(_brho)/(CLHEP::tesla*CLHEP::m) << "T*m"
00628          << " B'''= " << bTriplePrime/(CLHEP::tesla/CLHEP::m3) << "T/m^3"
00629          << " tilt= " << _element.tilt
00630          << " material= " << _element.outerMaterial
00631          << G4endl;
00632 #endif
00633   
00634   return ( new BDSOctupole( _element.name,
00635                             _element.l * CLHEP::m,
00636                             bTriplePrime,
00637                             PrepareBeamPipeInfo(_element),
00638                             PrepareMagnetOuterInfo(_element)));
00639 }
00640 
00641 BDSAcceleratorComponent* BDSComponentFactory::createMultipole()
00642 {
00643  if(!HasSufficientMinimumLength(_element))
00644     {return NULL;}
00645  
00646 #ifdef BDSDEBUG 
00647   G4cout << "---->creating Multipole,"
00648          << " name= " << _element.name
00649          << " l= " << _element.l << "m"
00650          << " tilt= " << _element.tilt << "rad"
00651          << " material= " << _element.outerMaterial
00652          << G4endl;
00653 #endif
00654   // magnetic field
00655   std::list<double>::iterator kit;
00656   
00657 #ifdef BDSDEBUG 
00658   G4cout << " knl={ ";
00659 #endif
00660   for(kit=(_element.knl).begin();kit!=(_element.knl).end();kit++)
00661     {
00662 #ifdef BDSDEBUG 
00663       G4cout<<(*kit)<<", ";
00664 #endif
00665       (*kit) /= _element.l; 
00666     }
00667 #ifdef BDSDEBUG 
00668   G4cout << "}";
00669 #endif
00670   
00671 #ifdef BDSDEBUG 
00672   G4cout << " ksl={ ";
00673 #endif
00674   for(kit=(_element.ksl).begin();kit!=(_element.ksl).end();kit++)
00675     {
00676 #ifdef BDSDEBUG 
00677       G4cout<<(*kit)<<" ";
00678 #endif
00679       (*kit) /= _element.l; 
00680     }
00681 #ifdef BDSDEBUG 
00682   G4cout << "}" << G4endl;
00683 #endif
00684 
00685   return (new BDSMultipole( _element.name,
00686                             _element.l * CLHEP::m,
00687                             _element.knl,
00688                             _element.ksl,
00689                             PrepareBeamPipeInfo(_element),
00690                             PrepareMagnetOuterInfo(_element)));
00691 }
00692 
00693 BDSAcceleratorComponent* BDSComponentFactory::createElement()
00694 {
00695   if(!HasSufficientMinimumLength(_element))
00696     {return NULL;}
00697   
00698 #ifdef BDSDEBUG 
00699   G4cout << "---->creating Element,"
00700          << " name = " << _element.name
00701          << " l = " << _element.l << "m"
00702          << " outerDiameter = "  << 0.5 * _element.outerDiameter << "m"
00703          << " bmapZOffset = "    <<  _element.bmapZOffset * CLHEP::m
00704          << " precision region " << _element.precisionRegion
00705          << G4endl;
00706 #endif
00707 
00708   return (new BDSElement(_element.name,
00709                          _element.l * CLHEP::m,
00710                          _element.geometryFile,
00711                          _element.bmapFile,
00712                          _element.bmapZOffset * CLHEP::m
00713                           ));
00714 }
00715 
00716 BDSAcceleratorComponent* BDSComponentFactory::createSolenoid()
00717 {
00718   if(!HasSufficientMinimumLength(_element))
00719     {return NULL;}
00720   
00721   // magnetic field
00722   //
00723   // B = B/Brho * Brho = ks * Brho
00724   // brho is in Geant4 units, but ks is not -> multiply ks by m^-1
00725   G4double bField;
00726   if(_element.B != 0){
00727     bField = _element.B * CLHEP::tesla;
00728     _element.ks  = (bField/_brho) / CLHEP::m;
00729   }
00730   else{
00731     bField = (_element.ks/CLHEP::m) * _brho;
00732     _element.B = bField/CLHEP::tesla;
00733   }
00734   
00735 #ifdef BDSDEBUG 
00736   G4cout << "---->creating Solenoid,"
00737          << " name = " << _element.name
00738          << " l = " << _element.l << " m,"
00739          << " ks = " << _element.ks << " m^-1,"
00740          << " brho = " << fabs(_brho)/(CLHEP::tesla*CLHEP::m) << " T*m,"
00741          << " B = " << bField/CLHEP::tesla << " T,"
00742          << " material = \"" << _element.outerMaterial << "\""
00743          << G4endl;
00744 #endif
00745   
00746   return (new BDSSolenoid( _element.name,
00747                            _element.l * CLHEP::m,
00748                            bField,
00749                            PrepareBeamPipeInfo(_element),
00750                            PrepareMagnetOuterInfo(_element)));
00751 }
00752 
00753 BDSAcceleratorComponent* BDSComponentFactory::createRectangularCollimator()
00754 {
00755   if(!HasSufficientMinimumLength(_element))
00756     {return NULL;}
00757 
00758 #ifdef BDSDEBUG 
00759   G4cout << "--->creating " << typestr(_element.type) << ","
00760          << " name = " << _element.name  << ","
00761          << " x half aperture = " << _element.xsize <<" m,"
00762          << " y half aperture = " << _element.ysize <<" m,"
00763          << " material = \"" << _element.material << "\""
00764          << G4endl;
00765 #endif
00766   
00767   return new BDSCollimatorRectangular(_element.name,
00768                                       _element.l*CLHEP::m,
00769                                       _element.outerDiameter*CLHEP::m,
00770                                       _element.xsize*CLHEP::m,
00771                                       _element.ysize*CLHEP::m,
00772                                       _element.material);
00773 }
00774 
00775 BDSAcceleratorComponent* BDSComponentFactory::createEllipticalCollimator()
00776 {
00777   if(!HasSufficientMinimumLength(_element))
00778     {return NULL;}
00779 
00780 #ifdef BDSDEBUG 
00781   G4cout << "--->creating " << typestr(_element.type) << ","
00782          << " name = " << _element.name 
00783          << " x half aperture = " << _element.xsize <<" m,"
00784          << " y half aperture = " << _element.ysize <<" m,"
00785          << " material = \"" << _element.material << "\""
00786          << G4endl;
00787 #endif
00788   
00789   return new BDSCollimatorElliptical(_element.name,
00790                                      _element.l*CLHEP::m,
00791                                      _element.outerDiameter*CLHEP::m,
00792                                      _element.xsize*CLHEP::m,
00793                                      _element.ysize*CLHEP::m,
00794                                      _element.material);
00795 }
00796 
00797 BDSAcceleratorComponent* BDSComponentFactory::createMuSpoiler()
00798 {
00799   if(!HasSufficientMinimumLength(_element))
00800     {return NULL;}
00801   
00802 #ifdef BDSDEBUG 
00803   G4cout << "---->creating muspoiler,"
00804          << " name = " << _element.name 
00805          << " length = " << _element.l
00806          << " B = " << _element.B
00807          << G4endl;
00808 #endif
00809         
00810 #ifdef BDSDEBUG
00811   G4cout << "BDSMuSpoiler: " << _element.name << " " << _element.l*CLHEP::m << " mm " << " " << _element.B*CLHEP::tesla << " MT " << G4endl;
00812 #endif
00813   
00814   return (new BDSMuSpoiler(_element.name,
00815                            _element.l*CLHEP::m,
00816                            _element.B * CLHEP::tesla,
00817                            PrepareBeamPipeInfo(_element),
00818                            PrepareMagnetOuterInfo(_element)));
00819 }
00820 
00821 BDSAcceleratorComponent* BDSComponentFactory::createLaser()
00822 {
00823   if(!HasSufficientMinimumLength(_element))
00824     {return NULL;}
00825         
00826 #ifdef BDSDEBUG 
00827   G4cout << "---->creating Laser,"
00828          << " name= "<< _element.name
00829          << " l=" << _element.l <<"m"
00830          << " lambda= " << _element.waveLength << "m"
00831          << " xSigma= " << _element.xsize << "m"
00832          << " ySigma= " << _element.ysize << "m"
00833          << " xdir= " << _element.xdir
00834          << " ydir= " << _element.ydir
00835          << " zdir= " << _element.zdir
00836          << G4endl;
00837 #endif
00838 
00839   G4double length = _element.l*CLHEP::m;
00840   G4double lambda = _element.waveLength*CLHEP::m;
00841 
00842         
00843   G4ThreeVector direction = 
00844     G4ThreeVector(_element.xdir,_element.ydir,_element.zdir);
00845   G4ThreeVector position  = G4ThreeVector(0,0,0);
00846         
00847   return (new BDSLaserWire( _element.name,
00848                             length,
00849                             lambda,
00850                             direction) );
00851         
00852 }
00853 
00854 BDSAcceleratorComponent* BDSComponentFactory::createScreen()
00855 {
00856   if(!HasSufficientMinimumLength(_element))
00857     {return NULL;}
00858         
00859 #ifdef BDSDEBUG 
00860         G4cout << "---->creating Screen,"
00861                << " name= "<< _element.name
00862                << " l=" << _element.l/CLHEP::m<<"m"
00863                << " tscint=" << _element.tscint/CLHEP::m<<"m"
00864                << " angle=" << _element.angle/CLHEP::rad<<"rad"
00865                << " scintmaterial=" << "ups923a"//_element.scintmaterial
00866                << " airmaterial=" << "vacuum"//_element.airmaterial
00867                << G4endl;
00868 #endif
00869         return (new BDSScintillatorScreen( _element.name, _element.tscint*CLHEP::m, (_element.angle-0.78539816339)*CLHEP::rad, "ups923a",BDSGlobalConstants::Instance()->GetVacuumMaterial())); //Name, scintillator thickness, angle in radians (relative to -45 degrees)
00870 }
00871 
00872 
00873 BDSAcceleratorComponent* BDSComponentFactory::createAwakeScreen(){
00874         
00875 #ifdef BDSDEBUG 
00876         G4cout << "---->creating Awake Screen,"
00877                << "twindow = " << _element.twindow*1e3/CLHEP::um << " um"
00878                << "tscint = " << _element.tscint*1e3/CLHEP::um << " um"
00879                << "windowmaterial = " << _element.windowmaterial << " um"
00880                << "scintmaterial = " << _element.scintmaterial << " um"
00881                << G4endl;
00882 #endif
00883         return (new BDSAwakeScintillatorScreen(_element.name, _element.scintmaterial, _element.tscint*1e3, _element.angle, _element.twindow*1e3, _element.windowmaterial)); //Name
00884 }
00885 
00886 BDSAcceleratorComponent* BDSComponentFactory::createTransform3D(){
00887         
00888 #ifdef BDSDEBUG 
00889   G4cout << "---->creating Transform3d,"
00890          << " name= " << _element.name
00891          << " xdir= " << _element.xdir/CLHEP::m << "m"
00892          << " ydir= " << _element.ydir/CLHEP::m << "m"
00893          << " zdir= " << _element.zdir/CLHEP::m << "m"
00894          << " phi= " << _element.phi/CLHEP::rad << "rad"
00895          << " theta= " << _element.theta/CLHEP::rad << "rad"
00896          << " psi= " << _element.psi/CLHEP::rad << "rad"
00897          << G4endl;
00898 #endif
00899         
00900   return (new BDSTransform3D( _element.name,
00901                               _element.xdir *CLHEP::m,
00902                               _element.ydir *CLHEP::m,
00903                               _element.zdir *CLHEP::m,
00904                               _element.phi *CLHEP::rad,
00905                               _element.theta *CLHEP::rad,
00906                               _element.psi *CLHEP::rad ) );
00907         
00908 }
00909 
00910 BDSAcceleratorComponent* BDSComponentFactory::createTerminator()
00911 {
00912   G4String name   = "terminator";
00913   G4double length = BDSGlobalConstants::Instance()->GetSamplerLength();
00914 #ifdef BDSDEBUG
00915     G4cout << "---->creating Terminator,"
00916            << " name = " << name
00917            << " l = "    << length / CLHEP::m << "m"
00918            << G4endl;
00919 #endif
00920   
00921   return (new BDSTerminator("terminator", 
00922                             length));
00923 }
00924 
00925 
00926 G4bool BDSComponentFactory::HasSufficientMinimumLength(Element& element)
00927 {
00928   if(element.l*CLHEP::m < 4*lengthSafety)
00929     {
00930       G4cerr << "---->NOT creating element, "
00931              << " name = " << _element.name
00932              << ", LENGTH TOO SHORT:"
00933              << " l = " << _element.l*CLHEP::m << "m"
00934              << G4endl;
00935       return false;
00936     }
00937   else
00938     {return true;}
00939 }
00940 
00941 G4Material* BDSComponentFactory::PrepareBeamPipeMaterial(Element& element)
00942 {
00943   G4Material* beamPipeMaterial;
00944   if(element.beampipeMaterial == "")
00945     {
00946       G4String defaultMaterialName = BDSGlobalConstants::Instance()->GetBeamPipeMaterialName();
00947       beamPipeMaterial = BDSMaterials::Instance()->GetMaterial(defaultMaterialName);
00948     }
00949   else
00950     { beamPipeMaterial = BDSMaterials::Instance()->GetMaterial(element.beampipeMaterial); }
00951   return beamPipeMaterial;
00952 }
00953 
00954 G4Material* BDSComponentFactory::PrepareVacuumMaterial(Element& /*element*/)
00955 {
00956   //in future do something relating to what's set in the element
00957   //also make some setting available in element
00958   return BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial());
00959 }
00960 
00961 BDSMagnetOuterInfo BDSComponentFactory::PrepareMagnetOuterInfo(Element& element)
00962 {
00963   BDSMagnetOuterInfo info;
00964   // magnet geometry type
00965   if (element.magnetGeometryType == "")
00966     info.geometryType = BDSGlobalConstants::Instance()->GetMagnetGeometryType();
00967   else
00968     info.geometryType = BDS::DetermineMagnetGeometryType(element.magnetGeometryType);
00969 
00970   // outer diameter
00971   G4double outerDiameter = element.outerDiameter*CLHEP::m;
00972   if (outerDiameter < 1e-6)
00973     {//outerDiameter not set - use global option as default
00974       outerDiameter = BDSGlobalConstants::Instance()->GetOuterDiameter();
00975     }
00976   info.outerDiameter = outerDiameter;
00977 
00978   // outer material
00979   G4Material* outerMaterial;
00980   if(element.outerMaterial == "")
00981     {
00982       G4String defaultMaterialName = BDSGlobalConstants::Instance()->GetOuterMaterialName();
00983       outerMaterial = BDSMaterials::Instance()->GetMaterial(defaultMaterialName);
00984     }
00985   else
00986     {outerMaterial = BDSMaterials::Instance()->GetMaterial(element.outerMaterial);}
00987   info.outerMaterial = outerMaterial;
00988   
00989   return info;
00990 }
00991 
00992 G4double BDSComponentFactory::PrepareOuterDiameter(Element& element)
00993 {
00994   G4double outerDiameter = element.outerDiameter*CLHEP::m;
00995   if (outerDiameter < 1e-6)
00996     {//outerDiameter not set - use global option as default
00997       outerDiameter = BDSGlobalConstants::Instance()->GetOuterDiameter();
00998     }
00999   // returns in metres
01000   return outerDiameter;
01001 }
01002 
01003 BDSBeamPipeInfo* BDSComponentFactory::PrepareBeamPipeInfo(Element& element)
01004 {
01005   BDSBeamPipeInfo* info = new BDSBeamPipeInfo;
01006   if (element.apertureType == "")
01007     info->beamPipeType = BDSGlobalConstants::Instance()->GetApertureType();
01008   else 
01009     info->beamPipeType = BDS::DetermineBeamPipeType(element.apertureType);
01010 
01011   // note even if aperN in the element is 0 (ie unset), we should use
01012   // the default aperture model from global constants (already in metres)
01013   // aper1
01014   if (element.aper1 == 0)
01015     {info->aper1 = BDSGlobalConstants::Instance()->GetAper1();}
01016   else
01017     {info->aper1 = element.aper1*CLHEP::m;}
01018   // aper2
01019   if (element.aper2 == 0)
01020     {info->aper2 = BDSGlobalConstants::Instance()->GetAper2();}
01021   else
01022     {info->aper2 = element.aper2*CLHEP::m;}
01023   // aper3
01024   if (element.aper3 == 0)
01025     {info->aper3 = BDSGlobalConstants::Instance()->GetAper3();}
01026   else
01027     {info->aper3 = element.aper3*CLHEP::m;}
01028   // aper4
01029   if (element.aper4 == 0)
01030     {info->aper4 = BDSGlobalConstants::Instance()->GetAper4();}
01031   else
01032     {info->aper4 = element.aper4*CLHEP::m;}
01033   
01034   info->vacuumMaterial    = PrepareVacuumMaterial(element);
01035   info->beamPipeThickness = element.beampipeThickness*CLHEP::m;
01036   if (info->beamPipeThickness < 1e-10)
01037     {info->beamPipeThickness = BDSGlobalConstants::Instance()->GetBeamPipeThickness();}
01038   info->beamPipeMaterial  = PrepareBeamPipeMaterial(element);
01039   return info;
01040 }

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7