#include #include #include #include #include #include "include.h" #include "run.h" #if defined(USE_MPI) #include "usempi.h" #endif /** This file runs the lanczos algorithm for finding the lowest Eigenvalues of the Hamiltonian with extrapolation for nonzero P_1. The results are then analyzed for consistant dispersion relations, and a best fit is found based on this criterion. This version also demands degeneracy in the lowest parity doublet. It also uses the string tension to determine the lattice spacing. **/ #if HINDEX==1 #define PRINTIT 1 /*Print timing and convergence information */ /*for each iteration of fcn */ #define FTEPER 0 /* Teper's states to fit, each sector*/ /* This can be 0 to NSTILLVALS (2 is a good nonzero choice) */ #define FCSQUARED 1*TOTALSTATES /* Number of c^2 values to use in fit. */ /* This can be 0, 1 or TOTALSTATES */ #define FPARITY 2 /* Number of parity doublets to fit. */ /* This can be 0, 2. */ #define FSCALE 1 /*Whether to include consistantcy of the */ /*longitudinal potential with the overall scale. The potential itself is calculated anyway. This can be 0 or 1. */ #define FLONG MAX_LONG /*Number of longitudinal heavy potential */ /*points to fit */ /*This can be 0 to MAX_LONG. */ #define NJPC 2 /*Number of JPC sectors for nonzero P_perp */ #define NP1 1 /*Number of values of nonzero transverse momentum */ #define TOTALSTATES 8 /*Total number of states in all NJPC sectors */ /*This is not so easily changed... */ #define NSTILL 4 /*Number of sectors for zero transverse momentum spectra This must be 4 to cover all multiplets. */ #define NSTILLVALS 4 /*Number of states calculated in each sector*/ /*This must be large enough to obtain all nonzero momenta states. */ #define MAXTH 10 /* max number of terms in fit functions */ #define NLONG 3 /*Data points used to estimate longitudinal potential */ #define NWIND 3 /* Data points used to estimate winding potential */ #define MAX_LONG 3 /* max number of criteria for roundness of long. pot. */ #if 1 /* newer smaller test basis */ /* one step takes about 47 CPU seconds on the Pentium Pro */ /* one step takes about 80 CPU seconds on the Hewlett Packard */ #define NS 4 const static int kt[NS]={10,10,14,18}, np[NS]={6,8,6,6}; #define WNS 4 int wkt[NWIND][WNS]={{10,10,14,18},{9,9,11,13},{10,10,12,14}}, wnp[NWIND][WNS]={{4,6,4,4},{5,7,5,5},{6,8,6,6}}, wht[NWIND][HINDEX]={{2},{3},{4}}; #define LNS 5 static int lkt0[LNS]={-14,-14,-14,-34,-34}, lkt[MAX_LONG][LNS]={{-7,-7,-7,-21,-21},{-7,-7,-7,-21,-21}, {-7,-7,-7,-21,-21}}, lnp0[LNS]={2,4,2,2,2}, lnp[MAX_LONG][LNS]={{3,5,3,3,3},{3,5,3,3,3},{3,5,3,3,3}}; element lkmax[LNS]={3.0,3.0,4.0,3.0,4.0},llong0[NLONG]={3.0,4.0,6.0}, llong[MAX_LONG]={0.0,2.5,5.0}; #define PNS 6 /* number of sectors in p extrapolation */ static int pnp1[PNS]={1,1,3,3,5,5}, pkt1[PNS]={19,29,19,29,19,21}, pht1[HINDEX]={1}; #elif 0 /* August 2000 Larger basis */ /* one step takes about 12.5 CPU minutes (geneva cluster) */ #define NS 4 const static int kt[NS]={20,20,26,32}, np[NS]={6,8,6,6}; #define WNS 4 static int wkt[NWIND][WNS]={{20,20,24,34},{21,21,25,35}, {20,20,24,34}}, wnp[NWIND][WNS]={{4,6,4,4},{5,7,5,5},{6,8,6,6}}, wht[NWIND][HINDEX]={{2},{3},{4}}; #define LNS 7 static int lkt0[LNS]={-40,-40,-40,-50,-50,-70,-70}, lnp0[LNS]={2,4,2,2,2,2,2}, lkt[MAX_LONG][LNS]={{-21,-21,-21,-35,-35,-69,-69}, {-21,-21,-21,-35,-35,-69,-69}, {-21,-21,-21,-35,-35,-69,-69}}, lnp[MAX_LONG][LNS]={{3,5,3,3,3,3,3},{3,5,3,3,3,3,3},{3,5,3,3,3,3,3}}; element lkmax0[LNS]={4.0,4.0,3.5,3.75,4.25,4.0,4.5}, lkmax[MAX_LONG][LNS]={{4.0,4.0,3.5,4.0,5.0,5.0,6.0}, {4.0,4.0,3.5,4.0,5.0,5.0,6.0}, {4.0,4.0,3.5,4.0,5.0,5.0,6.0}}, llong0[NLONG]={3.0,4.0,6.0},llong[MAX_LONG]={0.0,2.5,5.0}; #define PNS 7 /* number of sectors in p extrapolation */ static int pnp1[PNS]={3,3,3,5,5,7,7},pkt1[PNS]={21,27,39,21,27,21,23}, pht1[HINDEX]={1}; #elif 0 /* 1999 Larger basis */ /* one step takes about 21 CPU minutes */ /* one step takes about 34 CPU minutes on the Hewlett Packard */ /* Note there is an error in the winding extrapolation */ #define NS 6 const static int kt[NS]={18,18,20,20,26,32}, np[NS]={6,8,6,8,6,6}; #define WNS 6 static int wkt[NWIND][WNS]={{20,20,20,20,24,28},{19,19,21,21,23,27}, {18,18,20,20,22,26}}, wnp[NWIND][WNS]={{4,6,4,6,4,4},{5,7,5,7,5,5},{6,8,6,8,6,6}}, wht[NWIND][HINDEX]={{2},{3},{4}}; #define LNS 7 static int lkt0[LNS]={-32,-32,-32,-44,-44,-60,-60}, lkt[MAX_LONG][LNS]={{-19,-19,-19,-33,-33,-49,-49}, {-19,-19,-19,-33,-33,-49,-49}, {-19,-19,-19,-33,-33,-49,-49}}, lnp0[LNS]={2,4,2,2,2,2,2}, lnp[MAX_LONG][LNS]={{3,5,3,3,3,3,3},{3,5,3,3,3,3,3},{3,5,3,3,3,3,3}}; element lkmax0[LNS]={3.0,3.0,4.5,3.0,4.5,3.0,4.5}, llong0[NLONG]={3.0,4.0,6.0},llong[MAX_LONG]={0.0,2.5,5.0}; #define PNS 7 /* number of sectors in p extrapolation */ static int pnp1[PNS]={3,3,3,5,5,7,7},pkt1[PNS]={21,27,39,21,27,21,23}, pht1[HINDEX]={1}; #elif 0 /* Truncations used in paper */ #define NS 7 const static int kt[NS]={20,20,20,22,24,26,28}, np[NS]={4,6,8,6,6,6,6}; #define NWIND 4 #define WNS 1 static int wkt[NWIND][WNS]={{22},{21},{22},{21}}, wnp[NWIND][WNS]={{6},{7},{8},{9}}, wht[NWIND][HINDEX]={{2},{3},{4},{5}}; #define LNS 1 static int lkt[LNS]={-30}, lnp[LNS]={4}; #define PNS 5 /* number of sectors in p extrapolation */ static int pnp1[PNS]={3,3,5,5,7}, pkt1[PNS]={21,19,19,21,19}, pht1[HINDEX]={1}; static element longlist[NLONG]={3.0,4.0,5.0},kmax[2]={0.0,4.0}; #elif 0 /* older test basis */ #define NS 4 const static int kt[NS]={14,12,14,16}, np[NS]={4,6,6,4}; #define NWIND 3 #define WNS 3 int wkt[NWIND][WNS]={{12,14,16},{9,11,13},{10,12,14}}, wnp[NWIND][WNS]={{6,4,4},{7,5,5},{8,6,6}}, wht[NWIND][HINDEX]={{2},{3},{4}}; #define LNS 4 static int lkt0[LNS]={-14,-14,-18,-30}, lkt1[LNS]={-7,-7,-17,-21}, lnp0[LNS]={2,4,2,2}, lnp1[LNS]={3,5,3,3}; element kmaxlist[LNS]={3,3,3,3},longlist[NLONG]={3.0,4.0,5.0}; #define PNS 4 /* number of sectors in p extrapolation */ static int pnp1[PNS]={1,3,5,7}, pkt1[PNS]={11,11,11,11},pht1[HINDEX]={1}; #endif /* Below are several choices for errors. The error for: c^2 for each state, roundness of heavy quark potential (difference in eigenvalues), scale determined by longitudinal error (fractional error), and parity doublets (fractional error). */ #if 0 && MAX_LONG<4 /* try to get as many states correct as possible */ static const element lerr0=0.2, lerr[MAX_LONG]={0.2,0.2,0.2}, c2err[TOTALSTATES]={0.5,2.0,0.5,0.5,0.5,0.5,0.5,0.5}, parityerr[2]={2.0,0.5}; #elif 1 && MAX_LONG<4 /* new compromise between the above and below. */ /* Used August 2000 */ static const element lerr0=0.1, lerr[MAX_LONG]={0.1,0.1,0.1}, c2err[TOTALSTATES]={0.1,2.0,2.0,0.5,0.25,0.25,1.0,1.0}, parityerr[2]={1.0,0.1}; #elif 0 && MAX_LONG<4 /* compromise between the above and below. */ static const element lerr0=0.2, lerr[MAX_LONG]={0.1,0.1,0.1}, c2err[TOTALSTATES]={0.25,2.0,0.5,2.0,0.25,0.5,0.5,2.0}, parityerr[2]={2.0,0.5}; #elif 0 /* try to get lowest state correct in each charge sector. */ static const element lerr0=2.5, lerr[2]={3.0,0.3}, c2err[TOTALSTATES]={0.15,2.0,2.0,2.0,0.15,2.0,2.0,2.0}, parityerr[2]={2.0,2.0}; #endif /* Teper's lattice data with errors for the first four states in each charge conjugation sector: Also included is a 5% error from our eigenvalues. See "jessica.nb" and hep-lat/9804008 */ #if FTEPER<=4 element teper[NSTILL][4]= {{16.5242,38.1924,47.3344,63.8401}, {63.0436,88.1721,89.6809,92.9296}, {34.9281,58.2169,63.0436,80.2816}, {47.3344,74.3044,81.3604,100.}}, tepererr[NSTILL][4]= {{0.939451,2.49569,2.8858,4.7485}, {5.58069,9.86634,22.4233,11.2252}, {3.43249,6.35237,5.58069,12.3203}, {2.8858,7.53134,6.77042,6.52993}}; #endif /* Winding numbers for longitudinal string tension. lht0 must be zero since the lattice spacing is unknown */ #if MAX_LONG<4 static int lht0[HINDEX]={0},lht[MAX_LONG][HINDEX]={{1},{1},{1}}; #endif const int nvals[NJPC]={4,4}; static sectors s[NJPC][NS],ws[NWIND][WNS],ls0[LNS], lt0[LNS],ls[FLONG][LNS],lt[FLONG][LNS],t[NJPC][NS],ps1[PNS], stillbases[NSTILL][NS]; static int wpar[NPARAMS],scalemethod; static doublereal p1a[NP1][HINDEX]={{0.25}}; static element par[NPARAMS]; static integer wth,lth; /* These are all the quantities returned by fcn */ static struct {doublereal pextrap; element lvalue[FLONG]; element calclvalue[FLONG]; element wfitting[MAXTH]; element lfitting[MAXTH]; element rescale; element spectrumvals[NP1+1][TOTALSTATES]; element c2[TOTALSTATES]; element stillvals[NSTILL][NSTILLVALS];} best; int MAIN(int argc, char **argv){ #define NOUT 100 /*Dimensions of chi^2 fit*/ #define MM (NSTILL*FTEPER+FCSQUARED+FPARITY+FSCALE+FLONG) char out[NOUT],*pout; /* Output file name length */ integer mm=MM,npar=1,maxfev,mode=1,ifail=0,info,nfev,ipvt[NPARAMS]; /* epsfcn should be a little less than the Lanczos accuracy. (say 10 times) ftol should be a little more than epsfcn xtol is the desired precision of the coupling constants factor controls the maximum initial step size. If the chi^2 surface is not smooth, this must be decreased to maybe 1. (recommended range: 0.1 to 100, default 100). epsfcn is the variable used to determine the step size for the finite difference approximation. Since the extrapolations magnify any error in the eigenvalues, this should be comfortably larger than the errors in the lanczos routine. However, it should also be smaller than xtol. */ doublereal xtol=1.0e-3,gtol=0.0,ftol=5.e-5,epsfcn=5.0e-5,factor=1.0; doublereal vpar[NPARAMS],fvec[MM],diag[NPARAMS],fjac[MM*NPARAMS]; doublereal qtf[NPARAMS],wa1[NPARAMS],wa2[NPARAMS],wa3[NPARAMS],wa4[MM]; clock_t t1; int i,j,k,l,o[NJPC]={1,1},o2[NJPC]={-1,-1},ht[HINDEX]={0}, multi[NJPC]={1,2},multi2[NJPC]={2,1}; #if NSTILL==4 int multistill[NSTILL]={1,1,2,2},ostill[NSTILL]={1,-1,1,-1}; #endif element chi2; FILE *fp; #ifdef USE_MPI int myrank; #endif #ifdef BABBAGE /* Routine to initialize Fortran on Babbage */ if(hf_fint((char*)NULL)) exit(1); #endif /* initialize parallelization via MPI when applicable. in this case we use a simple master/slave setup to distribute the construction of the Hamiltonian and the diagonalization of the various bases. */ #ifdef USE_MPI MPI_Init(&argc, &argv); /* initialize MPI */ initmpisectors(); MPI_Comm_rank(MPI_COMM_WORLD,&myrank); if(myrank!=0){ slave(); MPI_Finalize(); /* cleanup MPI */ return 0; } #endif /* Choose scale method, Load in data files, and open output file */ printf("Output file name: "); fgets(out,NOUT,stdin); if((pout=strchr(out,'\n'))!=NULL)*pout='\0'; printf("%s\n",out); if((fp = fopen(out,"w")) == NULL){ fprintf(stderr,__FILE__": Can't open file %s, exiting\n",out); goto cleanup; } printf("Input maximum number of iterations: "); scanf("%li",&maxfev); printf("Choose method for determining the overall scale:\n" " 0 use longitudinal string tension\n" " 1 fit lowest state in spectrum to lattice value\n" " 2 demand minimum chi^2 for c^2 measurements\n" " 3 find scale by demanding overall minimum chi^2.\n"); scanf("%i",&scalemethod); for(i=0, j=0; i0 fprintf(fp,"Includes a fit to %i*%i eigenvalues from Teper.\n",NSTILLVALS,FTEPER); #endif #if FPARITY>0 fprintf(fp,"%i parity doublets with fractional errors",FPARITY); for(i=0, k=4; i0 " Finally come the states for the ordinary spectra.\n" #endif "\n",NPARAMS); fflush(fp); /* make basis structures */ printf("Make %i spectrum bases,",2*NJPC*NS); t1=clock(); for(j=0; j4) fprintf(stderr,__FILE__": Error in lmdif info=%li\n",info); if(info==0)goto cleanup; /*Map best values into par[],*/ for(i=0; i0)printf("\nwhile fitting"); for(i=0; iNLONG element weights[NWIND*MAXTH],holdvals[NWIND]; #else element weights[NLONG*MAXTH],holdvals[NLONG]; #endif #if defined(USE_MPI) && ONE_PROCESSOR_SPECTRUM #define SMAX 200 /* maximum total number of matrices to calculate */ sectors *mpibase[SMAX][2]; int job,njob,mpinvals[SMAX],whichvals[SMAX]; element angle[SMAX][HINDEX+2]; static element *mpivals=NULL; #else int idummy[HINDEX+2]; doublereal dummy[HINDEX+2]; #endif tf=clock(); /* bestpar is used later to see if unfitted variables have changed*/ for(i=0; i<*npar; i++)bestpar[wpar[i]]=par[wpar[i]]=xp[i]; /* then find what needs to be recalculated */ #if 0 /* I am not 100% sure this works right */ /* then find what needs to be recalculated */ for(i=0; i<4 && fabs(par[i]-oldpar[i])<=2*ELEMENT_EPSILON; i++); prepeat=i<4; /*recalculate "p-extrapolation", nonzero winding */ for(i=0; i1.0e4)break; if(iSMAX){ fprintf(stderr,__FILE__": SMAX is too small, exiting\n."); *iflag=-8; return SUBRETURN; } for(i=0, j=0; i=4 && vals[2]>vals[3]){ temp=vals[2]; vals[2]=vals[3]; vals[3]=temp; } for(k=0; k=4 && vals[2]>vals[3]){ temp=vals[2]; vals[2]=vals[3]; vals[3]=temp; } for(k=0; kNSTILLVALS){ fprintf(stderr,__FILE__": Insufficient number of states in ordinary\n" "spectrum for use in nonzero P_perp, exiting\n"); *iflag=-11; return SUBRETURN; } for(j=0, k=0; jmulti==s[i]->multi && stillbases[j]->o==s[i]->o)|| (stillbases[j]->multi==t[i]->multi && stillbases[j]->o==t[i]->o)) addterms(vals,&k,nvals[i],stillvals[j],NSTILLVALS); } } } /* copy couplings into oldparams */ for(i=0; i0.0) rescale=sqrt(rescale); else { rescale=0.0; *iflag = -1; } } else if(scalemethod==3){ /* Find scale by minimizing overall chi^2 This does not include the consistancy of the L nonzero, n=1 datum because it is too complicated initial guess is from Teper's lowest state */ for(rescale=teper[0][0]/stillvals[0][0], j=0; ; j++){ sum=0.0; zz=0.0; for(i=0; i1.0e10 || rescale < 0.0){ fprintf(stderr,__FILE__": The value of rescale is %e\n",rescale); printf("The value of rescale is %e\n",rescale); } /* find error of speed of light squared with coupling g^2 N and "a" as determined above. */ temp=wfitting[0]*pow(rescale,2)/fdot(p1a[0],p1a[0],HINDEX); for(i=0; i0.0){ calclvalue[i]=sqrt(temp); lweights(weights,<h,1,calclvalue+i); calclvalue[i]=fdot(weights,lfitting,lth); fvecc[fitc++]=(lvalue[i]-calclvalue[i])/lerr[i]; } else { fvecc[fitc++]=1.0; *iflag = -3; } } /* Consistancy of longitudinal string tension with rescale */ #if FSCALE fvecc[fitc++]=(rescale*lfitting[0]-1.0)/lerr0; #endif /* Add parity doublets to fitting criterion using fractional difference. */ /* Here we use some "model dependant" assumptions concerning the ordering of the states. */ #if FPARITY==2 for(i=0; imulti!=1 || stillbases[i]->o!=1); i++); for(j=0; jmulti!=2 || stillbases[j]->o!=-1); j++); if(imulti!=2 || stillbases[i]->o!=1); i++); for(j=0; jmulti!=1 || stillbases[j]->o!=-1); j++); if(i=0 && (i