/* Flow analysis through the cumulant method. Version with multiparticle correlations. */ /* The input is a file 'events.dat' following the structure of the file generated by 'detector.cc', i.e.: - first, the number of events; - then, for each event, the (detected) particle multiplicity, and for each particle, the transverse momentum and the azimuth. */ /* The program then reconstructs integrated elliptic flow (V2) and both differential elliptic (v2) and quadrupolar flows. Numbered equations refer to the paper [A]: N.Borghini, P.M.Dinh, J.-Y.Ollitrault, Phys. Rev. C64 (2001) 054901 [=nucl-th/0105040]. */ /* This program will give you first the INTEGRATED elliptic flow V2 reconstructed using the lowest order formulas of the paper, up to order 6 (section II of paper A): . order 2 (in the paper: v2{2}) corresponds to the "standard" flow analysis (two-particle nonflow correlations neglected); . order 4 (v2{4}) eliminates two-particle nonflow correlations; . order 6 (v2{6}) eliminates also four-particle nonflow correlations. */ /* Once integrated flow is reconstructed, the program evaluates the DIFFERENTIAL flow v'_{nm} of the particles using the lowest order formulas of the paper (section III): v'_nm{m+1} is the standard flow analysis (nonflow correlations neglected); v'_nm{m+3} is the next order. m=1 yields elliptic flow v'2, m=2 yields v'4. */ /* The results are stored in the output file 'cumulants.txt' */ #include #include #include #include #include "distributions.h" /* */ #define Pi (2.*acos(0.)) #define rad2deg (180./Pi) #define sqr(x) ((x)*(x)) /* PARAMETERS USED IN THE RECONSTRUCTION */ /* kr*kt is the number of points at which one computes the generating function [cf Eq.(B1)] kr possible values for the radius kt possible values for the angle: should satisfy kt>2*kr */ #define kr 3 #define kt 7 /* zmax is the maximum value of |z| for which you tabulate the generating functions G_n and C_mn, defined by Eqs.(5) and (7). If zmax is too small, then G_n and C_mn are too close to 1, and you may have large numerical errors when computing, especially if you do not use double precision. If zmax is too large, then the power series expansion of C_mn, which is truncated to order 2 in this program, is not accurate. Try several values of zmax, to check the accuracy of the interpolation procedure. */ #define zmax 1.5 #define r0 (zmax/sqrt(kr)) #define Nbins 60 /* number of bins for differential flow. Check that it is consistent with the number in distributions.cc! */ /* */ FILE *input,*output,*plotvdiff0,*plotvdiff1; double prod1(complex z, double phi, double w) { double temp; temp=1.+2.*w*(real(z)*cos(phi)+imag(z)*sin(phi)); return temp; } main() { const complex i(0,1); /* Variable declaration */ long neve; /* Number of events */ long rmult; /* Detected multiplicity in an event */ long rpmult[Nbins]; /* Detected multiplicity per bin */ double rmultmean=0.; /* Average detected multiplicity */ float phi, pT; /* particle azimuth and transverse momentum */ int binpT; /* Interpolation points [see Eq. (I-B1)]: z[k1][k2] = rz[k1] e^(i arg[k2]).*/ complex z[kr][kt]; double rz[kr], arg[kt]; /* Generating functions: - G2 generating function for integrated flow; - G2mean is the generating function G2 averaged over events; - g22, generating function for v'2 with respect to v2. - g42, generating function for v'4 with respect to v2. */ double G2[kr][kt], G2mean[kr][kt]; complex g22[Nbins][kr][kt], g42[Nbins][kr][kt]; double w2[Nbins]; /* particle weight */ complex sum22[Nbins][kr][kt], sum42[Nbins][kr][kt]; /* Cnrad is the generating function of cumulants for integrated flow, averaged over angles (Eq.(B3)); Dmrad (m=1 or 2) is the generating function of cumulants for differential flow, averaged over angles (Eq.(B7)). cn and dmn are the cumulants used for the reconstruction of integrated and differential flows resp. (c_n{.} and d_mn/n{.}) */ double C2rad[kr], c2[kr]; double D22rad[Nbins][kr], D42rad[Nbins][kr], d22[Nbins][kr], d42[Nbins][kr]; int mflag2[3]; /* tells whether the reconstruction to order k is applicable or not. */ /* V2[k] are the integrated flow estimates obtained from the cumulant to order 2(k+1), i.e. v_2{2k+2} in the Ref. */ double V2[kr]; double chi2sq; /* v22[], v42[], are the differential flow estimates in each bin. v22[0] is v'2/2{2} (Ref.[A]), computed with V2[0]: this is a TWO-particle estimates; v22[1] is v'2/2{4}, computed with V2[1]: this is a FOUR-particle estimate; v42[0], v42[1] are v'4/2{3}, v'4/2{5}, computed with V2[1]: these are MULTIparticle estimates. */ double v22[Nbins][2], v42[Nbins][2]; /* err22[], err42[] are the respective statistical error bars in each bin. */ double err22[Nbins][2], err42[Nbins][2]; double vd22av[2], vd42av[2]; double temp, err; struct timeval Time; int debut, fin; /* Initializations */ gettimeofday (&Time, 0); debut=Time.tv_sec; for(int k1=0; k1 */ G2mean[k1][k2]=0.; /* gmn is the generating function gm=exp(im psi) G_n */ for(int bin=0; bin=%G\n", rmultmean); fprintf(output," mean detected multiplicity =%G\n\n", rmultmean); /* Average over all differential particles of gm (m=1 or 2) */ for(int k1=0; k1^(1/M) - 1), then average over angles (see Eq.(B3)): the result 'Crad' depends on the radius only. For differential flow, compute Dm = / , multiply by z^m, take the real part, and average over angles (see Eq.(B7)): the result 'Dmrad' depends on the radius only. */ for(int k1=0; k10.) V2[1]=0.; else { V2[1]=pow(-c2[1],0.25); mflag2[1]=1; } /* uncorrected v2 using order k=6: Eq.(17c) */ if (c2[2]<0.) V2[2]=0.; else { V2[2]=pow(c2[2]/4.,1./6.); mflag2[2]=1; } fprintf(output,"\n\nINTEGRATED ELLIPTIC FLOW v2\n"); fprintf(output,"\tuncorrected\tcorrected\t+(stat)\t\t-(stat)\n"); /* Result of the method to order k=2 */ fprintf(output, " v2{2}:\t"); chi2sq=rmultmean*sqr(V2[0]); err=sqrt((1.+2.*chi2sq)/neve)/rmultmean; fprintf(output, "%.4g\t\t%.4g\t\t+%.4g", V2[0], V2[0], sqrt(sqr(V2[0])+err)-V2[0]); if (err0) { /* compute the average (over pT) v2 and v4 */ vd22av[0]+=rpmult[bin]*v22[bin][0]; vd22av[1]+=rpmult[bin]*v22[bin][1]; vd42av[0]+=rpmult[bin]*v42[bin][0]; vd42av[1]+=rpmult[bin]*v42[bin][1]; } fprintf(output, " . bin %i: average detected multiplicity =%G\n", bin, ((double) rpmult[bin])/((double) neve)); fprintf(output, " v'2/2{2}=%.3g +/- %.3g,", v22[bin][0], err22[bin][0]); fprintf(output, " v'2/2{4}=%.3g +/- %.3g,\n", v22[bin][1], err22[bin][1]); fprintf(output, " v'4/2{3}=%.3g +/- %.3g,", v42[bin][0], err42[bin][0]); fprintf(output, " v'4/2{5}=%.3g +/- %.3g;\n\n", v42[bin][1], err42[bin][0]); fprintf(plotvdiff0, "%i %.4g %.4g %.4g %.4g %.4g\n", bin, ((double) rpmult[bin])/((double) neve), v22[bin][0], err22[bin][0], v42[bin][0], err42[bin][0]); fprintf(plotvdiff1, "%i %.4g %.4g %.4g %.4g %.4g\n", bin, ((double) rpmult[bin])/((double) neve), v22[bin][1], err22[bin][1], v42[bin][1], err42[bin][1]); } vd22av[0]/=(rmultmean*neve); vd42av[0]/=(rmultmean*neve); vd22av[1]/=(rmultmean*neve); vd42av[1]/=(rmultmean*neve); fprintf(output, "=%.3g, =%.3g, =%.3g, =%.3g\n", vd22av[0], vd22av[1], vd42av[0], vd42av[1]); gettimeofday (&Time, 0); fin=Time.tv_sec; fprintf(output, "\nEnd of the analysis, elapsed time=%d s\n", fin-debut); fclose(output); fclose(plotvdiff0); fclose(plotvdiff1); }