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

00001 #include "globals.hh" // geant4 globals / types
00002 #include "G4RotationMatrix.hh"
00003 #include "G4ThreeVector.hh"
00004 
00005 #include "BDSDebug.hh"
00006 #include "BDSAcceleratorComponent.hh"
00007 #include "BDSBeamline.hh"
00008 #include "BDSBeamlineElement.hh"
00009 #include "BDSLine.hh"
00010 #include "BDSSampler.hh"
00011 #include "BDSTiltOffset.hh"
00012 #include "BDSTransform3D.hh"
00013 #include "BDSUtilities.hh"
00014 
00015 #include <iterator>
00016 #include <ostream>
00017 #include <utility>  // for std::pair
00018 #include <vector>
00019 
00020 BDSBeamline::BDSBeamline()
00021 {
00022 #ifdef BDSDEBUG
00023   G4cout << __METHOD_NAME__ << G4endl;
00024 #endif
00025   // initialise extents
00026   totalChordLength      = 0;
00027   totalArcLength        = 0;
00028   maximumExtentPositive = G4ThreeVector(0,0,0);
00029   maximumExtentNegative = G4ThreeVector(0,0,0);
00030   
00031   // initial rotation matrix
00032   previousReferenceRotationEnd = new G4RotationMatrix();
00033 
00034   // initial rotation axes
00035   xARS = xARM = xARE = G4ThreeVector(1,0,0);
00036   yARS = yARM = yARE = G4ThreeVector(0,1,0);
00037   zARS = zARM = zARE = G4ThreeVector(0,0,1);
00038 
00039   // initial position
00040   previousReferencePositionEnd = G4ThreeVector(0,0,0);
00041 
00042   // initial s coordinate
00043   previousSPositionEnd = 0; 
00044 }
00045 
00046 BDSBeamline::BDSBeamline(G4ThreeVector     initialGlobalPosition,
00047                          G4RotationMatrix* initialGlobalRotation)
00048 {
00049 #ifdef BDSDEBUG
00050   G4cout << __METHOD_NAME__ << "with initial position and rotation" << G4endl;
00051   G4cout << "Initial position: " << initialGlobalPosition << G4endl;
00052   G4cout << "Initial rotation: " << initialGlobalRotation << G4endl;
00053 #endif
00054   // initialise extents
00055   totalChordLength      = 0;
00056   totalArcLength        = 0;
00057   maximumExtentPositive = G4ThreeVector(0,0,0);
00058   maximumExtentNegative = G4ThreeVector(0,0,0);
00059   
00060   // initial rotation matrix
00061   previousReferenceRotationEnd = initialGlobalRotation;
00062 
00063   // initial rotation axes
00064   xARS = xARM = xARE = G4ThreeVector(1,0,0);
00065   yARS = yARM = yARE = G4ThreeVector(0,1,0);
00066   zARS = zARM = zARE = G4ThreeVector(0,0,1);
00067   // now apply the global rotation supplied to get the initial axes
00068 
00069   // initial position
00070   previousReferencePositionEnd = initialGlobalPosition;
00071 
00072   // initial s coordinate
00073   previousSPositionEnd = 0; 
00074 }
00075 
00076 BDSBeamline::~BDSBeamline()
00077 {
00078   BDSBeamlineIterator it = begin();
00079   for (; it != end(); ++it)
00080     {delete (*it);}
00081 
00082   // and delete the null one at the beginning
00083   delete beamline[0];
00084 }
00085 
00086 void BDSBeamline::PrintAllComponents(std::ostream& out) const
00087 {
00088   BDSBeamlineIterator it = begin();
00089   for (; it != end(); ++it)
00090     {out << *(it);}
00091 }
00092 
00093 std::ostream& operator<< (std::ostream& out, BDSBeamline const &bl)
00094 {
00095   out << "BDSBeamline with " << bl.size() << " elements"<< G4endl
00096       << "Elements are: " << G4endl;
00097   bl.PrintAllComponents(out);
00098   out << G4endl;
00099   out << "Total arc length:   " << bl.totalArcLength   << " mm" << G4endl;
00100   out << "Total chord length: " << bl.totalChordLength << " mm" << G4endl;
00101 
00102   return out;
00103 }
00104 
00105 void BDSBeamline::AddComponent(BDSAcceleratorComponent* component)
00106 {
00107   if (BDSLine* line = dynamic_cast<BDSLine*>(component))
00108     {
00109       for (BDSLine::BDSLineIterator i = line->begin(); i != line->end(); ++i)
00110         {AddSingleComponent(*i);}
00111     }
00112   else
00113     {AddSingleComponent(component);}
00114 }
00115 
00116 void BDSBeamline::AddSingleComponent(BDSAcceleratorComponent* component)
00117 {
00118 #ifdef BDSDEBUG
00119   G4cout << G4endl << __METHOD_NAME__ << "adding component to beamline and calculating coordinates" << G4endl;
00120   G4cout << "component name:      " << component->GetName() << G4endl;
00121 #endif
00122   
00123   // Test if it's a BDSTransform3D instance - this is a unique component that requires
00124   // rotation in all dimensions and can skip normal addition as isn't a real volume
00125   // that can be placed.  Apply the transform and skip the rest of this function by returning
00126   // This modifies the "end" coordinates, rotation and axes of the last element in the beamline
00127   if (BDSTransform3D* transform = dynamic_cast<BDSTransform3D*>(component))
00128     {ApplyTransform3D(transform); return;}
00129 
00130   // if it's not a transform3d instance, continue as normal
00131   // interrogate the item
00132   G4double      length     = component->GetChordLength();
00133   G4double      angle      = component->GetAngle();
00134   BDSTiltOffset tiltOffset = component->GetTiltOffset();
00135   G4bool hasFiniteLength   = BDS::IsFinite(length);
00136   G4bool hasFiniteAngle    = BDS::IsFinite(angle);
00137   G4bool hasFiniteTilt     = BDS::IsFinite(tiltOffset.GetTilt());
00138   G4bool hasFiniteOffset   = BDS::IsFinite(tiltOffset.GetXOffset()) || BDS::IsFinite(tiltOffset.GetYOffset());
00139 
00140   G4ThreeVector eP = component->GetExtentPositive();
00141   G4ThreeVector eN = component->GetExtentNegative();
00142   
00143 #ifdef BDSDEBUG
00144   G4cout << "chord length         " << length     << " mm"         << G4endl;
00145   G4cout << "angle                " << angle      << " rad"        << G4endl;
00146   G4cout << "tilt offsetX offsetY " << tiltOffset << " rad mm mm " << G4endl;
00147   G4cout << "has finite length    " << hasFiniteLength             << G4endl;
00148   G4cout << "has finite angle     " << hasFiniteAngle              << G4endl;
00149   G4cout << "has finite tilt      " << hasFiniteTilt               << G4endl;
00150   G4cout << "has finite offset    " << hasFiniteOffset             << G4endl;
00151   G4cout << "extent positive      " << eP                          << G4endl;
00152   G4cout << "extent negative      " << eN                          << G4endl;
00153 #endif
00154   
00155   // Calculate the reference placement rotation
00156   // rotations are done first as they're required to transform the spatial displacements.
00157   // if not the first element in the beamline, copy the rotation matrix (cumulative along line)
00158   // from end of last component
00159   if (!empty())
00160     {previousReferenceRotationEnd = beamline.back()->GetReferenceRotationEnd();}
00161   
00162   G4RotationMatrix* referenceRotationStart  = new G4RotationMatrix(*previousReferenceRotationEnd);
00163   G4RotationMatrix* referenceRotationMiddle = new G4RotationMatrix(*referenceRotationStart);
00164   G4RotationMatrix* referenceRotationEnd    = new G4RotationMatrix(*referenceRotationStart);
00165 
00166   // get the axes to rotate about - note if we only worked where component angles worked in the
00167   // x,y,z global axes, this would be unnecessary. However, with the ability to use Transform3D
00168   // we can possibly rotate the beamline permenantly and therefore must keep the axes we rotate about
00169   // rather than use the rotateX or rotateY functions for example, we must use rotate(angle,axis)
00170   // if it isn't the first item, get the rotation axes from the last element and assign to local copy
00171   if (!empty())
00172     {
00173       BDSBeamlineElement* last = beamline.back();
00174       xARS = last->GetXAxisReferenceStart();
00175       yARS = last->GetYAxisReferenceStart();
00176       zARS = last->GetZAxisReferenceStart();
00177       xARM = last->GetXAxisReferenceMiddle();
00178       yARM = last->GetYAxisReferenceMiddle();
00179       zARM = last->GetZAxisReferenceMiddle();
00180       xARE = last->GetXAxisReferenceEnd();
00181       yARE = last->GetYAxisReferenceEnd();
00182       zARE = last->GetZAxisReferenceEnd();
00183     }
00184   
00185   // if the component induces an angle in the reference trajectory, rotate the mid and end point
00186   // rotation matrices appropriately
00187   if (hasFiniteAngle)
00188     {
00189       G4double angle = component->GetAngle();
00190       // remember our definition of angle - +ve angle bends in -ve x direction in right
00191       // handed coordinate system
00192       // rotate about cumulative local y axis of beamline
00193       // middle rotated by half angle in local x,z plane
00194       referenceRotationMiddle->rotate(-angle * 0.5, yARE);
00195       // end rotated by full angle in local x,z plane
00196       referenceRotationEnd->rotate(-angle, yARE);
00197 
00198       // copy unaffected axes to update for next element
00199       xARS = xARE;
00200       yARS = yARE;
00201       zARS = zARE;
00202       yARM = yARM;
00203       //yARE = yARE; // truly stays the same
00204       
00205       // now apply the change in pointing vector the cumulative axes
00206       // y axis will stay the same as angle only affects direction in x,z plane
00207       xARM.rotate(-angle * 0.5, yARE); // middle by half angle
00208       zARM.rotate(-angle * 0.5, yARE);
00209       xARE.rotate(-angle,       yARE); // end by full angle
00210       zARE.rotate(-angle,       yARE);
00211     }
00212 
00213   // add the tilt to the rotation matrices (around z axis)
00214   G4RotationMatrix* rotationStart, *rotationMiddle, *rotationEnd;
00215   if (hasFiniteTilt)
00216     {
00217       G4double tilt = tiltOffset.GetTilt();
00218       rotationStart  = new G4RotationMatrix(*referenceRotationStart);
00219       rotationMiddle = new G4RotationMatrix(*referenceRotationMiddle);
00220       rotationEnd    = new G4RotationMatrix(*referenceRotationEnd);
00221       rotationStart ->rotate(tilt, zARS);
00222       rotationMiddle->rotate(tilt, zARM);
00223       rotationEnd   ->rotate(tilt, zARE);
00224     }
00225   else
00226     {
00227       rotationStart  = new G4RotationMatrix(*referenceRotationStart);
00228       rotationMiddle = new G4RotationMatrix(*referenceRotationMiddle);
00229       rotationEnd    = new G4RotationMatrix(*referenceRotationEnd);
00230     }
00231   
00232   // calculate the reference placement position
00233   // if not the first item in the beamline, get the reference trajectory global position
00234   // at the end of the previous element
00235   if (!empty())
00236     {previousReferencePositionEnd = beamline.back()->GetReferencePositionEnd();}
00237   
00238   G4ThreeVector referencePositionStart, referencePositionMiddle, referencePositionEnd;
00239   if (hasFiniteLength)
00240     {
00241       referencePositionStart  = previousReferencePositionEnd;
00242       // calculate delta to mid point
00243       G4ThreeVector md = G4ThreeVector(0, 0, 0.5 * length).transform(*referenceRotationMiddle);
00244       // flip x coordinate only due our definition of angle
00245       md.setX(md.x()*-1);
00246       referencePositionMiddle = referencePositionStart + md;
00247       // remember the end position is the chord length along the half angle, not the full angle
00248       // the particle achieves the full angle though by the end position.
00249       G4ThreeVector delta = G4ThreeVector(0, 0, length).transform(*referenceRotationMiddle);
00250       delta.setX(delta.x()*-1);
00251       referencePositionEnd = referencePositionStart + delta;
00252     }
00253   else
00254     {
00255       // element has no finite size so all positions are previous end position
00256       // likely this is a transform3d or similar - but not hard coded just for transform3d
00257       referencePositionStart  = previousReferencePositionEnd;
00258       referencePositionMiddle = previousReferencePositionEnd;
00259       referencePositionEnd    = previousReferencePositionEnd;
00260     }
00261 
00262   // calculate extents for world size determination
00263   // project size in global coordinates
00264   G4ThreeVector extentpos = referencePositionMiddle + eP.transform(*referenceRotationMiddle); 
00265   G4ThreeVector extentneg = referencePositionMiddle + eN.transform(*referenceRotationMiddle);
00266   // note extentneg is +eN.transform.. as eN is negative naturally
00267   // loop over each size and compare to cumulative extent
00268   for (int i=0; i<3; i++)
00269     {
00270       if (extentpos[i] > maximumExtentPositive[i])
00271         {maximumExtentPositive[i] = extentpos[i];}
00272       if (extentneg[i] < maximumExtentNegative[i])
00273         {maximumExtentNegative[i] = extentneg[i];}
00274     }
00275   
00276   // add the placement offset
00277   G4ThreeVector positionStart, positionMiddle, positionEnd;
00278   if (hasFiniteOffset)
00279     {
00280       G4double dx                  = tiltOffset.GetXOffset();
00281       G4double dy                  = tiltOffset.GetYOffset();
00282       // note the displacement is applied in the accelerator x and y frame so use
00283       // the reference rotation rather than the one with tilt already applied
00284       G4ThreeVector displacement   = G4ThreeVector(dx,dy,0).transform(*referenceRotationMiddle);
00285       positionStart  = referencePositionStart  + displacement;
00286       positionMiddle = referencePositionMiddle + displacement;
00287       positionEnd    = referencePositionEnd    + displacement;
00288     }
00289   else
00290     {
00291       positionStart  = referencePositionStart;
00292       positionMiddle = referencePositionMiddle;
00293       positionEnd    = referencePositionEnd;
00294     }
00295   
00296   // calculate the s position
00297   // if not the first element in the beamline, get the s position at the end of the previous element
00298   if (!empty())
00299     {previousSPositionEnd = beamline.back()->GetSPositionEnd();}
00300   
00301   G4double arcLength   = component->GetArcLength();
00302   G4double chordLength = component->GetChordLength();
00303 
00304   // integrate lengths
00305   totalChordLength += chordLength;
00306   totalArcLength   += arcLength;
00307 
00308   // advance s coordinate
00309   G4double sPositionStart, sPositionMiddle, sPositionEnd;
00310   sPositionStart  = previousSPositionEnd;
00311   sPositionMiddle = previousSPositionEnd + 0.5 * arcLength;
00312   sPositionEnd    = previousSPositionEnd + arcLength;
00313 
00314   // update the global constants
00315   BDSGlobalConstants::Instance()->SetSMax(sPositionEnd*CLHEP::m);
00316   
00317   /*
00318 #ifdef BDSDEBUG
00319   // feedback about calculated coordinates
00320   G4cout << "calculated coordinates in mm and rad are " << G4endl;
00321   G4cout << "reference position start:  " << referencePositionStart   << G4endl;
00322   G4cout << "reference position middle: " << referencePositionMiddle  << G4endl;
00323   G4cout << "reference position end:    " << referencePositionEnd     << G4endl;
00324   G4cout << "reference rotation start:  " << *referenceRotationStart;
00325   G4cout << "reference rotation middle: " << *referenceRotationMiddle;
00326   G4cout << "reference rotation end:    " << *referenceRotationEnd;
00327   G4cout << "position start:            " << positionStart            << G4endl;
00328   G4cout << "position middle:           " << positionMiddle           << G4endl;
00329   G4cout << "position end:              " << positionEnd              << G4endl;
00330   G4cout << "rotation start:            " << *rotationStart;
00331   G4cout << "rotation middle:           " << *rotationMiddle;
00332   G4cout << "rotation end:              " << *rotationEnd;
00333 #endif
00334   */
00335   // construct beamline element
00336   BDSBeamlineElement* element = new BDSBeamlineElement(component,
00337                                                        positionStart,
00338                                                        positionMiddle,
00339                                                        positionEnd,
00340                                                        rotationStart,
00341                                                        rotationMiddle,
00342                                                        rotationEnd,
00343                                                        referencePositionStart,
00344                                                        referencePositionMiddle,
00345                                                        referencePositionEnd,
00346                                                        referenceRotationStart,
00347                                                        referenceRotationMiddle,
00348                                                        referenceRotationEnd,
00349                                                        sPositionStart,
00350                                                        sPositionMiddle,
00351                                                        sPositionEnd,
00352                                                        xARS,
00353                                                        yARS,
00354                                                        zARS,
00355                                                        xARM,
00356                                                        yARM,
00357                                                        zARM,
00358                                                        xARE,
00359                                                        yARE,
00360                                                        zARE);
00361   
00362   // append it to the beam line
00363   beamline.push_back(element);
00364 #ifdef BDSDEBUG
00365   G4cout << *element;
00366   G4cout << __METHOD_NAME__ << "component added" << G4endl;
00367 #endif
00368 }
00369 
00370 void BDSBeamline::ApplyTransform3D(BDSTransform3D* component)
00371 {
00372 #ifdef BDSDEBUG
00373   G4cout << __METHOD_NAME__ << "- as it's a transform3d instance" << G4endl;
00374 #endif
00375   // interrogate component
00376   G4double dx     = component->GetDX();
00377   G4double dy     = component->GetDY();
00378   G4double dz     = component->GetDZ();
00379   G4double dTheta = component->GetDTheta();
00380   G4double dPsi   = component->GetDPsi();
00381   G4double dPhi   = component->GetDPhi();
00382   
00383   // debug feedback
00384 #ifdef BDSDEBUG
00385   G4cout << "dx     " << dx     << G4endl;
00386   G4cout << "dy     " << dy     << G4endl;
00387   G4cout << "dz     " << dz     << G4endl;
00388   G4cout << "dTheta " << dTheta << G4endl;
00389   G4cout << "dPsi   " << dPsi   << G4endl;
00390   G4cout << "dPhi   " << dPhi   << G4endl;
00391 #endif
00392 
00393   // test validity for overlaps
00394   if (dz < 0)
00395     {
00396       G4cerr << __METHOD_NAME__ << "Problemm with Transform3d: " << component->GetName() << G4endl;
00397       G4cerr << __METHOD_NAME__ << "dz = " << dz << " < 0 -> will overlap previous element" << G4endl;
00398     } 
00399 
00400   // if not the first element in the beamline, get information from the end of the
00401   // last element in the beamline
00402   if (!empty())
00403     {
00404       BDSBeamlineElement* last = back();
00405       previousReferenceRotationEnd = last->GetReferenceRotationEnd();
00406       previousReferencePositionEnd = last->GetReferencePositionEnd();
00407       xARE = last->GetXAxisReferenceEnd();
00408       yARE = last->GetYAxisReferenceEnd();
00409       zARE = last->GetZAxisReferenceEnd();
00410     }
00411 
00412   // apply position
00413   // transform the local dx,dy,dz displacement into the global frame then apply
00414   G4ThreeVector delta = G4ThreeVector(dx,dy,dz).transform(*previousReferenceRotationEnd);
00415   previousReferencePositionEnd = previousReferencePositionEnd + G4ThreeVector(dx,dy,dz);
00416   
00417   // apply rotation
00418   previousReferenceRotationEnd->rotate(dPsi,   zARE);
00419   previousReferenceRotationEnd->rotate(dPhi,   yARE);
00420   previousReferenceRotationEnd->rotate(dTheta, xARE);
00421   
00422   // apply rotation to axes of rotation
00423   xARE.rotate(dPsi,   zARE);
00424   yARE.rotate(dPsi,   zARE);
00425   xARE.rotate(dPhi,   yARE);
00426   zARE.rotate(dPhi,   yARE);
00427   yARE.rotate(dTheta, xARE);
00428   zARE.rotate(dTheta, xARE);
00429 }
00430 
00431 G4ThreeVector BDSBeamline::GetMaximumExtentAbsolute() const
00432 {
00433   G4ThreeVector mEA;
00434   for (int i=0; i<3; i++)
00435     {
00436       mEA[i] = std::max(std::abs(maximumExtentPositive[i]), std::abs(maximumExtentNegative[i]));
00437     }
00438   return mEA;
00439 }

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7