Exemplo n.º 1
0
void KVFlowTensor::Calculate()
{
    // Calculate eigenvalues & eigenvectors of tensor

    TMatrixT<double> evectors = fTensor.EigenVectors(fEVal);

    for (int i = 0; i < 3; i++) {
        TVectorD col = TMatrixDColumn(evectors, i);
        fEVec[i].SetXYZ(col[0], col[1], col[2]);
    }

    // check orientation of flow axis
    // by symmetry/convention, we allow FlowAngle between 0 & 90° i.e. flow vector always
    // points in the forward beam direction.
    if (fEVec[0].Theta() > TMath::PiOver2()) {
        fEVec[0] = -fEVec[0];
    }

    // check we have an orthonormal basis
    // we choose evec[0]=>'z' evec[1]=>'y' evec[2]=>'x'
    // therefore we should have evec[2].Cross(evec[1])=evec[0]
    // if not we change the sign of evec[2]
    if (fEVec[2].Cross(fEVec[1]) != fEVec[0]) fEVec[2] = -fEVec[2];

    // set up azimuthal rotation of CM axes around beam axis in order to put new 'X'-axis in reaction plane
    // we use the phi of the major axis (largest eigenvector)
    fAziReacPlane.SetToIdentity();
    fAziReacPlane.RotateZ(e(1).Phi());

    fFlowReacPlane.SetToIdentity();
    fFlowReacPlane.RotateY(e(1).Theta());
    fFlowReacPlane.RotateZ(e(1).Phi());

    // calculate Gutbrod squeeze angle (PRC42(1990)640
    // defined as the angle by which the middle eigenvector e2
    // needs to be rotated around the e1 flow axis
    // in order to be brought in to the reaction plane
    TVector3 normReac = e(1).Cross(TVector3(0, 0, 1)); //normal to reaction plane: e1 x z
    Double_t angle = TMath::RadToDeg() * e(2).Angle(normReac);
    // on the contrary to Gutbrod et al, we define this angle between 0 and 90 degrees.
    // see Fig. 3 of paper: only 0-90 angles can be defined
    fSqueezeAngle = (angle < 90 ? 90 - angle : angle - 90);

    // now calculate the in-plane and out-of-plane flow according to Fig. 5 of Gutbrod et al
    Double_t a = pow(f(2), 0.5); //semi-axes of ellipsoid given by square roots of eigenvalues
    Double_t b = pow(f(3), 0.5);
    Double_t tan_t = -a / b * TMath::Tan(fSqueezeAngle * TMath::DegToRad());
    Double_t t0 = TMath::ATan(tan_t);
    Double_t inPlane = a * cos(t0) * cos(fSqueezeAngle * TMath::DegToRad()) - b * sin(t0) * sin(fSqueezeAngle * TMath::DegToRad());
    tan_t = a / (b * tan(fSqueezeAngle * TMath::DegToRad()));
    t0 = atan(tan_t);
    Double_t outOfPlane = a * cos(t0) * sin(fSqueezeAngle * TMath::DegToRad()) + b * sin(t0) * cos(fSqueezeAngle * TMath::DegToRad());
    if (inPlane <= 0.) fSqOutRatio = -1.;
    else fSqOutRatio = TMath::Min(1.e+03, outOfPlane / inPlane);

    fCalculated = kTRUE;
}
Exemplo n.º 2
0
void solveLinear(Double_t eps = 1.e-12)
{
   cout << "Perform the fit  y = c0 + c1 * x in four different ways" << endl;

   const Int_t nrVar  = 2;
   const Int_t nrPnts = 4;

   Double_t ax[] = {0.0,1.0,2.0,3.0};
   Double_t ay[] = {1.4,1.5,3.7,4.1};
   Double_t ae[] = {0.5,0.2,1.0,0.5};

   // Make the vectors 'Use" the data : they are not copied, the vector data
   // pointer is just set appropriately

   TVectorD x; x.Use(nrPnts,ax);
   TVectorD y; y.Use(nrPnts,ay);
   TVectorD e; e.Use(nrPnts,ae);

   TMatrixD A(nrPnts,nrVar);
   TMatrixDColumn(A,0) = 1.0;
   TMatrixDColumn(A,1) = x;

   cout << " - 1. solve through Normal Equations" << endl;

   const TVectorD c_norm = NormalEqn(A,y,e);

   cout << " - 2. solve through SVD" << endl;
   // numerically  preferred method

   // first bring the weights in place
   TMatrixD Aw = A;
   TVectorD yw = y;
   for (Int_t irow = 0; irow < A.GetNrows(); irow++) {
      TMatrixDRow(Aw,irow) *= 1/e(irow);
      yw(irow) /= e(irow);
   }

   TDecompSVD svd(Aw);
   Bool_t ok;
   const TVectorD c_svd = svd.Solve(yw,ok);

   cout << " - 3. solve with pseudo inverse" << endl;

   const TMatrixD pseudo1  = svd.Invert();
   TVectorD c_pseudo1 = yw;
   c_pseudo1 *= pseudo1;

   cout << " - 4. solve with pseudo inverse, calculated brute force" << endl;

   TMatrixDSym AtA(TMatrixDSym::kAtA,Aw);
   const TMatrixD pseudo2 = AtA.Invert() * Aw.T();
   TVectorD c_pseudo2 = yw;
   c_pseudo2 *= pseudo2;

   cout << " - 5. Minuit through TGraph" << endl;

   TGraphErrors *gr = new TGraphErrors(nrPnts,ax,ay,0,ae);
   TF1 *f1 = new TF1("f1","pol1",0,5);
   gr->Fit("f1","Q");
   TVectorD c_graph(nrVar);
   c_graph(0) = f1->GetParameter(0);
   c_graph(1) = f1->GetParameter(1);

   // Check that all 4 answers are identical within a certain
   // tolerance . The 1e-12 is somewhat arbitrary . It turns out that
   // the TGraph fit is different by a few times 1e-13.

   Bool_t same = kTRUE;
   same &= VerifyVectorIdentity(c_norm,c_svd,0,eps);
   same &= VerifyVectorIdentity(c_norm,c_pseudo1,0,eps);
   same &= VerifyVectorIdentity(c_norm,c_pseudo2,0,eps);
   same &= VerifyVectorIdentity(c_norm,c_graph,0,eps);
   if (same)
      cout << " All solutions are the same within tolerance of " << eps << endl;
   else
      cout << " Some solutions differ more than the allowed tolerance of " << eps << endl;
}