#include "AliParamSolver.h" #include "AliSymMatrix.h" #include "AliLog.h" #include ClassImp(AliParamSolver) //______________________________________________________________________________________ AliParamSolver::AliParamSolver() : fMatrix(0),fSolGlo(0),fSolLoc(0),fMaxGlobal(0),fNGlobal(0),fNPoints(0),fMaxPoints(0), fRHSGlo(0),fRHSLoc(0),fMatGamma(0),fMatG(0),fCovDGl(0) { // default constructor } //______________________________________________________________________________________ AliParamSolver::AliParamSolver(Int_t maxglo,Int_t locbuff) : fMatrix(0),fSolGlo(0),fSolLoc(0),fMaxGlobal(maxglo),fNGlobal(maxglo),fNPoints(0),fMaxPoints(0), fRHSGlo(0),fRHSLoc(0),fMatGamma(0),fMatG(0),fCovDGl(0) { // constructor for nglo globals Init(locbuff); } //______________________________________________________________________________________ AliParamSolver::AliParamSolver(AliParamSolver& src) : TObject(src),fMatrix(0),fSolGlo(0),fSolLoc(0),fMaxGlobal(src.fMaxGlobal),fNGlobal(src.fNGlobal), fNPoints(0),fMaxPoints(0),fRHSGlo(0),fRHSLoc(0),fMatGamma(0),fMatG(0),fCovDGl(0) { // copy constructor if (src.fMatrix) { Init(src.fMaxPoints); (*this) = src; } } //______________________________________________________________________________________ AliParamSolver& AliParamSolver::operator=(const AliParamSolver& src) { // assignment operator if (this==&src) return *this; TObject::operator=(src); if (src.fMatrix && (fNGlobal!=src.fNGlobal || fMaxPointsSolveChol(fRHSGlo, fSolGlo, obtainCov)) { AliError("Solution Failed"); return kFALSE; } SetBit(kBitGloSol); if (obtainCov) SetBit(kBitCInv); } return kTRUE; } //______________________________________________________________________________________ Bool_t AliParamSolver::SolveLocals() { const double kTiny = 1e-16; if (TestBit(kBitLocSol)) return kTRUE; if (!TestBit(kBitGloSol)) { AliError("Cannot solve for Locals before SolveGlobals is called"); return kFALSE; } for (int i=fNPoints;i--;) { if (TMath::Abs(fMatGamma[i])InvertChol()) { SetBit(kBitCInv); return fMatrix; } return 0; } //______________________________________________________________________________________ Bool_t AliParamSolver::Solve(Bool_t obtainCov) { return (SolveGlobals(obtainCov) && SolveLocals()) ? kTRUE : kFALSE; } //______________________________________________________________________________________ void AliParamSolver::AddEquation(const Double_t* dGl,const Double_t *dLc,const Double_t *res, const Double_t *covI,Double_t sclErrI) { // add the measured point to chi2 normal equations // Input: // dGl : NGlo x 3 matrix of derivative for each of the 3 coordinates vs global params // dLc : 3-vector of derivative for each coordinate vs local param // res : residual of the point (extrapolated - measured) // covI: 3 x (3+1)/2 matrix of the (inverted) errors (symmetric) // sclErrI: scaling coefficient to apply to inverted errors (used if >0) // The contribution of the point to chi2 is V * covI * V // with component of the vector V(i) = dGl[i]*glob + dLc[i]*loc - res[i] // // Instead of the NGlo + NMeasPoints size matrix we create only NGlo size matrix using the // reduction a la millepede : http://www.desy.de/~blobel/millepede1.ps const double kTiny = 1e-16; // if (fNPoints+1 == fMaxPoints) ExpandStorage((fNPoints+1)*2); ResetBit(kBitGloSol|kBitLocSol); // if (TestBit(kBitCInv)) { // solution was obtained and the matrix was inverted for previous points fMatrix->InvertChol(); ResetBit(kBitCInv); } // double *mtG = fMatG + fNPoints*fNGlobal; // G_i double &beta = fRHSLoc[fNPoints]; double &gamma = fMatGamma[fNPoints]; double cDl[3]; // // cov * dR/dloc cDl[kX] = covI[kXX]*dLc[kX] + covI[kXY]*dLc[kY] + covI[kXZ]*dLc[kZ]; cDl[kY] = covI[kXY]*dLc[kX] + covI[kYY]*dLc[kY] + covI[kYZ]*dLc[kZ]; cDl[kZ] = covI[kXZ]*dLc[kX] + covI[kYZ]*dLc[kY] + covI[kZZ]*dLc[kZ]; if (sclErrI>0) { cDl[kX] *= sclErrI; cDl[kY] *= sclErrI; cDl[kZ] *= sclErrI;} // for (int i=fNGlobal;i--;) { const double *dGli = dGl+i*3; // derivatives of XYZ vs i-th global param double *cDgi = fCovDGl+i*3; // cov * dR/dGl_i cDgi[kX] = covI[kXX]*dGli[kX] + covI[kXY]*dGli[kY] + covI[kXZ]*dGli[kZ]; cDgi[kY] = covI[kXY]*dGli[kX] + covI[kYY]*dGli[kY] + covI[kYZ]*dGli[kZ]; cDgi[kZ] = covI[kXZ]*dGli[kX] + covI[kYZ]*dGli[kY] + covI[kZZ]*dGli[kZ]; if (sclErrI>0) { cDgi[kX] *= sclErrI; cDgi[kY] *= sclErrI; cDgi[kZ] *= sclErrI;} // mtG[i] = cDl[kX]*dGli[kX] + cDl[kY]*dGli[kY] + cDl[kZ]*dGli[kZ]; // dR/dGl_i * cov * dR/dLoc } beta = res[kX]*cDl[kX] + res[kY]*cDl[kY] + res[kZ]*cDl[kZ]; //RHS: res*cov*dR/dloc gamma = dLc[kX]*cDl[kX] + dLc[kY]*cDl[kY] + dLc[kZ]*cDl[kZ]; //RHS: dR/dloc*cov*dR/dloc double locSol = TMath::Abs(gamma)kTiny) add -= mtG[i]*mtG[j]/gamma; // - [G gamma^-1 T(G) ]_ij matC(i,j) += add; } } // fNPoints++; // } //______________________________________________________________________________________ void AliParamSolver::AddConstraint(Int_t parID, Double_t val, Double_t err2inv) { // add gassian constriant to parameter parID if (parID>=fNGlobal) { AliError(Form("Attempt to constraint non-existing parameter %d",parID)); return; } // (*fMatrix)(parID,parID) += err2inv; fRHSGlo[parID] += val*err2inv; // } //______________________________________________________________________________________ void AliParamSolver::Init(Int_t npini) { // create storage assuming maximum npini measured points fMatrix = new AliSymMatrix(fMaxGlobal); fSolGlo = new Double_t[fMaxGlobal]; fRHSGlo = new Double_t[fMaxGlobal]; // fCovDGl = new Double_t[3*fMaxGlobal]; ExpandStorage(npini); fMatrix->SetSizeUsed(fNGlobal); // } //______________________________________________________________________________________ void AliParamSolver::ExpandStorage(Int_t newSize) { // increase space to newSize measured points newSize = newSize>fMaxPoints ? newSize : fMaxPoints+1; double* tmp; tmp = new Double_t[newSize]; if (fSolLoc) delete[] fSolLoc; fSolLoc = tmp; // tmp = new Double_t[newSize]; if (fMatGamma) { memcpy(tmp,fMatGamma,fNPoints*sizeof(Double_t)); delete[] fMatGamma; } fMatGamma = tmp; // tmp = new Double_t[newSize]; if (fRHSLoc) { memcpy(tmp,fRHSLoc,fNPoints*sizeof(Double_t)); delete[] fRHSLoc; } fRHSLoc = tmp; // tmp = new Double_t[newSize*fMaxGlobal]; if (fMatG) { memcpy(tmp,fMatG,fNPoints*fMaxGlobal*sizeof(Double_t)); delete[] fMatG; } fMatG = tmp; // fMaxPoints = newSize; // } //______________________________________________________________________________________ void AliParamSolver::Clear(Option_t*) { fNPoints = 0; fMatrix->Reset(); for (int i=fNGlobal;i--;) fRHSGlo[i] = 0; ResetBit(kBitGloSol | kBitLocSol | kBitCInv); } //______________________________________________________________________________________ void AliParamSolver::Print(Option_t*) const { AliInfo(Form("Solver with %d globals for %d points",fNGlobal,fNPoints)); } //______________________________________________________________________________________ void AliParamSolver::SetNGlobal(Int_t n) { if (n>fMaxGlobal) { AliError(Form("Maximum number of globals was set to %d",fMaxGlobal)); return; } fNGlobal = n; fMatrix->SetSizeUsed(fNGlobal); } //______________________________________________________________________________________ void AliParamSolver::SetMaxGlobal(Int_t n) { if (n>0 && n==fMaxGlobal) return; fMaxGlobal = n; fNGlobal = n; if (fMatrix) delete fMatrix; fMatrix = 0; if (fSolGlo) delete[] fSolGlo; fSolGlo = 0; if (fSolLoc) delete[] fSolLoc; fSolLoc = 0; if (fRHSGlo) delete[] fRHSGlo; fRHSGlo = 0; if (fRHSLoc) delete[] fRHSLoc; fRHSLoc = 0; if (fMatGamma) delete[] fMatGamma; fMatGamma = 0; if (fMatG) delete[] fMatG; fMatG = 0; if (fCovDGl) delete[] fCovDGl; fCovDGl = 0; n = TMath::Max(16,fMaxPoints); Init(n); // }