00001 #include "BDSBunchInterface.hh"
00002
00003 #include "BDSDebug.hh"
00004
00005 #include "CLHEP/Matrix/Vector.h"
00006 #include "CLHEP/Matrix/SymMatrix.h"
00007 #include "CLHEP/RandomObjects/RandMultiGauss.h"
00008
00010 namespace {
00012 bool isPositiveDefinite(CLHEP::HepSymMatrix& S)
00013 {
00014 CLHEP::HepSymMatrix temp (S);
00015
00016 CLHEP::HepMatrix U = diagonalize ( &temp );
00017 CLHEP::HepSymMatrix D = S.similarityT(U);
00018 for (int i = 1; i <= S.num_row(); i++) {
00019 double s2 = D(i,i);
00020 if ( s2 <= 0 ) {
00021 return false;
00022 }
00023 }
00024 return true;
00025 }
00026 }
00027
00028 BDSBunchInterface::BDSBunchInterface() :
00029 X0(0.0), Y0(0.0), Z0(0.0), T0(0.0),
00030 Xp0(0.0), Yp0(0.0), Zp0(0.0), sigmaT(0.0), sigmaE(0.0)
00031 {}
00032
00033 BDSBunchInterface::BDSBunchInterface(G4double sigmaTIn, G4double sigmaEIn) :
00034 X0(0.0), Y0(0.0), Z0(0.0), T0(0.0), Xp0(0.0), Yp0(0.0), Zp0(0.0), sigmaT(sigmaTIn), sigmaE(sigmaEIn) {
00035
00036 }
00037
00038 BDSBunchInterface::BDSBunchInterface(G4double X0In, G4double Y0In, G4double Z0In, G4double T0In,
00039 G4double Xp0In, G4double Yp0In, G4double Zp0In,
00040 G4double sigmaTIn, G4double sigmaEIn) :
00041 X0(X0In), Y0(Y0In), Z0(Z0In), T0(T0In),
00042 Xp0(Xp0In), Yp0(Yp0In), Zp0(Zp0In), sigmaT(sigmaTIn), sigmaE(sigmaEIn)
00043 {}
00044
00045 BDSBunchInterface::~BDSBunchInterface() {
00046 }
00047
00048 void BDSBunchInterface::SetOptions(struct Options& opt) {
00049 X0 = opt.X0;
00050 Y0 = opt.Y0;
00051 Z0 = opt.Z0;
00052 T0 = opt.T0;
00053 Xp0 = opt.Xp0;
00054 Yp0 = opt.Yp0;
00055 sigmaE = opt.sigmaE;
00056 sigmaT = opt.sigmaT;
00057
00058 Zp0 = CalculateZp(Xp0,Yp0,opt.Zp0);
00059 }
00060
00061 void BDSBunchInterface::GetNextParticle(G4double& x0, G4double& y0, G4double& z0,
00062 G4double& xp, G4double& yp, G4double& zp,
00063 G4double& t , G4double& E, G4double& weight) {
00064 x0 = (X0 + 0.0) * CLHEP::m;
00065 y0 = (Y0 + 0.0) * CLHEP::m;
00066 z0 = (Z0 + 0.0) * CLHEP::m;
00067 xp = (Xp0 + 0.0)* CLHEP::rad;
00068 yp = (Yp0 + 0.0)* CLHEP::rad;
00069 zp = CalculateZp(xp,yp,Zp0);
00070 t = 0.0;
00071 E = BDSGlobalConstants::Instance()->GetParticleKineticEnergy();
00072 weight = 1.0;
00073 return;
00074 }
00075
00076 CLHEP::RandMultiGauss* BDSBunchInterface::CreateMultiGauss(CLHEP::HepRandomEngine & anEngine, const CLHEP::HepVector & mu, CLHEP::HepSymMatrix & sigma) {
00079
00080 if (!isPositiveDefinite(sigma)) {
00081 G4cout << __METHOD_NAME__ << "WARNING bunch generator sigma matrix is not positive definite" << G4endl;
00082 G4cout << sigma << G4endl;
00083 G4cout << __METHOD_NAME__ << "adding a small error to zero diagonal elements" << G4endl;
00084
00085 double small_error = 1e-20;
00086
00087 for (int i=0; i<6; i++) {
00088 if (sigma[i][i]==0) {
00089 sigma[i][i] += small_error;
00090 }
00091 }
00092
00093 if (!isPositiveDefinite(sigma)) {
00094 G4cout << __METHOD_NAME__ << "WARNING bunch generator sigma matrix is still not positive definite" << G4endl;
00095 G4cout << sigma << G4endl;
00096 G4cout << __METHOD_NAME__ << "adding a small error to all elements" << G4endl;
00097 for (int i=0; i<6; i++) {
00098 for (int j=0; j<6; j++) {
00099 if (sigma[i][j]==0) {
00100 sigma[i][j] += small_error;
00101 }
00102 }
00103 }
00104 if (!isPositiveDefinite(sigma)) {
00105 G4cout << __METHOD_NAME__ << "ERROR bunch generator sigma matrix is still not positive definite, giving up" << G4endl;
00106 G4cout << sigma << G4endl;
00107 exit(1);
00108 }
00109 }
00110 }
00111
00112 return new CLHEP::RandMultiGauss(anEngine,mu,sigma);
00113 }
00114
00115 G4double BDSBunchInterface::CalculateZp(G4double xp, G4double yp, G4double Zp0)const
00116 {
00117 double zp;
00118 if (xp*xp+yp*yp > 1) {
00119 G4cout << __METHOD_NAME__ << "ERROR xp, yp too large, xp: " << xp << " yp: " << yp << G4endl;
00120 exit(1);
00121 }
00122 if (Zp0<0)
00123 zp = -sqrt(1.-xp*xp -yp*yp);
00124 else
00125 zp = sqrt(1.-xp*xp -yp*yp);
00126
00127 return zp;
00128 }