00001 #include "globals.hh"
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>
00018 #include <vector>
00019
00020 BDSBeamline::BDSBeamline()
00021 {
00022 #ifdef BDSDEBUG
00023 G4cout << __METHOD_NAME__ << G4endl;
00024 #endif
00025
00026 totalChordLength = 0;
00027 totalArcLength = 0;
00028 maximumExtentPositive = G4ThreeVector(0,0,0);
00029 maximumExtentNegative = G4ThreeVector(0,0,0);
00030
00031
00032 previousReferenceRotationEnd = new G4RotationMatrix();
00033
00034
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
00040 previousReferencePositionEnd = G4ThreeVector(0,0,0);
00041
00042
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
00055 totalChordLength = 0;
00056 totalArcLength = 0;
00057 maximumExtentPositive = G4ThreeVector(0,0,0);
00058 maximumExtentNegative = G4ThreeVector(0,0,0);
00059
00060
00061 previousReferenceRotationEnd = initialGlobalRotation;
00062
00063
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
00068
00069
00070 previousReferencePositionEnd = initialGlobalPosition;
00071
00072
00073 previousSPositionEnd = 0;
00074 }
00075
00076 BDSBeamline::~BDSBeamline()
00077 {
00078 BDSBeamlineIterator it = begin();
00079 for (; it != end(); ++it)
00080 {delete (*it);}
00081
00082
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
00124
00125
00126
00127 if (BDSTransform3D* transform = dynamic_cast<BDSTransform3D*>(component))
00128 {ApplyTransform3D(transform); return;}
00129
00130
00131
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
00156
00157
00158
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
00167
00168
00169
00170
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
00186
00187 if (hasFiniteAngle)
00188 {
00189 G4double angle = component->GetAngle();
00190
00191
00192
00193
00194 referenceRotationMiddle->rotate(-angle * 0.5, yARE);
00195
00196 referenceRotationEnd->rotate(-angle, yARE);
00197
00198
00199 xARS = xARE;
00200 yARS = yARE;
00201 zARS = zARE;
00202 yARM = yARM;
00203
00204
00205
00206
00207 xARM.rotate(-angle * 0.5, yARE);
00208 zARM.rotate(-angle * 0.5, yARE);
00209 xARE.rotate(-angle, yARE);
00210 zARE.rotate(-angle, yARE);
00211 }
00212
00213
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
00233
00234
00235 if (!empty())
00236 {previousReferencePositionEnd = beamline.back()->GetReferencePositionEnd();}
00237
00238 G4ThreeVector referencePositionStart, referencePositionMiddle, referencePositionEnd;
00239 if (hasFiniteLength)
00240 {
00241 referencePositionStart = previousReferencePositionEnd;
00242
00243 G4ThreeVector md = G4ThreeVector(0, 0, 0.5 * length).transform(*referenceRotationMiddle);
00244
00245 md.setX(md.x()*-1);
00246 referencePositionMiddle = referencePositionStart + md;
00247
00248
00249 G4ThreeVector delta = G4ThreeVector(0, 0, length).transform(*referenceRotationMiddle);
00250 delta.setX(delta.x()*-1);
00251 referencePositionEnd = referencePositionStart + delta;
00252 }
00253 else
00254 {
00255
00256
00257 referencePositionStart = previousReferencePositionEnd;
00258 referencePositionMiddle = previousReferencePositionEnd;
00259 referencePositionEnd = previousReferencePositionEnd;
00260 }
00261
00262
00263
00264 G4ThreeVector extentpos = referencePositionMiddle + eP.transform(*referenceRotationMiddle);
00265 G4ThreeVector extentneg = referencePositionMiddle + eN.transform(*referenceRotationMiddle);
00266
00267
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
00277 G4ThreeVector positionStart, positionMiddle, positionEnd;
00278 if (hasFiniteOffset)
00279 {
00280 G4double dx = tiltOffset.GetXOffset();
00281 G4double dy = tiltOffset.GetYOffset();
00282
00283
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
00297
00298 if (!empty())
00299 {previousSPositionEnd = beamline.back()->GetSPositionEnd();}
00300
00301 G4double arcLength = component->GetArcLength();
00302 G4double chordLength = component->GetChordLength();
00303
00304
00305 totalChordLength += chordLength;
00306 totalArcLength += arcLength;
00307
00308
00309 G4double sPositionStart, sPositionMiddle, sPositionEnd;
00310 sPositionStart = previousSPositionEnd;
00311 sPositionMiddle = previousSPositionEnd + 0.5 * arcLength;
00312 sPositionEnd = previousSPositionEnd + arcLength;
00313
00314
00315 BDSGlobalConstants::Instance()->SetSMax(sPositionEnd*CLHEP::m);
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
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
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
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
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
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
00401
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
00413
00414 G4ThreeVector delta = G4ThreeVector(dx,dy,dz).transform(*previousReferenceRotationEnd);
00415 previousReferencePositionEnd = previousReferencePositionEnd + G4ThreeVector(dx,dy,dz);
00416
00417
00418 previousReferenceRotationEnd->rotate(dPsi, zARE);
00419 previousReferenceRotationEnd->rotate(dPhi, yARE);
00420 previousReferenceRotationEnd->rotate(dTheta, xARE);
00421
00422
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 }