/home/cern/BDSIM_new/src/BDSDetectorConstruction.cc

00001 //  
00002 //   BDSIM, (C) 2001-2007
00003 //   
00004 //   version 0.4
00005 //  
00006 //
00007 //
00008 //   Geometry construction
00009 //
00010 //
00011 //   History
00012 //      3 Oct 2007 by Malton v.0.4
00013 //     21 Nov 2006 by Agapov v.0.3
00014 //     28 Mar 2006 by Agapov v.0.2
00015 //     15 Dec 2005 by Agapov beta
00016 //
00017 
00018 
00019 const int DEBUG = 0;
00020 
00021 //=================================================================
00022 
00023 #include "BDSGlobalConstants.hh"
00024 
00025 #include "BDSDetectorConstruction.hh"
00026 
00027 #include "G4UserLimits.hh"
00028 
00029 #include "G4Region.hh"
00030 #include "G4ProductionCuts.hh"
00031 
00032 #include "G4Tubs.hh"
00033 #include "G4Box.hh"
00034 #include "G4LogicalVolume.hh"
00035 #include "G4PVPlacement.hh"
00036 #include "G4UniformMagField.hh"
00037 #include "G4FieldManager.hh"
00038 #include "G4TransportationManager.hh"
00039 #include "G4PropagatorInField.hh"
00040 #include "G4SDManager.hh"
00041 #include "G4RunManager.hh"
00042 
00043 #include "G4VisAttributes.hh"
00044 #include "G4Colour.hh"
00045 #include "globals.hh"
00046 #include "G4ios.hh"
00047 #include <iostream>
00048 #include <list>
00049 #include <map>
00050 #include "BDSAcceleratorComponent.hh"
00051 
00052 #include "G4Navigator.hh"
00053 #include "G4UniformMagField.hh"
00054 
00055 #include "G4Material.hh"
00056 #include "BDSEnergyCounterSD.hh"
00057 
00058 // elements
00059 #include "BDSBeamPipe.hh"
00060 #include "BDSDrift.hh"
00061 #include "BDSSectorBend.hh"
00062 #include "BDSRBend.hh"
00063 #include "BDSKicker.hh"
00064 #include "BDSQuadrupole.hh"
00065 #include "BDSSextupole.hh"
00066 //#include "BDSSkewSextupole.hh"
00067 #include "BDSOctupole.hh"
00068 #include "BDSDecapole.hh"
00069 #include "BDSTMultipole.hh"
00070 #include "BDSRfCavity.hh"
00071 #include "BDSSolenoid.hh"
00072 #include "BDSSampler.hh"
00073 #include "BDSSamplerCylinder.hh"
00074 #include "BDSDump.hh"
00075 #include "BDSLaserWire.hh"
00076 #include "BDSLWCalorimeter.hh"
00077 #include "BDSMuSpoiler.hh"
00078 #include "BDSTransform3D.hh"
00079 #include "BDSElement.hh"
00080 #include "BDSComponentOffset.hh"
00081 #include "BDSCollimator.hh"
00082 
00083 // output interface
00084 #include "BDSOutput.hh"
00085 
00086 //#include "BDSMultipoleOuterMagField.hh"
00087 #include "G4MagneticField.hh"
00088 
00089 // GMAD interface
00090 #include "parser/gmad.h"
00091 #include "ggmad.hh"
00092 
00093 using namespace std;
00094 
00095 
00096 //====================================
00097 
00098 typedef list<BDSAcceleratorComponent*>  BDSBeamline;
00099 BDSBeamline theBeamline;
00100 
00101 typedef list<BDSEnergyCounterSD*>  ECList;
00102 ECList* theECList;
00103 
00104 BDSMaterials* theMaterials;
00105 
00106 extern BDSGlobalConstants* BDSGlobals;
00107 
00108 //--------------------------
00109 // SYNCHROTRON RAD ***
00110 G4double BDSLocalRadiusOfCurvature=DBL_MAX;// Used in Mean Free Path calc.
00111 //--------------------------
00112 
00113 G4Material* aMaterial;
00114 extern G4double NumSpoilerRadLen;
00115 
00116 typedef std::map<G4String,int> LogVolCountMap;
00117 LogVolCountMap* LogVolCount;
00118 
00119 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00120 LogVolMap* LogVol;
00121 
00122 G4RotationMatrix* RotY90=new G4RotationMatrix();
00123 G4RotationMatrix* RotYM90=new G4RotationMatrix();
00124 
00125 G4Navigator* StepperNavigator;
00126 G4Navigator* QuadNavigator;
00127 
00128 //=========================================
00129 G4FieldManager* theOuterFieldManager;
00130 
00131 extern BDSOutput bdsOutput;
00132 extern G4bool verbose;
00133 extern G4bool outline;
00134 //=================================================================
00135 
00136 
00137 
00138 BDSDetectorConstruction::BDSDetectorConstruction()
00139 {  // create commands for interactive definition of the beamline  
00140   G4double pi_ov_2 = asin(1.);
00141 
00142   RotY90->rotateY(pi_ov_2);
00143   RotYM90->rotateY(-pi_ov_2);
00144 }
00145 
00146 //=================================================================
00147 
00148 G4VPhysicalVolume* BDSDetectorConstruction::Construct()
00149 {
00150   theECList=new ECList;
00151 
00152   LogVolCount=new LogVolCountMap();
00153 
00154   LogVol=new LogVolMap();
00155 
00156   theMaterials=new BDSMaterials();
00157 
00158   if (verbose || DEBUG) G4cout << "-->starting BDS construction \n"<<G4endl;
00159 
00160   return ConstructBDS(beamline_list);
00161 
00162 }
00163 
00164 
00165 G4VPhysicalVolume* BDSDetectorConstruction::ConstructBDS(list<struct Element>& beamline_list)
00166 {
00167   //
00168   // set default output formats:
00169   //
00170   G4cout.precision(10);
00171   
00172   
00173   //
00174   // convert the parsed atom list to list of Geant4 G4Elements
00175   //
00176   list<struct Element>::iterator it;
00177 
00178 
00179   if (verbose || DEBUG) G4cout << "parsing the atom list..."<< G4endl;
00180   for(it = atom_list.begin();it!=atom_list.end();it++)
00181   {
00182     if (DEBUG) G4cout << "---->adding Atom, "
00183                       << "name= " << (*it).name << " "
00184                       << "symbol= " << (*it).symbol << " "
00185                       << "Z= " << (*it).Z << " "
00186                       << "A= " << (*it).A << "g/mole "
00187                       << G4endl;
00188 
00189     theMaterials->AddElement((*it).name,(*it).symbol,(*it).Z,(*it).A);
00190   }
00191   if (verbose || DEBUG) G4cout << "size of atom list: "<< atom_list.size() << G4endl;
00192 
00193 
00194   //
00195   // convert the parsed material list to list of Geant4 G4Materials
00196   //
00197   if (verbose || DEBUG) G4cout << "parsing the material list..."<< G4endl;
00198   for(it = material_list.begin();it!=material_list.end();it++)
00199   {
00200     if((*it).Z != 0) {
00201       if (DEBUG) G4cout << "---->adding Material, "
00202                         << "name= "<< (*it).name << " "
00203                         << "Z= " << (*it).Z << " "
00204                         << "A= " << (*it).A << "g/mole "
00205                         << "density= "<< (*it).density << "g/cm3 "
00206                         << G4endl;
00207 
00208       theMaterials->AddMaterial((*it).name,(*it).Z,(*it).A,(*it).density);
00209     }
00210     else if((*it).components.size() != 0){
00211 
00212       G4State itsState;
00213       if ((*it).state=="solid") itsState = kStateSolid;
00214       else
00215       if ((*it).state=="liquid") itsState = kStateLiquid;
00216       else
00217       if ((*it).state=="gas") itsState = kStateGas;
00218       else {
00219         G4cout << "Unknown material state "<< (*it).state 
00220                << ", setting it to default (solid)"
00221                << G4endl;
00222         (*it).state="solid";
00223         itsState = kStateSolid;
00224       }
00225 
00226       if((*it).componentsWeights.size()==(*it).components.size()) {
00227 
00228         if (DEBUG) G4cout << "---->adding Material, "
00229                           << "name= "<< (*it).name << " "
00230                           << "density= "<< (*it).density << "g/cm3 "
00231                           << "state= " << (*it).state << " "
00232                           << "T= " << (*it).temper << "K "
00233                           << "P= " << (*it).pressure << "atm "
00234                           << "ncomponents= " << (*it).components.size() << " "
00235                           << G4endl;
00236 
00237         theMaterials->AddMaterial((*it).name,
00238                                   (*it).density,
00239                                   itsState,
00240                                   (*it).temper,
00241                                   (*it).pressure,
00242                                   (*it).components,
00243                                   (*it).componentsWeights);
00244       }
00245       else if((*it).componentsFractions.size()==(*it).components.size()) {
00246 
00247         if (DEBUG) G4cout << "---->adding Material, "
00248                           << "name= "<< (*it).name << " "
00249                           << "density= "<< (*it).density << "g/cm3 "
00250                           << "state= " << (*it).state << " "
00251                           << "T= " << (*it).temper << "K "
00252                           << "P= " << (*it).pressure << "atm "
00253                           << "ncomponents= " << (*it).components.size() << " "
00254                           << G4endl;
00255 
00256         theMaterials->AddMaterial((*it).name,
00257                                   (*it).density,
00258                                   itsState,
00259                                   (*it).temper,
00260                                   (*it).pressure,
00261                                   (*it).components,
00262                                   (*it).componentsFractions);
00263       }
00264       else {
00265         G4Exception("Badly defined material - number of components is not equal to number of weights or mass fractions!");
00266         exit(1);
00267       }
00268     }
00269     else {
00270       G4Exception("Badly defined material - need more information!");
00271       exit(1);
00272     }
00273   }
00274   if (verbose || DEBUG) G4cout << "size of material list: "<< material_list.size() << G4endl;
00275 
00276 
00277   //
00278   // set global magnetic field first
00279   //
00280   SetMagField(0.0); // necessary to set a global field; so chose zero
00281 
00282   
00283   //
00284   // compute magnetic rigidity brho
00285   // formula: B(Tesla)*rho(m) = p(GeV)/(0.299792458 * |charge(e)|)
00286   //
00287   // charge (in |e| units)
00288   G4double charge = BDSGlobals->GetParticleDefinition()->GetPDGCharge();
00289   // momentum (in GeV/c)
00290   G4double momentum = BDSGlobals->GetBeamMomentum();
00291   // rigidity (in T*m)
00292   G4double brho = ( (momentum/GeV) / (0.299792458 * charge));
00293   // rigidity (in Geant4 units)
00294   brho *= (tesla*m);
00295   if (verbose || DEBUG) G4cout << "Rigidity (Brho) : "<< fabs(brho)/(tesla*m) << " T*m"<<G4endl;
00296 
00297 
00298   //
00299   // beampipe default outer radius (if not overridden by "aper" option)
00300   //
00301   G4double bpRad=BDSGlobals->GetBeampipeRadius();
00302   if (verbose || DEBUG) G4cout<<"Default pipe outer radius= "<<bpRad/m<< "m"
00303                               << G4endl;
00304 
00305 
00306   // I suspect FeRad is planned to be offered as an option for the inner radius
00307   // of the iron in case it is different from the beampipe outer radius
00308   // Not done yet.
00309   G4double FeRad = bpRad;
00310   if (verbose || DEBUG) G4cout<<"Default magnet inner radius= "<<FeRad/m<< "m"
00311                               << G4endl;
00312 
00313 
00314   // magnetic field moments (depending on the magnet type)
00315   G4double bField;       // dipole (constant) field (G4 units)
00316   G4double bPrime;       // quadrupole field gradient dBy/dx (G4 units)
00317   G4double bDoublePrime; // sextupole field coefficient d^2 By/dx^2 (G4 units)
00318   G4double bTriplePrime; // octupole field coefficient d^3 By/dy^3 (G4 units)
00319 
00320 
00321   // stuff for rescaling due to synchrotron radiation, IGNORING
00322   G4double synch_factor = 1;
00323 
00324 
00325   //
00326   G4double samplerLength = 1.E-11 * m;
00327 
00328 
00329   //
00330   // convert the parsed element list to list of BDS elements
00331   //
00332   G4bool added_comp = false;
00333   if (verbose || DEBUG) G4cout << "parsing the beamline element list..."<< G4endl;
00334   for(it = beamline_list.begin();it!=beamline_list.end();it++)
00335     {
00336       added_comp = false;
00337 
00338       if((*it).type==_SAMPLER ) {
00339         if(DEBUG) G4cout << "---->adding Sampler,"
00340                          << " name= " << (*it).name
00341                          << G4endl;
00342 
00343         theBeamline.push_back(new BDSSampler( (*it).name,
00344                                               samplerLength ) );
00345         bdsOutput.nSamplers++;
00346       
00347         added_comp=true;
00348       }
00349 
00350       if((*it).type==_CSAMPLER ) {
00351 
00352         // replace short cylinders with 1 meter cylinders
00353         if( (*it).l < 1.E-4 ) (*it).l = 1.0 ;
00354 
00355         if(DEBUG) G4cout << "---->adding CSampler,"
00356                          << " name= " << (*it).name
00357                          << " l= " << (*it).l << "m"
00358                          << " r= " << (*it).r << "m"
00359                          << G4endl;
00360 
00361         theBeamline.push_back(new BDSSamplerCylinder( (*it).name,
00362                                                       (*it).l * m,
00363                                                       (*it).r * m ) );
00364         bdsOutput.nSamplers++;
00365       
00366         added_comp=true;
00367       }
00368 
00369       if((*it).type==_DUMP ) {
00370         if(DEBUG) G4cout << "---->adding Dump,"
00371                          << " name= " << (*it).name
00372                          << G4endl;
00373 
00374         theBeamline.push_back(new BDSDump( (*it).name,
00375                                            samplerLength ) );
00376 
00377         added_comp=true;
00378       }
00379 
00380       if((*it).type==_DRIFT ) {
00381         G4double aper = bpRad;
00382         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00383 
00384         if((*it).l > 0) // skip zero-length elements
00385           {
00386             if(DEBUG) G4cout << "---->adding Drift,"
00387                              << " name= " << (*it).name
00388                              << " l= " << (*it).l << "m"
00389                              << " aper= " << aper/m << "m"
00390                              << G4endl;
00391 
00392             theBeamline.push_back(new BDSDrift( (*it).name,
00393                                                 (*it).l*m,
00394                                                 aper ) );
00395             added_comp=true;
00396           } else {
00397             G4cerr << "---->NOT adding Drift,"
00398                    << " name= " << (*it).name
00399                    << ", TOO SHORT LENGTH:"
00400                    << " l= " << (*it).l << "m"
00401                    << G4endl;
00402           }
00403       }
00404 
00405       if((*it).type==_RF ) {
00406         G4double aper = bpRad;
00407         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00408 
00409         if((*it).l > 0) // skip zero-length elements
00410           {
00411             if(DEBUG) G4cout << "---->adding RF,"
00412                              << " name= " << (*it).name
00413                              << " l= " << (*it).l << "m"
00414                              << " aper= " << aper/m << "m"
00415                              << " grad= " << (*it).gradient << "MV/m"
00416                              << G4endl;
00417 
00418             theBeamline.push_back(new BDSRfCavity( (*it).name,
00419                                                    (*it).l * m,
00420                                                    aper,
00421                                                    (*it).gradient,
00422                                                    (*it).material ) );
00423             added_comp=true;
00424           } else {
00425             G4cerr << "---->NOT adding RF,"
00426                    << " name= " << (*it).name
00427                    << ", TOO SHORT LENGTH:"
00428                    << " l= " << (*it).l << "m"
00429                    << G4endl;
00430           }
00431       }
00432       
00433       if((*it).type==_SBEND ) {
00434 
00435         //
00436         // geometry
00437         //
00438         G4double aper = bpRad;
00439         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00440 
00441         FeRad = aper;
00442 
00443         if( (*it).outR < aper/m)
00444           {
00445             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00446                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00447             G4cerr << (*it).name << ": setting outer radius to default = "
00448                    << "aper+22*cm"<<G4endl;
00449             (*it).outR = aper/m + 0.22;
00450           }
00451 
00452         // arc length
00453         G4double length = (*it).l*m;
00454 
00455         //
00456         // magnetic field
00457         //
00458 
00459         // MAD conventions:
00460         // 1) a positive bend angle represents a bend to the right, i.e.
00461         // towards negative x values (even for negative charges??)
00462         // 2) a positive K1 = 1/|Brho| dBy/dx means horizontal focusing of
00463         // positive charges
00464         // CHECK SIGNS 
00465         //
00466         if((*it).B != 0){
00467           // angle = arc length/radius of curvature = L/rho = (B*L)/(B*rho)
00468           bField = (*it).B * tesla;
00469           (*it).angle  = - bField * length / brho;
00470         }
00471         else{
00472           (*it).angle *= -1;
00473           // B = Brho/rho = Brho/(arc length/angle)
00474           bField = - brho * (*it).angle / length;
00475           (*it).B = bField/tesla;
00476         }
00477 
00478         // synch factor??
00479 
00480         // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00481         // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00482         bPrime = - brho * ((*it).k1 / (m*m)) * synch_factor;
00483 
00484         if( fabs((*it).angle) < 1.e-7 * rad) {
00485           if(DEBUG)
00486           G4cerr << "---->NOT adding Sbend,"
00487                  << " name= " << (*it).name
00488                  << ", TOO SMALL ANGLE"
00489                  << " angle= " << (*it).angle << "rad"
00490                  << ": REPLACED WITH Drift,"
00491                  << " l= " << length/m << "m"
00492                  << " aper= " << aper/m << "m"
00493                  << G4endl;
00494 
00495           theBeamline.push_back(new BDSDrift( (*it).name,
00496                                               length,
00497                                               aper ) );
00498         }
00499         else {
00500           if(DEBUG) G4cout << "---->adding Sbend "
00501                            << " name= " << (*it).name
00502                            << " l= " << length/m << "m"
00503                            << " angle= " << (*it).angle << "rad"
00504                            << " B= " << bField/tesla << "T"
00505                            << " B'= " << bPrime/(tesla/m) << "T/m"
00506                            << " tilt= " << (*it).tilt 
00507                            << " aper= " << aper/m << "m"
00508                            << " outR= " << (*it).outR << "m"
00509                            << " FeRad= " << FeRad/m << "m"
00510                            << " material= " << (*it).material
00511                            << G4endl;
00512 
00513 
00514           // REPLACE WITH BDSRBend FOR THE MOMENT (UNTIL TOROIDAL GEOMETRY IS
00515           // IMPLEMENTED!
00516           length *= sin((*it).angle/2.0) / ((*it).angle/2.0);
00517 
00518           theBeamline.push_back(new BDSRBend( (*it).name,
00519                                                    length,
00520                                                    aper,
00521                                                    FeRad,
00522                                                    bField,
00523                                                    (*it).angle,
00524                                                    (*it).outR*m,
00525                                                    (*it).tilt,
00526                                                    bPrime,
00527                                                    (*it).material ) );
00528 /*        
00529           theBeamline.push_back(new BDSSectorBend( (*it).name,
00530                                                    length,
00531                                                    aper,
00532                                                    FeRad,
00533                                                    bField,
00534                                                    (*it).angle,
00535                                                    (*it).outR*m,
00536                                                    (*it).tilt,
00537                                                    bPrime,
00538                                                    (*it).material ) );
00539 */        
00540         }
00541       
00542         added_comp=true;
00543       }
00544 
00545       if((*it).type==_RBEND ) {
00546 
00547         //
00548         // geometry
00549         //
00550         G4double aper = bpRad;
00551         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00552 
00553         FeRad = aper;
00554 
00555         if( (*it).outR < aper/m)
00556           {
00557             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00558                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00559             G4cerr << (*it).name << ": setting outer radius to default = "
00560                    << "aper+22*cm"<<G4endl;
00561             (*it).outR = aper/m + 0.22;
00562           }
00563 
00564         G4double length = (*it).l*m; //geometrical length
00565 
00566         //
00567         // magnetic field
00568         //
00569 
00570         // CHECK SIGNS OF B, B', ANGLE
00571         if((*it).B != 0){
00572           // angle = arc length/radius of curvature = L/rho = (B*L)/(B*rho)
00573           bField = (*it).B * tesla;
00574           G4double rho = brho/bField;
00575           //(*it).angle  = - bField * length / brho;
00576           (*it).angle  = - 2.0*asin(length/2.0/rho);
00577         }
00578         else{
00579           (*it).angle *= -1;
00580           // arc length = radius*angle
00581           //            = (geometrical length/(2.0*sin(angle/2))*angle
00582           G4double arclength = 0.5*length * (*it).angle / sin((*it).angle/2.0);
00583           // B = Brho/rho = Brho/(arc length/angle)
00584           bField = - brho * (*it).angle / arclength;
00585           (*it).B = bField/tesla;
00586         }
00587 
00588         // synch factor???
00589 
00590         // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00591         // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00592         bPrime = - brho * ((*it).k1 / (m*m)) * synch_factor;
00593 
00594         if( fabs((*it).angle) < 1.e-7 * rad) {
00595           if(DEBUG)
00596             G4cerr << "---->NOT adding Rbend,"
00597                  << " name= " << (*it).name
00598                  << ", TOO SMALL ANGLE"
00599                  << " angle= " << (*it).angle << "rad"
00600                  << ": REPLACED WITH Drift,"
00601                  << " l= " << length/m << "m"
00602                  << " aper= " << aper/m << "m"
00603                  << G4endl;
00604           
00605           theBeamline.push_back(new BDSDrift( (*it).name,
00606                                               length,
00607                                               aper ) );
00608         }
00609         else {
00610           if(DEBUG) G4cout << "---->adding Rbend,"
00611                            << " name= " << (*it).name 
00612                            << " l= " << length/m << "m"
00613                            << " angle= " << (*it).angle << "rad"
00614                            << " B= " << bField/tesla << "T"
00615                            << " B'= " << bPrime/(tesla/m) << "T/m"
00616                            << " tilt= " << (*it).tilt 
00617                            << " aper= " << aper/m << "m"
00618                            << " outR= " << (*it).outR << "m"
00619                            << " FeRad= " << FeRad/m << "m"
00620                            << " material= " << (*it).material
00621                            << G4endl;
00622 
00623           theBeamline.push_back(new BDSRBend( (*it).name,
00624                                               length,
00625                                               aper,
00626                                               FeRad,
00627                                               bField,
00628                                               (*it).angle,
00629                                               (*it).outR*m,
00630                                               (*it).tilt,
00631                                               bPrime,
00632                                               (*it).material ) );
00633         }
00634 
00635         added_comp=true;
00636       }
00637 
00638       if((*it).type==_HKICK ) {
00639 
00640         //
00641         // geometry
00642         //
00643         G4double aper = bpRad;
00644         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00645 
00646         FeRad = aper;
00647 
00648         if( (*it).outR < aper/m)
00649           {
00650             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00651                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00652             G4cerr << (*it).name << ": setting outer radius to default = "
00653                    << "aper+22*cm"<<G4endl;
00654             (*it).outR = aper/m + 0.22;
00655           }
00656         
00657         G4double length = (*it).l*m;
00658 
00659         //
00660         // magnetic field
00661         //
00662         if((*it).B != 0){
00663           // angle = arc length/radius of curvature = L/rho = (B*L)/(B*rho)
00664           bField = (*it).B * tesla;
00665           (*it).angle  = -bField * length / brho;
00666         }
00667         else{
00668           // B = Brho/rho = Brho/(arc length/angle)
00669           bField = - brho * (*it).angle / length;
00670           (*it).B = bField/tesla;
00671         }
00672 
00673         // synch factor??
00674         
00675         // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00676         // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00677         bPrime = - brho * ((*it).k1 / (m*m)) * synch_factor;
00678         
00679         if( fabs((*it).angle) < 1.e-7 * rad ) {
00680           G4cerr << "---->NOT adding Hkick,"
00681                  << " name= " << (*it).name
00682                  << ", TOO SMALL ANGLE"
00683                  << " angle= " << (*it).angle << "rad"
00684                  << ": REPLACED WITH Drift,"
00685                  << " l= " << length/m << "m"
00686                  << " aper= " << aper/m << "m"
00687                  << G4endl;
00688 
00689           theBeamline.push_back(new BDSDrift( (*it).name,
00690                                               length,
00691                                               aper ) );
00692         } 
00693         else {
00694           if(DEBUG) G4cout << "---->adding HKick,"
00695                            << " name= " << (*it).name 
00696                            << " l= " << length/m << "m"
00697                            << " angle= " << (*it).angle << "rad"
00698                            << " B= " << bField/tesla << "T"
00699                            << " B'= " << bPrime/(tesla/m) << "T/m"
00700                            << " tilt= " << (*it).tilt 
00701                            << " aper= " << aper/m << "m"
00702                            << " outR= " << (*it).outR << "m"
00703                            << " FeRad= " << FeRad/m << "m"
00704                            << " material= " << (*it).material
00705                            << G4endl;
00706 
00707           theBeamline.push_back(new BDSKicker( (*it).name,
00708                                                length,
00709                                                aper,
00710                                                FeRad,
00711                                                bField,
00712                                                (*it).angle,
00713                                                (*it).outR*m,
00714                                                (*it).tilt,
00715                                                bPrime,
00716                                                (*it).material ) );
00717         }
00718       
00719         added_comp=true;
00720       }
00721 
00722       if((*it).type==_VKICK ) {
00723 
00724         //
00725         // geometry
00726         //
00727         G4double aper = bpRad;
00728         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00729 
00730         FeRad = aper;
00731 
00732         if( (*it).outR < aper/m)
00733           {
00734             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00735                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00736             G4cerr << (*it).name << ": setting outer radius to default = "
00737                    << "aper+22*cm"<<G4endl;
00738             (*it).outR = aper/m + 0.22;
00739           }
00740 
00741         G4double length = (*it).l*m;
00742 
00743         //
00744         // magnetic field
00745         //
00746         if((*it).B != 0){
00747           // angle = arc length/radius of curvature = L/rho = (B*L)/(B*rho)
00748           bField = (*it).B * tesla;
00749           (*it).angle  = -bField * length / brho;
00750         }
00751         else{
00752           // B = Brho/rho = Brho/(arc length/angle)
00753           bField = - brho * (*it).angle / length;
00754           (*it).B = bField/tesla;
00755         }
00756 
00757         // synch factor???
00758 
00759         // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00760         // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00761         bPrime = - brho * ((*it).k1 / (m*m)) * synch_factor;
00762 
00763         if( fabs((*it).angle) < 1.e-7 * rad ) {
00764           G4cerr << "---->NOT adding Vkick,"
00765                  << " name= " << (*it).name
00766                  << ", TOO SMALL ANGLE"
00767                  << " angle= " << (*it).angle << "rad"
00768                  << ": REPLACED WITH Drift,"
00769                  << " l= " << (*it).l << "m"
00770                  << " aper= " << aper/m << "m"
00771                  << G4endl;
00772 
00773           theBeamline.push_back(new BDSDrift( (*it).name,
00774                                               (*it).l * m,
00775                                               aper ) );
00776         } 
00777         else {
00778           if(DEBUG) G4cout << "---->adding VKick,"
00779                            << " name= " << (*it).name 
00780                            << " l= " << (*it).l << "m"
00781                            << " angle= " << (*it).angle << "rad"
00782                            << " B= " << bField/tesla << "T"
00783                            << " B'= " << bPrime/(tesla/m) << "T/m"
00784                            << " tilt= " << (*it).tilt 
00785                            << " aper= " << aper/m << "m"
00786                            << " outR= " << (*it).outR << "m"
00787                            << " FeRad= " << FeRad/m << "m"
00788                            << " material= " << (*it).material
00789                            << G4endl;
00790 
00791           theBeamline.push_back(new BDSKicker( (*it).name,
00792                                                (*it).l * m,
00793                                                aper,
00794                                                FeRad,
00795                                                bField,
00796                                                (*it).angle,
00797                                                (*it).outR * m,
00798                                                pi/2,
00799                                                bPrime,
00800                                                (*it).material ) );
00801         }
00802       
00803         added_comp=true;
00804       }
00805 
00806 
00807       if((*it).type==_QUAD ) {
00808 
00809         //
00810         // geometry
00811         //
00812         G4double aper = bpRad;
00813         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00814 
00815         FeRad = aper;
00816         
00817         if( (*it).outR < aper/m)
00818           {
00819             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00820                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00821             G4cerr << (*it).name << ": setting outer radius to default = "
00822                    << "aper+22*cm"<<G4endl;
00823             (*it).outR = aper/m + 0.22;
00824           }
00825         
00826         //
00827         // magnetic field
00828         //
00829 
00830         // B' = dBy/dx = Brho * (1/Brho dBy/dx) = Brho * k1
00831         // Brho is already in G4 units, but k1 is not -> multiply k1 by m^-2
00832         bPrime = - brho * ((*it).k1 / (m*m)) * synch_factor;
00833 
00834         if(DEBUG) G4cout << "---->adding Quadrupole,"
00835                          << " name= " << (*it).name
00836                          << " l= " << (*it).l << "m"
00837                          << " k1= " << (*it).k1 << "m^-2"
00838                          << " brho= " << fabs(brho)/(tesla*m) << "T*m"
00839                          << " B'= " << bPrime/(tesla/m) << "T/m"
00840                          << " aper= " << aper/m << "m"
00841                          << " outR= " << (*it).outR << "m"
00842                          << " FeRad= " << FeRad/m << "m"
00843                          << " material= " << (*it).material
00844                          << G4endl;
00845         
00846         theBeamline.push_back(new BDSQuadrupole( (*it).name,
00847                                                  (*it).l * m,
00848                                                  aper,
00849                                                  FeRad,
00850                                                  bPrime, 
00851                                                  (*it).tilt,
00852                                                  (*it).outR * m, 
00853                                                  (*it).material,
00854                                                  (*it).spec ) );
00855         
00856         added_comp=true;
00857       }
00858       
00859       if((*it).type==_SEXTUPOLE ) {
00860 
00861         //
00862         // geometry
00863         //
00864         G4double aper = bpRad;
00865         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00866 
00867         FeRad = aper;
00868 
00869         if( (*it).outR < aper/m)
00870           {
00871             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00872                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00873             G4cerr << (*it).name << ": setting outer radius to default = "
00874                    << "aper+22*cm"<<G4endl;
00875             (*it).outR = aper/m + 0.22;
00876           }
00877 
00878         //
00879         // magnetic field
00880         //
00881 
00882         // B'' = d^2By/dx^2 = Brho * (1/Brho d^2By/dx^2) = Brho * k2
00883         // brho is in Geant4 units, but k2 is not -> multiply k2 by m^-3
00884         bDoublePrime = - brho * ((*it).k2 / (m*m*m)) * synch_factor;
00885 
00886         if(DEBUG) G4cout << "---->adding Sextupole,"
00887                          << " name= " << (*it).name
00888                          << " l= " << (*it).l << "m"
00889                          << " k2= " << (*it).k2 << "m^-3"
00890                          << " brho= " << fabs(brho)/(tesla*m) << "T*m"
00891                          << " B''= " << bDoublePrime/(tesla/(m*m)) << "T/m^2"
00892                          << " aper= " << aper/m << "m"
00893                          << " outR= " << (*it).outR << "m"
00894                          << " FeRad= " << FeRad/m << "m"
00895                          << " material= " << (*it).material
00896                          << G4endl;
00897 
00898         theBeamline.push_back(new BDSSextupole( (*it).name,
00899                                                 (*it).l * m,
00900                                                 aper,
00901                                                 FeRad,
00902                                                 bDoublePrime,
00903                                                 (*it).tilt,
00904                                                 (*it).outR * m,
00905                                                 (*it).material ) );
00906       
00907         added_comp=true;
00908       }
00909 
00910       if((*it).type==_OCTUPOLE ) {
00911 
00912         //
00913         // geometry
00914         //
00915         G4double aper = bpRad;
00916         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00917 
00918         FeRad = aper;
00919 
00920         if( (*it).outR < aper/m)
00921           {
00922             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00923                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00924             G4cerr << (*it).name << ": setting outer radius to default = "
00925                    << "aper+22*cm"<<G4endl;
00926             (*it).outR = aper/m + 0.22;
00927           }
00928 
00929         //
00930         // magnetic field
00931         //
00932 
00933         // B''' = d^3By/dx^3 = Brho * (1/Brho d^3By/dx^3) = Brho * k3
00934         // brho is in Geant4 units, but k3 is not -> multiply k3 by m^-4
00935         bTriplePrime = - brho * ((*it).k3 / (m*m*m*m)) * synch_factor;
00936 
00937         if(DEBUG) G4cout << "---->adding Octupole,"
00938                          << " name= " << (*it).name
00939                          << " l= " << (*it).l << "m"
00940                          << " k3= " << (*it).k3 << "m^-4"
00941                          << " brho= " << fabs(brho)/(tesla*m) << "T*m"
00942                          << " B'''= " << bTriplePrime/(tesla/(m*m*m)) << "T/m^3"
00943                          << " aper= " << aper/m << "m"
00944                          << " outR= " << (*it).outR << "m"
00945                          << " FeRad= " << FeRad/m << "m"
00946                          << " material= " << (*it).material
00947                          << G4endl;
00948 
00949         theBeamline.push_back(new BDSOctupole( (*it).name,
00950                                                (*it).l * m,
00951                                                aper,
00952                                                FeRad,
00953                                                bTriplePrime,
00954                                                (*it).tilt,
00955                                                (*it).outR * m,
00956                                                (*it).material ) );
00957       
00958         added_comp=true;
00959       }
00960 
00961       if((*it).type==_MULT ) {
00962         
00963         //
00964         // geometry
00965         //
00966         G4double aper = bpRad;
00967         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
00968 
00969         FeRad = aper;
00970 
00971         if( (*it).outR < aper/m)
00972           {
00973             G4cerr << (*it).name << ": outer radius smaller than aperture: "
00974                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
00975             G4cerr << (*it).name << ": setting outer radius to default = "
00976                    << "aper+22*cm"<<G4endl;
00977             (*it).outR = aper/m + 0.22;
00978           }
00979 
00980         if(DEBUG) G4cout << "---->adding Multipole,"
00981                          << " name= " << (*it).name
00982                          << " l= " << (*it).l << "m"
00983                          << " aper= " << aper/m << "m"
00984                          << " outR= " << (*it).outR << "m"
00985                          << " FeRad= " << FeRad/m << "m"
00986                          << " material= " << (*it).material
00987                          << G4endl;
00988 
00989         //
00990         // magnetic field
00991         //
00992 
00993         list<double>::iterator kit;
00994         
00995         if(DEBUG) G4cout << " knl={ ";
00996         for(kit=(it->knl).begin();kit!=(it->knl).end();kit++)
00997           {
00998             if(DEBUG) G4cout<<(*kit)<<", ";
00999             (*kit) /= (*it).l; 
01000           }
01001         if(DEBUG) G4cout << " }";
01002         
01003         if(DEBUG) G4cout << " ksl={ ";
01004         for(kit=(it->ksl).begin();kit!=(it->ksl).end();kit++)
01005           {
01006             if(DEBUG) G4cout<<(*kit)<<" ";
01007             (*kit) /= (*it).l; 
01008           }
01009         if(DEBUG) G4cout << " }" << G4endl;
01010         
01011         theBeamline.push_back(new BDSTMultipole( (*it).name,
01012                                                  (*it).l * m,
01013                                                  aper,
01014                                                  FeRad,
01015                                                  (*it).outR*m,
01016                                                  it->knl,
01017                                                  it->ksl,
01018                                                  (*it).material ) );
01019 
01020         added_comp=true;
01021       }
01022       
01023       if((*it).type==_ELEMENT ) {
01024 
01025         //
01026         // geometry
01027         //
01028         G4double aper = bpRad;
01029         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
01030 
01031 /* Fix for element volume overlaps - do not set default outR!
01032         if( (*it).outR < aper/m)
01033           {
01034             G4cerr << (*it).name << ": outer radius smaller than aperture: "
01035                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
01036             G4cerr << (*it).name << ": setting outer radius to default = "
01037                    << "aper+22*cm"<<G4endl;
01038             (*it).outR = aper/m + 0.22;
01039           }
01040 */
01041         if(DEBUG) G4cout << "---->adding Element,"
01042                          << " name= " << (*it).name
01043                          << " l= " << (*it).l << "m"
01044                          << " aper= " << aper/m << "m"
01045                          << " outR= " << (*it).outR << "m"
01046                          << G4endl;
01047         
01048         theBeamline.push_back(new BDSElement( (*it).name,
01049                                               (*it).geometryFile,
01050                                               (*it).bmapFile,
01051                                               (*it).l * m,
01052                                               aper,
01053                                               (*it).outR*m ) );
01054       
01055         added_comp=true;
01056       }
01057 
01058       if((*it).type==_SOLENOID ) {
01059 
01060         //
01061         // geometry
01062         //
01063         G4double aper = bpRad;
01064         if( (*it).aper > 1.e-10*m ) aper = (*it).aper * m;
01065 
01066         FeRad = aper;
01067 
01068         if( (*it).outR < aper/m)
01069           {
01070             G4cerr << (*it).name << ": outer radius smaller than aperture: "
01071                    << "aper= "<<aper/m<<"m outR= "<<(*it).outR<<"m"<<G4endl;
01072             G4cerr << (*it).name << ": setting outer radius to default = "
01073                    << "aper+22*cm"<<G4endl;
01074             (*it).outR = aper/m + 0.22;
01075           }
01076 
01077         //
01078         // magnetic field
01079         //
01080         // B = B/Brho * Brho = ks * Brho
01081         // brho is in Geant4 units, but ks is not -> multiply ks by m^-1
01082         G4double bField;
01083         if((*it).B != 0){
01084           bField = (*it).B * tesla;
01085           (*it).ks  = (bField/brho) / m;
01086         }
01087         else{
01088           bField = ((*it).ks/m) * brho;
01089           (*it).B = bField/tesla;
01090         }
01091 
01092         if(DEBUG) G4cout << "---->adding Solenoid,"
01093                          << " name= " << (*it).name
01094                          << " l= " << (*it).l << "m"
01095                          << " ks= " << (*it).ks << "m^-1"
01096                          << " brho= " << fabs(brho)/(tesla*m) << "T*m"
01097                          << " B= " << bField/tesla << "T"
01098                          << " aper= " << aper/m << "m"
01099                          << " outR= " << (*it).outR << "m"
01100                          << " FeRad= " << FeRad/m << "m"
01101                          << " material= " << (*it).material
01102                          << G4endl;
01103         
01104         theBeamline.push_back(new BDSSolenoid( (*it).name,
01105                                                (*it).l * m,
01106                                                aper,
01107                                                FeRad,
01108                                                bField,
01109                                                (*it).outR*m,
01110                                                (*it).material,
01111                                                (*it).spec ) );
01112         
01113         added_comp=true;
01114       }
01115       
01116       if((*it).type==_ECOL ) {
01117 
01118         G4Material* theMaterial;
01119         if((*it).material != "")
01120           theMaterial = theMaterials->GetMaterial( (*it).material );
01121         else
01122           theMaterial = theMaterials->GetMaterial( "Graphite" );
01123 
01124         if(DEBUG) G4cout << "---->adding Ecol,"
01125                          << " name= " << (*it).name 
01126                          << " xaper= " << (*it).xsize <<"m"
01127                          << " yaper= " << (*it).ysize <<"m"
01128                          << " material= " << (*it).material
01129                          << G4endl;
01130 
01131         theBeamline.push_back(new BDSCollimator((*it).name,
01132                                                 (*it).l * m,
01133                                                 bpRad,
01134                                                 (*it).xsize * m,
01135                                                 (*it).ysize * m,
01136                                                 _ECOL,
01137                                                 theMaterial,
01138                                                 (*it).outR*m) );
01139       
01140         added_comp=true;
01141       }
01142 
01143       if((*it).type==_RCOL ) {
01144 
01145         G4Material* theMaterial;
01146         if((*it).material != "")
01147           theMaterial = theMaterials->GetMaterial( (*it).material );
01148         else
01149           theMaterial = theMaterials->GetMaterial( "Graphite" );
01150 
01151         if(DEBUG) G4cout << "---->adding Rcol,"
01152                          << " name= " << (*it).name 
01153                          << " xaper= " << (*it).xsize <<"m"
01154                          << " yaper= " << (*it).ysize <<"m"
01155                          << " material= " << (*it).material
01156                          << G4endl;
01157 
01158         theBeamline.push_back(new BDSCollimator( (*it).name,
01159                                                  (*it).l * m,
01160                                                  bpRad,
01161                                                  (*it).xsize * m,
01162                                                  (*it).ysize * m,
01163                                                  _RCOL,
01164                                                  theMaterial,
01165                                                  (*it).outR*m) );
01166       
01167         added_comp=true;
01168       }
01169 
01170       if((*it).type==_LASER ) {
01171         if((*it).l == 0) (*it).l = 1e-8;
01172         
01173         if(DEBUG) G4cout << "---->adding Laser,"
01174                          << " name= "<< (*it).name
01175                          << " l=" << (*it).l/m<<"m"
01176                          << " lambda= " << (*it).waveLength/m << "m"
01177                          << " xSigma= " << (*it).xsize/m << "m"
01178                          << " ySigma= " << (*it).ysize/m << "m"
01179                          << " xdir= " << (*it).xdir
01180                          << " ydir= " << (*it).ydir
01181                          << " zdir= " << (*it).zdir
01182                          << G4endl;
01183         
01184         G4ThreeVector direction = 
01185           G4ThreeVector((*it).xdir,(*it).ydir,(*it).zdir);
01186         G4ThreeVector position  = G4ThreeVector(0,0,0);
01187         
01188         theBeamline.push_back(new BDSLaserWire( (*it).name,
01189                                                 (*it).l * m,
01190                                                 (*it).waveLength * m,
01191                                                 direction,
01192                                                 position ) );
01193         
01194         added_comp=true;
01195       }
01196 
01197       if((*it).type==_TRANSFORM3D ) {
01198         
01199         if(DEBUG) G4cout << "---->adding Transform3d,"
01200                          << " name= " << (*it).name
01201                          << " xdir= " << (*it).xdir/m << "m"
01202                          << " ydir= " << (*it).ydir/m << "m"
01203                          << " zdir= " << (*it).zdir/m << "m"
01204                          << " phi= " << (*it).phi/rad << "rad"
01205                          << " theta= " << (*it).theta/rad << "rad"
01206                          << " psi= " << (*it).psi/rad << "rad"
01207                          << G4endl;
01208         
01209         theBeamline.push_back(new BDSTransform3D( (*it).name,
01210                                                   (*it).xdir *m,
01211                                                   (*it).ydir *m,
01212                                                   (*it).zdir *m,
01213                                                   (*it).phi *rad,
01214                                                   (*it).theta *rad,
01215                                                   (*it).psi *rad ) );
01216         
01217       
01218         added_comp=true;
01219       }
01220 
01221       if(added_comp)      //for BDSOutline
01222         {
01223           list<BDSAcceleratorComponent*>::iterator curr = theBeamline.end();
01224           curr--; //get last element added
01225       
01226           (*curr)->SetK1((*it).k1);
01227           (*curr)->SetK2((*it).k2);
01228           (*curr)->SetK3((*it).k3);
01229         }
01230     }
01231   
01232   
01233   if (verbose || DEBUG) G4cout << "size of beamline element list: "<< beamline_list.size() << G4endl;
01234   
01235   
01236   //
01237   // construct the component list
01238   //
01239 
01240   if (verbose || DEBUG) G4cout << "now constructing geometry" << G4endl;
01241   
01242   list<BDSAcceleratorComponent*>::const_iterator iBeam;
01243   
01244   G4ThreeVector rtot = G4ThreeVector(0.,0.,0.);   // world dimension
01245   G4ThreeVector rlast = G4ThreeVector(0.,0.,0.);  // edge of last element coordinates
01246   G4ThreeVector rmin = G4ThreeVector(0.,0.,0.);
01247   G4ThreeVector rmax = G4ThreeVector(0.,0.,0.);
01248 
01249   G4ThreeVector localX = G4ThreeVector(1,0,0);  // local coordinate axis
01250   G4ThreeVector localY = G4ThreeVector(0,1,0);
01251   G4ThreeVector localZ = G4ThreeVector(0,0,1);
01252 
01253   G4double s_tot = 0; // position along the beamline
01254 
01255   // define geometry scope
01256   for(iBeam=theBeamline.begin();iBeam!=theBeamline.end();iBeam++)
01257     {
01258 
01259       if(DEBUG) G4cout << (*iBeam)->GetName() << "  "
01260                        << (*iBeam)->GetLength() << "  "
01261                        << (*iBeam)->GetAngle() << "  "
01262                        << G4endl;
01263 
01264       (*iBeam)->SetSPos(s_tot+(*iBeam)->GetArcLength()/2.0);
01265 
01266       // advance coordinates , but not for cylindrical sampler
01267       if(( (*iBeam)->GetType() != "sampler") || ( (*iBeam)->GetLength() <= samplerLength ) )
01268         {
01269           s_tot+= (*iBeam)->GetArcLength();
01270 
01271           G4double angle=(*iBeam)->GetAngle();
01272           if(!angle && (*iBeam)->GetType()=="transform3d")
01273             angle=(*iBeam)->GetPhi();
01274           G4double theta=(*iBeam)->GetTheta();
01275           G4double psi=(*iBeam)->GetPsi();
01276 
01277           // define new coordinate system local frame     
01278           localX.rotate(psi,localZ);
01279           localY.rotate(psi,localZ);
01280           localZ.rotate(psi,localZ);
01281 
01282           localX.rotate(angle,localY);
01283           localY.rotate(angle,localY);
01284           localZ.rotate(angle,localY);
01285 
01286           localX.rotate(theta,localX);
01287           localY.rotate(theta,localX);
01288           localZ.rotate(theta,localX);
01289 
01290           // advance the coordinate system translation
01291           rtot += localZ * (*iBeam)->GetZLength();
01292           if(DEBUG)
01293             G4cout << (*iBeam)->GetType() << " " << rtot << G4endl;
01294         }
01295 
01296       if(rmax(0)<rtot(0)) rmax(0) = rtot(0);
01297       if(rmax(1)<rtot(1)) rmax(1) = rtot(1);
01298       if(rmax(2)<rtot(2)) rmax(2) = rtot(2);
01299 
01300       if(rmin(0)>rtot(0)) rmin(0) = rtot(0);
01301       if(rmin(1)>rtot(1)) rmin(1) = rtot(1);
01302       if(rmin(2)>rtot(2)) rmin(2) = rtot(2);
01303     }
01304     
01305   
01306   BDSGlobals->SetTotalS(s_tot);
01307   
01308   // -----------------------------------
01309   
01310   // determine the world size
01311   
01312   G4String LocalName="World";
01313   
01314   G4double WorldSizeX = 1 * ( (fabs(rmin(0)) + fabs(rmax(0)) ) + 5*BDSGlobals->GetComponentBoxSize());
01315   G4double WorldSizeY = 1 * ( (fabs(rmin(1)) + fabs(rmax(1)) ) + 5*BDSGlobals->GetComponentBoxSize());
01316   G4double WorldSizeZ = 1 * ( (fabs(rmin(2)) + fabs(rmax(2)) ) + 5*BDSGlobals->GetComponentBoxSize());
01317   
01318   //G4cout<<"world radius="<<WorldRadius/m<<" m"<<G4endl;
01319   if(verbose || DEBUG)
01320     {
01321       G4cout<<"minX="<<rmin(0)/m<<"m"<<" maxX="<<rmax(0)/m<<" m"<<G4endl;
01322       G4cout<<"minY="<<rmin(1)/m<<"m"<<" maxY="<<rmax(1)/m<<" m"<<G4endl;
01323       G4cout<<"minZ="<<rmin(2)/m<<"m"<<" maxZ="<<rmax(2)/m<<" m"<<G4endl;
01324       
01325       G4cout<<"box size="<<BDSGlobals->GetComponentBoxSize()/m<<" m"<<G4endl;
01326       G4cout<<"s_tot="<<s_tot/m<<" m"<<G4endl;
01327     }
01328 
01329   bdsOutput.zMax=s_tot;
01330 
01331   solidWorld = new G4Box("World", WorldSizeX, WorldSizeY, WorldSizeZ);
01332     
01333   logicWorld = new G4LogicalVolume(solidWorld,         //its solid
01334                                    theMaterials->GetMaterial("Vacuum"), //its material
01335                                    "World");           //its name
01336   
01337   logicWorld->SetVisAttributes (G4VisAttributes::Invisible);
01338   // set world volume visibility for debugging
01339   if (DEBUG) logicWorld->SetVisAttributes(new G4VisAttributes(true));
01340 
01341   // set default max step length (only for particles which have the
01342   // G4StepLimiter process enabled)
01343   G4UserLimits* WorldUserLimits =new G4UserLimits();
01344   WorldUserLimits->SetMaxAllowedStep(100*m);
01345   logicWorld->SetUserLimits(WorldUserLimits);
01346 
01347 
01348   G4cout<<"Charged Thresholdcut="<<BDSGlobals->GetThresholdCutCharged()/GeV<<" GeV"<<G4endl;
01349   G4cout<<"Photon Thresholdcut="<<BDSGlobals->GetThresholdCutPhotons()/GeV<<" GeV"<<G4endl;
01350 
01351 
01352   G4cout<<"Creating regions..."<<G4endl;
01353   
01354   G4Region* precisionRegion = new G4Region("precision");
01355    
01356   G4ProductionCuts* theProductionCuts = new G4ProductionCuts();
01357   
01358   if(BDSGlobals->GetProdCutPhotonsP()>0)
01359     theProductionCuts->SetProductionCut(BDSGlobals->GetProdCutPhotonsP(),"gamma");
01360 
01361   if(BDSGlobals->GetProdCutElectronsP()>0)
01362     theProductionCuts->SetProductionCut(BDSGlobals->GetProdCutElectronsP(),"e-");
01363 
01364   if(BDSGlobals->GetProdCutPositronsP()>0)
01365     theProductionCuts->SetProductionCut(BDSGlobals->GetProdCutPositronsP(),"e+");
01366   
01367   precisionRegion->SetProductionCuts(theProductionCuts);
01368 
01369   // world
01370 
01371   physiWorld = new G4PVPlacement(0,             // no rotation
01372                                  0,             // at (0,0,0)
01373                                  logicWorld,    // its logical volume
01374                                  LocalName,     // its name
01375                                  NULL,          // its mother  volume
01376                                  false,         // no boolean operation
01377                                  0);            // copy number
01378 
01379 
01380   // sensitive detectors
01381 
01382   G4SDManager* SDman = G4SDManager::GetSDMpointer();
01383 
01384   G4bool use_graphics=true;
01385   G4ThreeVector TargetPos;
01386 
01387   // set default output formats:
01388   G4cout.precision(15);
01389   
01390   if(DEBUG) G4cout<<" total length="<<s_tot/m<<G4endl;
01391   
01392   // reset counters:
01393   for(iBeam=theBeamline.begin();iBeam!=theBeamline.end();iBeam++){
01394 
01395     // zero length components have no logical volumes
01396     if((*iBeam)->GetLength()!=0.)
01397       {
01398         G4String logVolName = (*iBeam)->GetMarkerLogicalVolume()->GetName();
01399         (*LogVolCount)[logVolName]=1;
01400       }
01401   }
01402   
01403   if (verbose || DEBUG) G4cout<<"starting placement procedure "<<G4endl;
01404   
01405   rtot = G4ThreeVector(0.,0.,0.);
01406   localX = G4ThreeVector(1.,0.,0.); 
01407   localY = G4ThreeVector(0.,1.,0.);
01408   localZ = G4ThreeVector(0.,0.,1.);
01409   
01410   G4RotationMatrix globalRotation;
01411   
01412   for(iBeam=theBeamline.begin();iBeam!=theBeamline.end();iBeam++)
01413     { 
01414       //(*iBeam)->SetZLower(rtot.z());
01415        
01416       G4double angle=(*iBeam)->GetAngle();
01417       G4double theta=(*iBeam)->GetTheta();
01418       G4double psi = (*iBeam)->GetPsi();
01419       G4double tilt = (*iBeam)->GetTilt();
01420       G4double phi = (*iBeam)->GetPhi();
01421       G4double length = (*iBeam)->GetZLength();
01422 
01423       if( (*iBeam)->GetType() == "transform3d")
01424         {
01425 
01426           if(DEBUG) G4cout<<"transform3d : "<<phi<<" "<<theta<<" "<<psi<<G4endl;
01427 
01428 
01429           rtot(0) += (*iBeam)->GetXOffset(); 
01430           rtot(1) += (*iBeam)->GetYOffset(); 
01431           rtot(2) += (*iBeam)->GetZOffset(); 
01432 
01433           rlast(0) += (*iBeam)->GetXOffset();
01434           rlast(1) += (*iBeam)->GetYOffset(); 
01435           rlast(2) += (*iBeam)->GetZOffset(); 
01436 
01437           globalRotation.rotate(psi,localZ);
01438           localX.rotate(psi,localZ);
01439           localY.rotate(psi,localZ);
01440 
01441           globalRotation.rotate(phi,localY);
01442           localX.rotate(phi,localY);
01443           localZ.rotate(phi,localY);
01444           
01445           globalRotation.rotate(theta,localX);
01446           localY.rotate(theta,localX);
01447           localZ.rotate(theta,localX);
01448                           
01449           continue;
01450         }
01451       
01452       // rotation matrix for component placement
01453       G4RotationMatrix *rotateComponent = new G4RotationMatrix;
01454 
01455       // tilted bends influence reference frame, otherwise just local tilt
01456       if((*iBeam)->GetType() == "sbend" || (*iBeam)->GetType() == "rbend" )
01457         {
01458           globalRotation.rotate(tilt,localZ);
01459           localX.rotate(tilt,localZ);
01460           localY.rotate(tilt,localZ);
01461         }
01462       else 
01463         rotateComponent->rotateZ(tilt);
01464     
01465       // define center of bended elements from the previos coordinate frame
01466       G4ThreeVector zHalfAngle = localZ; 
01467 
01468       if((*iBeam)->GetType() == "sbend" || (*iBeam)->GetType() == "rbend")
01469         zHalfAngle.rotate(angle/2,localY);
01470 
01471       if(DEBUG)
01472         {
01473           G4cout<<"zHalfAngle="<<zHalfAngle<<G4endl;
01474           G4cout<<"localZ="<<localZ<<G4endl;
01475           G4cout<<"localX="<<localX<<G4endl;
01476           G4cout<<"localY="<<localY<<G4endl;
01477           G4cout<<"rlast="<<rlast<<G4endl;
01478         }
01479       
01480       // target position
01481       TargetPos = rlast + zHalfAngle *  ( length/2 + BDSGlobals->GetLengthSafety()/2 ) ;
01482 
01483       if(DEBUG) G4cout<<"TargetPos="<<TargetPos<<G4endl;
01484 
01485       // advance the coordinates, but not for cylindrical samplers 
01486       if( ( ( (*iBeam)->GetType() != "sampler") || ( length <= samplerLength ) )  && ( (*iBeam)->GetType()!=_ELEMENT ))
01487         {
01488           if(DEBUG) G4cout << (*iBeam)->GetType() << " "
01489                            << (*iBeam)->GetName() << " "
01490                            << G4endl;
01491           rtot = rlast + zHalfAngle * ( length/2 + BDSGlobals->GetLengthSafety()/2 );
01492           rlast = rtot + zHalfAngle * ( length/2 + BDSGlobals->GetLengthSafety()/2 );
01493         }
01494 
01495       // rotate to the previous reference frame
01496       rotateComponent->transform(globalRotation);
01497 
01498       rotateComponent->invert();
01499 
01500       // recompute global rotation
01501       // define new coordinate system local frame         
01502  
01503       // bends transform the coordinate system
01504       if( (*iBeam)->GetType() == "sbend" || (*iBeam)->GetType() == "rbend")
01505         {
01506           globalRotation.rotate(angle,localY);
01507           localX.rotate(angle,localY);
01508           localZ.rotate(angle,localY);
01509           
01510           
01511           globalRotation.rotate(theta,localX);
01512           localY.rotate(theta,localX);
01513           localZ.rotate(theta,localX);
01514           
01515           // bend trapezoids defined along z-axis
01516           rotateComponent->rotateY(-pi/2-angle/2);
01517         }
01518 
01519 
01520       //(*iBeam)->SetZUpper(rtot.z());
01521       
01522       // zero length components not placed (transform3d)
01523       if(length!=0.){
01524         
01525         G4LogicalVolume* LocalLogVol=(*iBeam)->GetMarkerLogicalVolume();
01526         
01527         G4String LogVolName=LocalLogVol->GetName();
01528         int nCopy=(*LogVolCount)[LogVolName]-1;
01529         (*LogVolCount)[LogVolName]++;
01530 
01531 
01532         // add the wolume to one of the regions
01533         if((*iBeam)->GetType() == _ELEMENT)
01534           {
01535             //G4cout<<"ENCOUNTERED ELEMENT : "<<_ELEMENT<<" ADDING TO PRECISION REg\n";
01536             LocalLogVol->SetRegion(precisionRegion);
01537             precisionRegion->AddRootLogicalVolume(LocalLogVol);
01538           }
01539 
01540         
01541         // set up the sensitive volumes for energy counting:
01542         (*iBeam)->SetCopyNumber(nCopy);
01543         G4LogicalVolume* SensVol=(*iBeam)->GetSensitiveVolume();
01544 
01545         if(SensVol)
01546           {
01547             BDSEnergyCounterSD* ECounter=new BDSEnergyCounterSD(LogVolName);
01548             (*iBeam)->SetBDSEnergyCounter(ECounter);
01549             SensVol->SetSensitiveDetector(ECounter);
01550             SDman->AddNewDetector(ECounter);
01551             theECList->push_back(ECounter);
01552           }
01553 
01554         vector<G4LogicalVolume*> MultipleSensVols = (*iBeam)->GetMultipleSensitiveVolumes();
01555         if((*iBeam)->GetType()!="sampler" && MultipleSensVols.size()>0)
01556            {
01557              for(G4int i=0; i<(G4int)MultipleSensVols.size(); i++)
01558                {
01559                  BDSEnergyCounterSD* ECounter=
01560                    new BDSEnergyCounterSD(LogVolName+BDSGlobals->StringFromInt(i));
01561                  (*iBeam)->SetBDSEnergyCounter(ECounter);
01562                  MultipleSensVols.at(i)->SetSensitiveDetector(ECounter);
01563                  SDman->AddNewDetector(ECounter);
01564                  theECList->push_back(ECounter);             
01565                }
01566            }
01567         
01568         if((*iBeam)->GetType()=="sampler") {
01569           LocalName=(*iBeam)->GetName()+"_phys";
01570           bdsOutput.SampName.push_back(LocalName + "_" + BDSGlobals->StringFromInt(nCopy+1));
01571         } else {
01572           //it would be nice to set correctly names also for other elements...
01573           //but need to count them!
01574           LocalName=(*iBeam)->GetName()+"_phys";
01575         }
01576 
01577         /*
01578         //for torus sbend
01579         if((*iBeam)->GetType() == "sbend") {
01580 
01581           G4double rho = length/fabs(angle);
01582 
01583           G4RotationMatrix* Rot=new G4RotationMatrix();
01584           Rot->rotateX(-pi/2 * rad);
01585           //Rot->rotateZ(pi * rad);
01586           //Rot->rotateZ(- ( pi/2 - fabs(angle)/2 ) * rad);
01587           TargetPos -= zHalfAngle *  ( length/2 + BDSGlobals->GetLengthSafety()/2 ) ;
01588           TargetPos+=G4ThreeVector(-rho,0,0);
01589           //TargetPos=G4ThreeVector(0,0,rho);
01590           //if(angle < 0)
01591           //{
01592           //  Rot->rotateZ(pi);
01593           //  TargetPos=G4ThreeVector(rho,0,0);
01594           //}
01595           rotateComponent=Rot;
01596         }
01597         */
01598 
01599         // Align Component - most cases does nothing. 
01600         // Currently only used for BDSElement   
01601         // For other elements stores global position and rotation,
01602         // needed for BDSOutline
01603         (*iBeam)->AlignComponent(//TargetPos,
01604                                  rlast,
01605                                  rotateComponent,
01606                                  globalRotation,
01607                                  rtot,
01608                                  rlast,
01609                                  localX,
01610                                  localY,
01611                                  localZ);
01612 
01613 
01614         G4PVPlacement* PhysiComponentPlace = 
01615           new G4PVPlacement(
01616                             rotateComponent,  // its rotation
01617                             TargetPos,        // its position
01618                             LocalName,        // its name
01619                             LocalLogVol,      // its logical volume
01620                             physiWorld,       // its mother  volume
01621                             false,            // no boolean operation
01622                             nCopy);           // copy number
01623         
01624         (*iBeam)->PrepareField(PhysiComponentPlace);
01625 
01626         if(use_graphics)
01627           {
01628             (*iBeam)->GetVisAttributes()->SetVisibility(false);
01629             //(*iBeam)->GetVisAttributes()->SetForceSolid(true);
01630             (*iBeam)->GetMarkerLogicalVolume()->
01631               SetVisAttributes((*iBeam)->GetVisAttributes());
01632           }
01633         
01634       }
01635     }
01636 
01637   // construct tunnel
01638   for(it = beamline_list.begin();it!=beamline_list.end();it++)
01639     {
01640       
01641       if((*it).type==_TUNNEL ) {
01642         G4cout<<"BUILDING TUNNEL : "<<(*it).l<<"  "<<(*it).name<<G4endl;
01643         
01644         G4String gFormat="",  gFile="";
01645         G4String geometry = (*it).geometryFile;
01646 
01647         // get geometry format and file
01648         G4int pos = geometry.find(":");
01649         
01650         if(pos<0) { 
01651           G4cerr<<"WARNING: invalid geometry reference format : "<<geometry<<endl;
01652           gFormat="none";
01653         }
01654         
01655         else {
01656           gFormat = geometry.substr(0,pos);
01657           gFile = geometry.substr(pos+1,geometry.length() - pos); 
01658         }
01659         
01660         G4cout<<"placing components\n: geometry format - "<<gFormat<<G4endl<<
01661           "file - "<<gFile<<G4endl;
01662         
01663         GGmadDriver *ggmad;
01664         
01665         if(gFormat=="gmad") {
01666          
01667           ggmad = new GGmadDriver(gFile);
01668           ggmad->Construct(logicWorld);
01669 
01670           
01671         } else  G4cerr<<"Tunnel won't be build! "<<endl;
01672       }
01673       
01674     }
01675   
01676   // free the parser list
01677   beamline_list.clear();
01678 
01679   // theProductionCuts->SetProductionCut(1.e-6*m,"gamma");
01680   // theProductionCuts->SetProductionCut(1.e-6*m,"e+");
01681   // theProductionCuts->SetProductionCut(1.e-6*m,"e-");
01682   // precisionRegion->SetProductionCuts(theProductionCuts);
01683   
01684   if(verbose || DEBUG) G4cout<<"end placement, size="<<theBeamline.size()<<G4endl;
01685   
01686   if(verbose || DEBUG) G4cout<<"Detector Construction done"<<G4endl; 
01687 
01688   if(DEBUG) G4cout << *(G4Material::GetMaterialTable()) << G4endl;
01689 
01690   return physiWorld;
01691 }
01692 
01693   
01694   
01695 //=================================================================
01696 
01697 void BDSDetectorConstruction::SetMagField(const G4double fieldValue)
01698 {
01699  
01700   G4FieldManager* fieldMgr =
01701     G4TransportationManager::GetTransportationManager()->GetFieldManager();
01702   magField = new G4UniformMagField(G4ThreeVector(0.,fieldValue,0.));  
01703   fieldMgr->SetDetectorField(magField);
01704   fieldMgr->CreateChordFinder(magField);
01705 
01706 }
01707 
01708 //=================================================================
01709   
01710 void BDSDetectorConstruction::UpdateGeometry()
01711 {
01712   G4RunManager::GetRunManager()->DefineWorldVolume(ConstructBDS(beamline_list));
01713 }
01714 
01715 //=================================================================
01716 BDSDetectorConstruction::~BDSDetectorConstruction()
01717 { 
01718   LogVolCount->clear();
01719   delete LogVolCount;
01720 
01721   LogVolMap::iterator iter;
01722   for(iter=LogVol->begin();iter!=LogVol->end();iter++){
01723     delete (*iter).second;
01724   }
01725   LogVol->clear();
01726   delete LogVol;
01727 
01728   delete theMaterials;
01729 }
01730 
01731 //=================================================================

Generated on Wed Mar 5 17:25:22 2008 for BDSIM by  doxygen 1.5.3