#include #include #include #include #include #include #include "improved.h" #include "interact.h" /* This file contains subroutines to calculate improved matrix elements for DLCQ. This calculates P^- (previously, it gave 2 P^-, this was changed in Feb. 2002, as noted in comments) This follows the basic method of Appendix C of hep-ph/9704408 with the following exceptions: 1. The method is now numerically stable with values good to machine precision. This is because a basis of sines and cosines is used instead of the Polynomials. 3. For particle number changing interactions, the wavefunction is assumed to go to a constant as any two momenta go to zero (this can be proven from the bound state equations). 4. There is no limit to K other than K = KKMAX. The method for calculating the matrix elements of the instantaneous interaction rely on a combination of numerical Gauss-Jacobi integration (The number of necessary grid points was determined before hand in Mathematica) and analytic integration. External subroutines to provide the weighting functions, the gamma function, and Bessel functions are used. In the parallelized version, all order K^2 computations are parallelized. This includes the numerical integrations in instant22() the matrix multiplications in mapcouplings(); These are all performed with the communications handle IMPROVED_MPI_COMM; For large K, the arrays holding the matrix elements can be very large, increasing as K^3. The use of order_k(...) minimizes the storage needed for the 2->2 particle interactions. */ #ifdef USE_MPI #include "usempi.h" #if 0 /* GROUP_SIZE != 0*/ /* case with master and slaves */ #define IMPROVED_MPI_COMM mpiallslaves #else /* case where everyone does the work */ #define IMPROVED_MPI_COMM MPI_COMM_WORLD #endif #endif /* mapcouplings(...) Calculate beta and calculate matrix elements in the arrays fun22 and fun13. ratio=m^2=mu^2 a^{D-2}/g^2 N and kt is twice the maximum value of K to calculate matrix elements. The root finding for beta is done internally since efficiency is not very important here. Here, I have rescaled g^2 -> g^2/2.0 so that the definition of g is now standard. If the value of beta matches the previous value and global_kt is the largest value of kt for any spectrum, as determined by initspectrum(...). */ unsigned int global_kt=0; /* initial value for global_kt */ /* the following variables are used to determine if new matrix elements need to be calculated */ static element last_beta=-1.0; /* previous value of beta */ static unsigned int last_kt=0; /* previous value of kt */ size_t fun22_memory=0; /* bytes of memory used fun22 currently used */ size_t fun13_memory=0; /* bytes of memory used fun13 currently used */ /* This file uses a lot of functions which are only needed locally */ /* This is the number terms in fourelements and two elements */ const int four=4,two=2; #define TOP (3*KKMAX+20) /*This is the maximum number of states */ /*in the cosine and sine bases */ /*This definition should match the definition of top below. */ #if IMPROVED==3 static struct {element x; element b; element tol; integer which; element k1; element k2; element u; element kk;} f; static element bj(element, element); static void inner22(element *,element *,int,element,element); static void map22(element *,element *,int,int,element,element); static void mass22(element *,element *,int,element,element); static void instant22(element *,element *,int,element,element); static void annihilate22(element *,element *,int,element,element); static void lambda22(element *,element *,int,element,element); #endif element mapcouplings(element *couplings, unsigned int this_kt){ int i,j,k; element beta=0.0,pi,ratio=couplings[MM]/couplings[GGN]; element lower=0.0, upper=0.5, tol=10.0*DBL_EPSILON; clock_t t1,t2; size_t size_temp; integer kkdown; /* sum of two incoming momenta, *each* rounded down */ #if IMPROVED==1 element k1,k2,k3,k4,k123,kl; int l; element ksum; #elif IMPROVED==3 element temp; fun13_forms *sow2; int l,m; integer kk2,top,error,itype=1,lwork; element *vvi[2],*vvl[2],*ham[2],*tt[2],*tt2; element offset=-0.5,pre; char up='U',vects='V'; #else element *rowin; #endif fun22_forms *row; fun13_forms *sow; #ifdef USE_MPI /* initialize communicator with just slaves. */ int nslaves,myrank; #endif pi= atan(1.) * 4.; /* Complain if this_kt is larger than global_kt */ if(this_kt>global_kt){ fprintf(stderr,__FILE__": present value of kt=%i is larger than " "global_kt=%i\n Use initspectrum() to properly initialize " "global_kt.\n",this_kt,global_kt); goto error; } /* Complain if global_kt is too large */ if(global_kt>2*KKMAX){ fprintf(stderr,__FILE__": Value of kt=%i in mapcouplings is too large," " exiting\n",global_kt); goto error; } /* Complain if improved and periodic */ if(GLUE_PERIODIC && IMPROVED==3){ fprintf(stderr,__FILE__": Improved matrix elements for periodic\n" " boundary conditions does not work yet.\n"); goto error; } /* Calculate beta and prepare coupings. */ if(ratiotol){ beta=0.5*(upper+lower); if(beta * tan(pi * beta)2 particle interactions */ #if 0 /*debugging print */ printf("Starting 2->2 max K=%i/2 beta=%f\n",global_kt,beta); #endif #if IMPROVED==3 /* internally constructed improved matrix elements */ /* top is the number of wavefunctions to include in the basis; it should be roughly proportional to K. The time needed to calculate the improved matrix elements is roughly order top^4. */ /* Timing measured on rum or whiskey */ /* top=4*K, K=20 takes 140 seconds. matrix elements 2.5 digits. */ /* top=3*K, K=20 takes 54 seconds. matrix elements 2.5 digits. */ /* top=2*K, K=20 takes 15 seconds. matrix elements 2 digits. */ top=(GLUE_PERIODIC?3*global_kt+40:(3*global_kt+40)/2); if(top>TOP){ fprintf(stderr,__FILE__": Value of top=%li in mapcouplings is too large," " exiting\n",top); goto error; } for(i=0; i<2; i++){ if(NULL==(vvi[i]=malloc(top*top*sizeof(element))))goto memerror; if(NULL==(vvl[i]=malloc(top*top*sizeof(element))))goto memerror; if(NULL==(ham[i]=malloc(top*top*sizeof(element))))goto memerror; if(NULL==(tt[i]=malloc(top*(global_kt+3)/2* sizeof(element))))goto memerror; } if(NULL==(tt2=malloc(top*(global_kt+3)/2* sizeof(element))))goto memerror; t2=clock(); instant22(vvi[0],vvi[1],top,beta,offset); t2=clock()-t2; lambda22(vvl[0],vvl[1],top,beta,offset); if(beta>tol){ mass22(ham[0],ham[1],top,beta,offset); pre=beta*tan(pi*beta); for(k=0; k<2; k++) for(i=0; i0.0) vvl[1][l]=1.0; else vvl[1][l]=-1.0; DORGQR(&kk,&kk2,&kk2,tt2,&kk,vvl[0],vvl[0]+kk,&lwork,&error); if(error){ fprintf(stderr,__FILE__": DORGQR error %li in mapcouplings\n", error); goto error; } /* Perform multiplication to get to cosine-sine basis */ for(j=0; jmass=temp; break; case 1: row->ggn=temp; break; case 2: row->annihilate=temp; break; case 3: row->lambda=temp; break; } } } } } /* gather and send out results */ #ifdef USE_MPI /* kkdown is the sum of the momenta, *each* rounded down */ for(kkdown=0; kkdown<=global_kt/2-(GLUE_PERIODIC?0:1); kkdown++) for(j=0; j<=kkdown; j++) MPI_Bcast(fun22[kkdown][j],((2*j<=kkdown?j:kkdown-j)+1)* sizeof(fun22_forms)/sizeof(element), MPI_DOUBLE, kkdown%nslaves,IMPROVED_MPI_COMM); #endif /* free in reverse order of allocation */ free(tt2); for(i=1; i>=0; i--){ free(tt[i]); free(ham[i]); free(vvl[i]); free(vvi[i]); } #else /* internally constructed DLCQ */ /* kkdown is the sum of the momenta, *each* rounded down */ for(kkdown=0; kkdown<=global_kt/2-(GLUE_PERIODIC?0:1); kkdown++){ /* j is one incoming momentum (rounded down) */ for(j=0; j<=kkdown; j++){ if(fun22[kkdown][j]==NULL){ size_temp=((2*j<=kkdown?j:kkdown-j)+1)*sizeof(fun22_forms); fun22_memory+=size_temp; if(NULL==(fun22[kkdown][j]=malloc(size_temp))) goto memerror; } /* k is one outgoing momentum (rounded down) */ for(k=0; k<=j && k<=kkdown-j; k++){ row=&fun22[kkdown][j][k]; ksum=(element) (GLUE_PERIODIC?kkdown:kkdown+1); k1=GE(j); k2=ksum-k1; k3=GE(k); k4=ksum-k3; if(j==k) row->mass=0.25*(1.0/k1+1.0/k2); /* changed 0.5 -> 0.25 */ else row->mass=0.0; if(j==k){ row->ggn=1.0/(16.0*sqrt(k1*k2)); /* changed 8->16 */ for(l=0; l<=kkdown; l++){ /* no zero mode */ if(GLUE_PERIODIC && (l==0 || l==kkdown))continue; if(l==j)continue; /* no pole */ kl=GE(l); row->ggn+=(k1+kl)*(k2+ksum-kl)/ (16*pi*sqrt(k1*k2*kl*(ksum-kl))*pow(k1-kl,2)); /* 8->16 */ } } else row->ggn=-(k1+k3)*(k2+k4)/ (16.0*pi*sqrt(k1*k2*k3*k4)*pow(k1-k3,2)); /* 8->16 */ row->annihilate=-(ksum-2.0*k1)*(ksum-2.0*k3)/ (16.0*pi*sqrt(k1*k2*k3*k4)*ksum*ksum); /* 8->16 */ row->lambda=1.0/(8.0*pi*sqrt(k1*k2*k3*k4)); /* 4.0 -> 8.0 */ } } } #endif /* value of improved */ /**** calculate 1->3 particle interactions *****/ #if 0 /*debugging print */ printf("Starting 1->3\n"); #endif /* i is the momentum (rounded down) of the single incoming particle */ for(i=(GLUE_PERIODIC?0:1); i<=(global_kt-(GLUE_PERIODIC?0:1))/2; i++){ /* j is the momentum (rounded down) of an outgoing particle */ for(j=0; j<=(GLUE_PERIODIC?i:i-1); j++){ if(fun13[i][j]==NULL){ size_temp=(i-j+1)*sizeof(fun13_forms); fun13_memory+=size_temp; if(NULL==(fun13[i][j]=malloc(size_temp))) goto memerror; } #if IMPROVED==3 /* construct improved matrix elements */ #ifdef USE_MPI if(i%nslaves==myrank) #endif /* k is momentum (rounded down) of another outgoing particle */ for(k=0; k+j<=(GLUE_PERIODIC?i:i-1) && k<=j; k++){ /* don't do zero modes */ if(GLUE_PERIODIC && (k==0 || j==0 || i==k+j))continue; sow=&fun13[i][j][k]; temp=1.0/(8.0*pi*sqrt(GE(i)* inner13(1,i,j,k,beta,&error))); /* 4->8 */ sow->ggn=0.5*temp*inner13(3,i,j,k,beta,&error); sow->lambda=temp*inner13(2,i,j,k,beta,&error); if(error){ fprintf(stderr,__FILE__": inner13 error=%li in mapcouplings\n", error); goto error; } if(k!=j){ sow2=&fun13[i][k][j]; sow2->ggn =- sow->ggn; sow2->lambda = sow->lambda; } } #else /* construct DLCQ matrix elements */ for(k=0; k+j<=(GLUE_PERIODIC?i:i-1); k++){ sow=&fun13[i][j][k]; k123=GE(i); k1=GE(j); k2=GE(k); k3=k123-k1-k2; sow->ggn=(k1-k2)*(k123+k3)/ (16.0*pi*sqrt(k1*k2*k3*k123)*pow(k1+k2,2)); /* 8->16 */ sow->lambda=1.0/(8.0*pi*sqrt(k1*k2*k3*k123)); /* 4->8 */ } #endif } } /* gather and send out results */ #if defined(USE_MPI) && IMPROVED==3 for(i=(GLUE_PERIODIC?0:1); i<=(global_kt-(GLUE_PERIODIC?0:1))/2; i++) /* j is the momentum (rounded down) of an outgoing particle */ for(j=0; j<=(GLUE_PERIODIC?i:i-1); j++) MPI_Bcast(fun13[i][j],(i-j+1)*sizeof(fun13_forms)/sizeof(element), MPI_DOUBLE, i%nslaves,IMPROVED_MPI_COMM); #endif #if 0 /*********debugging print *****************************/ printf("finished in a total of %f seconds (instant in %f).\n ", (float)(clock()-t1)/(float) CLOCKS_PER_SEC, (float) t2/(float) CLOCKS_PER_SEC); /* kkdown is the sum of the momenta, *each* rounded down */ for(kkdown=0; kkdown<5 && kkdown<=global_kt/2-(GLUE_PERIODIC?0:1); kkdown++){ int kk=(GLUE_PERIODIC?kkdown:kkdown+1); double x=1.0; printf("starting Ktot=%i%s times %f\n",kk,(GLUE_PERIODIC?"":"/2"),x); for(j=0; j<=kkdown; j++) for(k=0; k<=j && k<=kkdown-j; k++){ row=&fun22[kkdown][j][k]; printf("%.12f %.12f %.12f %.12f\n",x*row->mass,x*row->ggn, x*row->annihilate,x*row->lambda); } } /* i is the momentum (rounded down) of the single incoming particle */ for(i=(GLUE_PERIODIC?0:1); i<5 && i<=(global_kt-(GLUE_PERIODIC?0:1))/2; i++){ double x=2.0; printf("starting Kin=%i%s times %f\n",GLUE_PERIODIC?i:2*i+1, GLUE_PERIODIC?"":"/2",x); /* j is the momentum (rounded down) of an outgoing particle */ for(j=0; j<=(GLUE_PERIODIC?i:i-1); j++) for(k=0; k+j<=(GLUE_PERIODIC?i:i-1); k++){ sow=&fun13[i][j][k]; printf("%.12f %.12f\n",x*sow->ggn,x*sow->lambda); } } #endif /* end debugging prints */ #ifdef USE_MPI /* all slaves must finish before going further. */ MPI_Barrier(IMPROVED_MPI_COMM); #endif return beta; /* normal return */ memerror: fprintf(stderr,__FILE__": malloc returning null in mapcouplings\n"); error: fprintf(stderr,__FILE__": Error in mapcouplings\n"); #ifdef USE_MPI fprintf(stderr,__FILE__": Slave %i sending abort signal\n",myrank); MPI_Abort(IMPROVED_MPI_COMM,1); #endif return -1.0; } /******************************************************************/ /******************************************************************/ /******************************************************************/ #if IMPROVED==3 /* Functions for internal improved matrix element */ /* The function J_n(x/2)/x^n */ static element bj(element n, element x){ doublereal n1,x1; if(n<0.0) return 4.0*(n+1.0)*bj(n+1.0,x)-x*x*bj(n+2.0,x); else if(fabs(x) < ELEMENT_EPSILON){ n1=n+1; return 1.0/(MYGAMMA(&n1)*pow(4.0,n)); } else { n1=n; x1=0.5*fabs(x); return MYBESSELJ(&n1,&x1)/pow(fabs(x),n); } } /* Inner produces top by top matrices for cosine and sine bases One triangle of the matrix is filled. */ static void inner22(element *cc, element *ss, int top, element beta, element offset){ int i,j; element pre,pi,m,n; doublereal b2=2.0*beta+1.0; pi=4.0*atan(1.0); pre=0.5*sqrt(pi)*MYGAMMA(&b2); for(i=0; i 0.125 */ for(i=0; i 0.125 */ for(i=0; i 0.0625 */ for(i=0; iMAXGAUSS){ fprintf(stderr,__FILE__": Too many gauss points in instant22, exiting\n"); fprintf(stderr,__FILE__": top=%i rpc=%i MAXGAUSS=%i\n",top,rpc,MAXGAUSS); return; } /* calculate gaussian weights and points */ GAUSSQ(&kind,&nn,&alpha,&alpha,&kpts,lims,work,t,w); for(i=0; i16 */ ss[col*top+row]=ss[row*top+col] /= -16.0*pi; /* 8->16 */ #if 0 /* debugging print */ if(row<5 && col<5) printf(" row=%i col=%i cc=%.16f ss=%.16f\n", row,col,cc[row*top+col],ss[row*top+col]); #endif } } #ifdef USE_MPI #if 0 /* debugging print */ printf("Proc %i of %i starting to collect from others\n",myrank,nslaves); #endif for(rpc=0; rpc<2*top-1; rpc++){ /* we need to find i even if no data is broadcast */ for(i=0, rmc=rpc%2; rmc<=rpc && rmc<=2*top-2-rpc; rmc+=2, i++) if(rpc%nslaves==myrank){ row=(rpc+rmc)/2; col=(rpc-rmc)/2; sendercc[i]=cc[row*top+col]; senderss[i]=ss[row*top+col]; } if(i>(TOP+1)/2){ fprintf(stderr,__FILE__": i=%i is too large in instant22\n",i); goto error; } MPI_Bcast(sendercc,i,MPI_DOUBLE,rpc%nslaves,IMPROVED_MPI_COMM); MPI_Bcast(senderss,i,MPI_DOUBLE,rpc%nslaves,IMPROVED_MPI_COMM); if(rpc%nslaves!=myrank) for(i=0, rmc=rpc%2; rmc<=rpc && rmc<=2*top-2-rpc; rmc+=2, i++){ row=(rpc+rmc)/2; col=(rpc-rmc)/2; cc[row*top+col]=cc[col*top+row]=sendercc[i]; ss[row*top+col]=ss[col*top+row]=senderss[i]; } } #endif #if 0 /* print out some elements of ss and cc */ for(i=0; i<5 && iMAXGAUSS){ fprintf(stderr,__FILE__": Too many gauss points in instant22, exiting\n"); fprintf(stderr,__FILE__": top=%i rpc=%i MAXGAUSS=%i\n",top,rpc,MAXGAUSS); return; } /* calculate gaussian weights and points */ /* vvdiag is used as a working array */ GAUSSQ(&kind,&nn,&alpha,&alpha,&kpts,lims,vvdiag,t,w); for(i=0; i16 */ /* second to sine states */ m += 1.0; n += 1.0; a1=0.5*pi*(m+n); b1=0.5*pi*(m-n); xc= -0.5*pi*pow(MYGAMMA(&beta2),2)*( bj(beta,b1)*((1.0+4.0*beta)*bj(beta,b1)-2.0*b1*b1*bj(beta+1.0,b1))- bj(beta,a1)*((1.0+4.0*beta)*bj(beta,a1)-2.0*a1*a1*bj(beta+1.0,a1))); /* numerical integration using gauss-Jacobi */ for(i=0; i16 */ #if 1==0 /* debugging print */ printf(" row=%i col=%i cc=%.16f ss=%.16f\n", row,col,cc[row*top+col],ss[row*top+col]); #endif } } } #endif /* Calculate integrals for 1->3 particle interactions All momenta are the DLCQ values minus 0.5 which=1 inner product which=2 lambda interaction (without the 1/(4 pi sqrt(K inner product)) which=3 instantaneous interaction (without the 1/(8 pi sqrt(K inner product)) Unfortunately, the integration subroutine only uses relative errors. Thus I have to do some gymnastics to get a consistant relative answer for the final answer. K=20 took 100 seconds on whiskey for tol=1.0e-6 (relative) K=20 took 61 seconds on whiskey for tol=1.0e-5 (relative) This routine returns the error code of the integration routine. ierr=2 indicates error for DGAUS8. */ element inner13(int which, int kk,int k1,int k2,element b,integer *ierr){ /* tol is the absolute error for the improved matrix elements */ doublereal lower,upper,y,yt=0,tol=1.0e-10; f.kk=0.5+(element) kk; f.k1=0.5+(element) k1; f.k2=0.5+(element) k2; f.b=b; f.which=which; /* error flag, successful completion is ierr=0 */ #if 0 /* debug print */ printf("starting inner13: which=%i kk=%i k1=%i k2=%i\n", which,kk,k1,k2); #endif #if 0 /* This makes the above tol an absolute error */ /*else tol is the relative error in the final improved value. */ f.x=f.k1; tol/=f33(&f.k2); #endif if(which==3 && k1==k2) return 0.0; /* Do K=3/2 in terms of K=5/2 */ if(kk==1 && which==1) return 3.0*pow(3.0/5.0,2.0-6.0*b)*inner13(which,2,0,0,b,ierr); if(kk==1 && which==2) return 3.0*pow(3.0/5.0,0.5-3.0*b)*inner13(which,2,0,0,b,ierr); /* Do either of two lower corners */ if((k1==0 && k2==0)||(k1+k2+1==kk && k2==0)){ lower=0.0; upper=5.0/4.0; f.tol=tol/(upper-lower); DGAUS8(F1_TO_FORTRAN,&lower,&upper,&f.tol,&y,ierr); yt+=y; lower=5.0/4.0; upper=5.0/3.0; f.tol=tol/(upper-lower); DGAUS8(F1_TO_FORTRAN,&lower,&upper,&f.tol,&y,ierr); yt+=y; /* Do either lower or right edge */ } else if((k2==0 || k1+k2+1==kk) && k1>0 && k10 && k2>0 && k1+k2+13)goto error; return yt; /* normal return */ error: fprintf(stderr,__FILE__": Error in DGAUS8 in inner13, ierr=%li, which=%i\n", *ierr,which); *ierr=2; return 0.0; } #ifdef __GNUC__ /* assume that g77 is being used, doesn't have RECURSIVE */ #define DGAUS8_SUB DGAUS8_COPY #else /* otherwise, call DGAUS8 recursively */ #define DGAUS8_SUB DGAUS8 #endif /* Numerical integration function for corners for which=1 and beta small, the integrand of the z integration disappears. */ doublereal f1(doublereal *u){ integer ierr; doublereal lower=0.0,upper,y,tol; f.u=*u; y=2.0-5.0/(2.0* *u); if(y>lower)lower=y; if(f.which==3){ upper=1; y=5.0/(2.0* *u)-1.0; if(ylower)lower=yt; upper=1.5-f.k1+ *x; yt=0.5*f.k1+1.0-0.5* *x; if(upper>yt)upper=yt; yt=2.0*f.k1+1.5-2.0* *x; if(upper>yt)upper=yt; if(f.which==1 && f.b<10.0*DBL_EPSILON) yt=0.0; else { if(f.xlower)lower=yt; yt=*x-1.0-f.k1+f.k2; if(yt>lower)lower=yt; upper=2.0*f.k1+f.k2+1.0-2.0* *x; yt=0.5*f.k1+f.k2+0.5-0.5* *x; if(upper>yt)upper=yt; yt=*x+1.0-f.k1+f.k2; if(upper>yt)upper=yt; tol=f.tol/(upper-lower); DGAUS8_SUB(F33_TO_FORTRAN,&lower,&upper,&tol,&yt,&ierr); if(ierr==2) fprintf(stderr,__FILE__": Error=%li in f3 DGAUSS8\n",ierr); return yt; } /* This should be the dominant time consumer for large K for the 1->3 particle interactions */ doublereal f33(doublereal *y){ doublereal a,b; if(f.which==1){ a=(f.x+*y)*(f.kk-f.x)*(f.kk-*y); return pow((f.kk-f.x-*y)*f.x* *y/(a*a),2.0*f.b); } else if(f.which==2){ a=(f.x+*y)*(f.kk-f.x)*(f.kk-*y); return pow(*y*f.x*(f.kk-f.x-*y)/(a*a),f.b-0.5)/a; } else { a=f.x+*y; b=a*(f.kk-f.x)*(f.kk-*y); return (f.x-*y)*(2.0*f.kk-f.x-*y)* pow(*y*f.x*(f.kk-f.x-*y)/(b*b),f.b-0.5)/ (a*a*b); } } #endif /* functions for IMPROVED=3 */ /* This prints out the memory used by fun22 and fun13 */ void print_interaction_memory(FILE *fp){ fprintf(fp,"MM 2->2 and 1->3 interactions use " SIZE_T_PRINT " and " SIZE_T_PRINT " bytes\n", fun22_memory,fun13_memory); fprintf(fp,"MM with pointer static memory use %i bytes\n", sizeof(fun22)+sizeof(fun13)); } /* free memory allocated for fun22 and fun13. */ void free_improved(void){ int i,j,kkdown; /* kkdown is the sum of the momenta, *each* rounded down */ for(kkdown=0; kkdown<=global_kt/2-(GLUE_PERIODIC?0:1); kkdown++) /* j is one incoming momentum (rounded down) */ for(j=0; j<=kkdown; j++){ free(fun22[kkdown][j]); fun22[kkdown][j]=NULL; } fun22_memory=0; last_kt=0; /* i is the momentum (rounded down) of the single incoming particle */ for(i=(GLUE_PERIODIC?0:1); i<=(global_kt-(GLUE_PERIODIC?0:1))/2; i++) /* j is the momentum (rounded down) of an outgoing particle */ for(j=0; j<=(GLUE_PERIODIC?i:i-1); j++){ free(fun13[i][j]); fun13[i][j]=NULL; } fun13_memory=0; last_beta=-1.0; last_kt=0; }