/////////////////////////////////////////////////////////////////////////////////// // // // Wrapper for the set of mag.field parameterizations by Chebyshev polinomials // // To obtain the field in cartesian coordinates/components use // // Field(float* xyz, float* bxyz); // // For cylindrical coordinates/components: // // FieldCyl(float* rphiz, float* brphiz) // // // // The solenoid part is parameterized in the volume R<500, -550AddAtAndExpand(new AliCheb3D(*src.GetParamSol(i)),i); } // if (src.fNParamsDip) { memcpy(fSegZDip = new Float_t[fNZSegDip], src.fSegZDip, sizeof(Float_t)*fNZSegDip); memcpy(fSegYDip = new Float_t[fNYSegDip], src.fSegYDip, sizeof(Float_t)*fNYSegDip); memcpy(fSegXDip = new Float_t[fNXSegDip], src.fSegZDip, sizeof(Float_t)*fNXSegDip); memcpy(fBegSegYDip= new Int_t[fNZSegDip], src.fBegSegYDip, sizeof(Int_t)*fNZSegDip); memcpy(fNSegYDip = new Int_t[fNZSegDip], src.fNSegYDip, sizeof(Int_t)*fNZSegDip); memcpy(fBegSegXDip= new Int_t[fNYSegDip], src.fBegSegXDip, sizeof(Int_t)*fNYSegDip); memcpy(fNSegXDip = new Int_t[fNYSegDip], src.fNSegXDip, sizeof(Int_t)*fNYSegDip); memcpy(fSegIDDip = new Int_t[fNXSegDip], src.fSegIDDip, sizeof(Int_t)*fNXSegDip); fParamsDip = new TObjArray(fNParamsDip); for (int i=0;iAddAtAndExpand(new AliCheb3D(*src.GetParamDip(i)),i); } // if (src.fNParamsTPCInt) { memcpy(fSegZTPCInt = new Float_t[fNSegZTPCInt], src.fSegZTPCInt, sizeof(Float_t)*fNSegZTPCInt); memcpy(fSegRTPCInt = new Float_t[fNParamsTPCInt], src.fSegRTPCInt, sizeof(Float_t)*fNParamsTPCInt); memcpy(fNSegRTPCInt = new Int_t[fNSegZTPCInt], src.fNSegRTPCInt, sizeof(Int_t)*fNSegZTPCInt); memcpy(fSegZIdTPCInt= new Int_t[fNSegZTPCInt], src.fSegZIdTPCInt, sizeof(Int_t)*fNSegZTPCInt); fParamsTPCInt = new TObjArray(fNParamsTPCInt); for (int i=0;iAddAtAndExpand(new AliCheb3D(*src.GetParamTPCInt(i)),i); } // } //__________________________________________________________________________________________ AliMagFCheb& AliMagFCheb::operator=(const AliMagFCheb& rhs) { if (this != &rhs) { Clear(); CopyFrom(rhs); } return *this; // } //__________________________________________________________________________________________ void AliMagFCheb::Clear(Option_t *) { if (fNParamsSol) { delete fParamsSol; delete[] fSegZSol; delete[] fSegRSol; delete[] fNSegRSol; delete[] fSegZIdSol; } // if (fNParamsTPCInt) { delete fParamsTPCInt; delete[] fSegZTPCInt; delete[] fSegRTPCInt; delete[] fNSegRTPCInt; delete[] fSegZIdTPCInt; } // if (fNParamsDip) { delete fParamsDip; delete[] fSegZDip; delete[] fSegYDip; delete[] fSegXDip; delete[] fBegSegYDip; delete[] fNSegYDip; delete[] fBegSegXDip; delete[] fNSegXDip; delete[] fSegIDDip; } fNParamsSol = fNParamsTPCInt = fNParamsDip = fNZSegDip = fNYSegDip = fNXSegDip = 0; fNSegZSol = fNSegZTPCInt = 0; fMinZSol = fMinZDip = fMinZTPCInt = 1e6; fMaxZSol = fMaxZDip = fMaxZTPCInt = fMaxRSol = fMaxRTPCInt = -1e6; // } //__________________________________________________________________________________________ void AliMagFCheb::Field(Float_t *xyz, Float_t *b) const { // compute field in cartesian coordinates. If point is outside of the parameterized region // get it at closest valid point static float rphiz[3]; // #ifndef _BRING_TO_BOUNDARY_ // exact matching to fitted volume is requested if ( !(xyz[2]>=GetMinZSol()&&xyz[2]<=GetMaxZSol()) && !(xyz[2]>=GetMinZDip()&&xyz[2]<=GetMaxZDip()) ) {for (int i=3;i--;) b[i]=0; return;} #endif // if (xyz[2]IsInside(xyz)) {par->Eval(xyz,b); return;} for (int i=3;i--;) b[i]=0; return; #else GetParamDip(FindDipSegment(xyz))->Eval(xyz,b); return; #endif } // // Sol region: convert coordinates to cyl system CartToCyl(xyz,rphiz); #ifndef _BRING_TO_BOUNDARY_ if (rphiz[0]>GetMaxRSol()) {for (int i=3;i--;) b[i]=0; return;} #endif // FieldCylSol(rphiz,b); // // convert field to cartesian system CylToCartCylB(rphiz, b,b); // } //__________________________________________________________________________________________ void AliMagFCheb::GetTPCInt(Float_t *xyz, Float_t *b) const { // compute TPC region field integral in cartesian coordinates. // If point is outside of the parameterized region get it at closeset valid point static float rphiz[3]; // // TPCInt region // convert coordinates to cyl system CartToCyl(xyz,rphiz); #ifndef _BRING_TO_BOUNDARY_ if ( (rphiz[2]>GetMaxZTPCInt()||rphiz[2]GetMaxRTPCInt()) {for (int i=3;i--;) b[i]=0; return;} #endif // GetTPCIntCyl(rphiz,b); // // convert field to cartesian system CylToCartCylB(rphiz, b,b); // } //__________________________________________________________________________________________ void AliMagFCheb::FieldCylSol(Float_t *rphiz, Float_t *b) const { // compute Solenoid field in Cylindircal coordinates // note: if the point is outside the volume get the field in closest parameterized point float &r = rphiz[0]; float &z = rphiz[2]; int SolZId = 0; while (z>fSegZSol[SolZId] && SolZIdfSegRSol[SolRId] && SolRIdEval(rphiz,b); // } //__________________________________________________________________________________________ void AliMagFCheb::GetTPCIntCyl(Float_t *rphiz, Float_t *b) const { // compute field integral in TPC region in Cylindircal coordinates // note: the check for the point being inside the parameterized region is done outside float &r = rphiz[0]; float &z = rphiz[2]; int TPCIntZId = 0; while (z>fSegZTPCInt[TPCIntZId] && TPCIntZIdfSegRTPCInt[TPCIntRId] && TPCIntRIdEval(rphiz,b); // } //__________________________________________________________________________________________ void AliMagFCheb::Print(Option_t *) const { printf("Alice magnetic field parameterized by Chebyshev polynomials\n"); printf("Segmentation for Solenoid (%+.2fPrint(); /* for (int iz=0;izGetBoundMin(2),param->GetBoundMax(2)); for (int ir=0;irGetBoundMin(0), param->GetBoundMax(0),param->GetPrecision(),fSegZIdSol[iz]+ir); } } */ // printf("Segmentation for TPC field integral (%+.2fPrint(); /* for (int iz=0;izGetBoundMin(2),param->GetBoundMax(2)); for (int ir=0;irGetBoundMin(0), param->GetBoundMax(0),param->GetPrecision(),fSegZIdTPCInt[iz]+ir); } } */ // printf("Segmentation for Dipole (%+.2fPrint(); // } //_______________________________________________ void AliMagFCheb::LoadData(const char* inpfile) { // read coefficients data from the text file // TString strf = inpfile; gSystem->ExpandPathName(strf); FILE* stream = fopen(strf,"r"); if (!stream) { printf("Did not find input file %s\n",strf.Data()); return; } // TString buffs; AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("START")) { Error("LoadData","Expected: \"START \", found \"%s\"\nStop\n",buffs.Data()); exit(1); } if (buffs.First(' ')>0) SetName(buffs.Data()+buffs.First(' ')+1); // // Solenoid part ----------------------------------------------------------- AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("START SOLENOID")) { Error("LoadData","Expected: \"START SOLENOID\", found \"%s\"\nStop\n",buffs.Data()); exit(1); } AliCheb3DCalc::ReadLine(buffs,stream); // nparam int nparSol = buffs.Atoi(); // for (int ip=0;ipLoadData(stream); AddParamSol(cheb); } // AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("END SOLENOID")) { Error("LoadData","Expected \"END SOLENOID\", found \"%s\"\nStop\n",buffs.Data()); exit(1); } // // TPCInt part ----------------------------------------------------------- AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("START TPCINT")) { Error("LoadData","Expected: \"START TPCINT\", found \"%s\"\nStop\n",buffs.Data()); exit(1); } AliCheb3DCalc::ReadLine(buffs,stream); // nparam int nparTPCInt = buffs.Atoi(); // for (int ip=0;ipLoadData(stream); AddParamTPCInt(cheb); } // AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("END TPCINT")) { Error("LoadData","Expected \"END TPCINT\", found \"%s\"\nStop\n",buffs.Data()); exit(1); } // // Dipole part ----------------------------------------------------------- AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("START DIPOLE")) { Error("LoadData","Expected: \"START DIPOLE\", found \"%s\"\nStop\n",buffs.Data()); exit(1); } AliCheb3DCalc::ReadLine(buffs,stream); // nparam int nparDip = buffs.Atoi(); // for (int ip=0;ipLoadData(stream); AddParamDip(cheb); } // AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("END DIPOLE")) { Error("LoadData","Expected \"END DIPOLE\", found \"%s\"\nStop\n",GetName(),buffs.Data()); exit(1); } // AliCheb3DCalc::ReadLine(buffs,stream); if (!buffs.BeginsWith("END") || !buffs.Contains(GetName())) { Error("LoadData","Expected: \"END %s\", found \"%s\"\nStop\n",GetName(),buffs.Data()); exit(1); } // // --------------------------------------------------------------------------- fclose(stream); BuildTableSol(); BuildTableTPCInt(); BuildTableDip(); printf("Loaded magnetic field \"%s\" from %s\n",GetName(),strf.Data()); // } //_________________________________________________________________________ Int_t AliMagFCheb::FindDipSegment(float *xyz) const { // find the segment containing point xyz. If it is outside find the closest segment int xid,yid,zid = TMath::BinarySearch(fNZSegDip,fSegZDip,xyz[2]); // find zsegment int ysegBeg = fBegSegYDip[zid]; // for (yid=0;yidAdd(param); fNParamsSol++; // } //__________________________________________________________________________________________ void AliMagFCheb::AddParamTPCInt(AliCheb3D* param) { // adds new parameterization piece for TPCInt // NOTE: pieces must be added strictly in increasing R then increasing Z order // if (!fParamsTPCInt) fParamsTPCInt = new TObjArray(); fParamsTPCInt->Add(param); fNParamsTPCInt++; // } //__________________________________________________________________________________________ void AliMagFCheb::AddParamDip(AliCheb3D* param) { // adds new parameterization piece for Dipole // if (!fParamsDip) fParamsDip = new TObjArray(); fParamsDip->Add(param); fNParamsDip++; // } //__________________________________________________________________________________________ void AliMagFCheb::ResetTPCInt() { // clean TPC field integral (used for update) if (!fNParamsTPCInt) return; delete fParamsTPCInt; delete[] fSegZTPCInt; delete[] fSegRTPCInt; delete[] fNSegRTPCInt; delete[] fSegZIdTPCInt; // fNParamsTPCInt = 0; fNSegZTPCInt = 0; fSegZTPCInt = 0; fSegRTPCInt = 0; fNSegRTPCInt = 0; fSegZIdTPCInt = 0; fMinZTPCInt = 0; fMaxZTPCInt = 0; fMaxRTPCInt = 0; fParamsTPCInt = 0; // } //__________________________________________________ void AliMagFCheb::BuildTableDip() { // TArrayF segY,segX; TArrayI begSegYDip,begSegXDip; TArrayI nsegYDip,nsegXDip; TArrayI segID; float *tmpSegZ,*tmpSegY,*tmpSegX; // // create segmentation in Z fNZSegDip = SegmentDipDimension(&tmpSegZ, fParamsDip, fNParamsDip, 2, 1,-1, 1,-1, 1,-1) - 1; fNYSegDip = 0; fNXSegDip = 0; // // for each Z slice create segmentation in Y begSegYDip.Set(fNZSegDip); nsegYDip.Set(fNZSegDip); float xyz[3]; for (int iz=0;izAt(ipar); if (!cheb->IsInside(xyz)) continue; segID[fNXSegDip+ix] = ipar; break; } } fNXSegDip += nx; // delete[] tmpSegX; } delete[] tmpSegY; fNYSegDip += ny; } // fMinZDip = tmpSegZ[0]; fMaxZDip = tmpSegZ[fNZSegDip]; fSegZDip = new Float_t[fNZSegDip]; for (int i=fNZSegDip;i--;) fSegZDip[i] = tmpSegZ[i]; delete[] tmpSegZ; // fSegYDip = new Float_t[fNYSegDip]; fSegXDip = new Float_t[fNXSegDip]; fBegSegYDip = new Int_t[fNZSegDip]; fNSegYDip = new Int_t[fNZSegDip]; fBegSegXDip = new Int_t[fNYSegDip]; fNSegXDip = new Int_t[fNYSegDip]; fSegIDDip = new Int_t[fNXSegDip]; // for (int i=fNYSegDip;i--;) fSegYDip[i] = segY[i]; for (int i=fNXSegDip;i--;) fSegXDip[i] = segX[i]; for (int i=fNZSegDip;i--;) {fBegSegYDip[i] = begSegYDip[i]; fNSegYDip[i] = nsegYDip[i];} for (int i=fNYSegDip;i--;) {fBegSegXDip[i] = begSegXDip[i]; fNSegXDip[i] = nsegXDip[i];} for (int i=fNXSegDip;i--;) {fSegIDDip[i] = segID[i];} // } //__________________________________________________________________________________________ void AliMagFCheb::BuildTableSol() { // build the indexes for each parameterization of Solenoid // const float kSafety=0.001; // if (fNParamsSol<1) return; fSegRSol = new Float_t[fNParamsSol]; float *tmpbufF = new float[fNParamsSol+1]; int *tmpbufI = new int[fNParamsSol+1]; int *tmpbufI1 = new int[fNParamsSol+1]; // // count number of Z slices and number of R slices in each Z slice for (int ip=0;ipGetBoundMax(2)-GetParamSol(ip-1)->GetBoundMax(2))>kSafety) { // new Z slice tmpbufF[fNSegZSol] = GetParamSol(ip)->GetBoundMax(2); // tmpbufI[fNSegZSol] = 0; tmpbufI1[fNSegZSol++] = ip; } fSegRSol[ip] = GetParamSol(ip)->GetBoundMax(0); // upper R tmpbufI[fNSegZSol-1]++; } // fSegZSol = new Float_t[fNSegZSol]; fSegZIdSol = new Int_t[fNSegZSol]; fNSegRSol = new Int_t[fNSegZSol]; for (int iz=0;izGetBoundMin(2); fMaxZSol = GetParamSol(fNParamsSol-1)->GetBoundMax(2); fMaxRSol = GetParamSol(fNParamsSol-1)->GetBoundMax(0); // delete[] tmpbufF; delete[] tmpbufI; delete[] tmpbufI1; // // } //__________________________________________________________________________________________ void AliMagFCheb::BuildTableTPCInt() { // build the indexes for each parameterization of TPC field integral // const float kSafety=0.001; // if (fNParamsTPCInt<1) return; fSegRTPCInt = new Float_t[fNParamsTPCInt]; float *tmpbufF = new float[fNParamsTPCInt+1]; int *tmpbufI = new int[fNParamsTPCInt+1]; int *tmpbufI1 = new int[fNParamsTPCInt+1]; // // count number of Z slices and number of R slices in each Z slice for (int ip=0;ipGetBoundMax(2)-GetParamTPCInt(ip-1)->GetBoundMax(2))>kSafety) { // new Z slice tmpbufF[fNSegZTPCInt] = GetParamTPCInt(ip)->GetBoundMax(2); // tmpbufI[fNSegZTPCInt] = 0; tmpbufI1[fNSegZTPCInt++] = ip; } fSegRTPCInt[ip] = GetParamTPCInt(ip)->GetBoundMax(0); // upper R tmpbufI[fNSegZTPCInt-1]++; } // fSegZTPCInt = new Float_t[fNSegZTPCInt]; fSegZIdTPCInt = new Int_t[fNSegZTPCInt]; fNSegRTPCInt = new Int_t[fNSegZTPCInt]; for (int iz=0;izGetBoundMin(2); fMaxZTPCInt = GetParamTPCInt(fNParamsTPCInt-1)->GetBoundMax(2); fMaxRTPCInt = GetParamTPCInt(fNParamsTPCInt-1)->GetBoundMax(0); // delete[] tmpbufF; delete[] tmpbufI; delete[] tmpbufI1; // // } void AliMagFCheb::SaveData(const char* outfile) const { // writes coefficients data to output text file TString strf = outfile; gSystem->ExpandPathName(strf); FILE* stream = fopen(strf,"w+"); // // Sol part --------------------------------------------------------- fprintf(stream,"# Set of Chebyshev parameterizations for ALICE magnetic field\nSTART %s\n",GetName()); fprintf(stream,"START SOLENOID\n#Number of pieces\n%d\n",fNParamsSol); for (int ip=0;ipSaveData(stream); fprintf(stream,"#\nEND SOLENOID\n"); // // TPCInt part --------------------------------------------------------- fprintf(stream,"# Set of Chebyshev parameterizations for ALICE magnetic field\nSTART %s\n",GetName()); fprintf(stream,"START TPCINT\n#Number of pieces\n%d\n",fNParamsTPCInt); for (int ip=0;ipSaveData(stream); fprintf(stream,"#\nEND TPCINT\n"); // // Dip part --------------------------------------------------------- fprintf(stream,"START DIPOLE\n#Number of pieces\n%d\n",fNParamsDip); for (int ip=0;ipSaveData(stream); fprintf(stream,"#\nEND DIPOLE\n"); // fprintf(stream,"#\nEND %s\n",GetName()); // fclose(stream); // } Int_t AliMagFCheb::SegmentDipDimension(float** seg,const TObjArray* par,int npar, int dim, float xmn,float xmx,float ymn,float ymx,float zmn,float zmx) { // find all boundaries in deimension dim for boxes in given region. // if mn>mx for given projection the check is not done for it. float *tmpC = new float[2*npar]; int *tmpInd = new int[2*npar]; int nseg0 = 0; for (int ip=0;ipAt(ip); if (xmnGetBoundMin(0)>(xmx+xmn)/2 || cheb->GetBoundMax(0)<(xmn+xmx)/2)) continue; if (ymnGetBoundMin(1)>(ymx+ymn)/2 || cheb->GetBoundMax(1)<(ymn+ymx)/2)) continue; if (zmnGetBoundMin(2)>(zmx+zmn)/2 || cheb->GetBoundMax(2)<(zmn+zmx)/2)) continue; // tmpC[nseg0++] = cheb->GetBoundMin(dim); tmpC[nseg0++] = cheb->GetBoundMax(dim); } // range Dim's boundaries in increasing order TMath::Sort(nseg0,tmpC,tmpInd,kFALSE); // count number of really different Z's int nseg = 0; float cprev = -1e6; for (int ip=0;ip1e-4) { cprev = tmpC[ tmpInd[ip] ]; nseg++; } else tmpInd[ip] = -1; // supress redundant Z } // *seg = new float[nseg]; // create final Z segmenations nseg = 0; for (int ip=0;ip=0) (*seg)[nseg++] = tmpC[ tmpInd[ip] ]; // delete[] tmpC; delete[] tmpInd; return nseg; } #endif