1
SUBROUTINE IMPROVE_PS_POINT_PRECISION(P)
7
PARAMETER (NEXTERNAL=4)
11
DOUBLE PRECISION P(0:3,NEXTERNAL)
12
REAL*16 QP_P(0:3,NEXTERNAL)
28
CALL MP_IMPROVE_PS_POINT_PRECISION(QP_P)
39
SUBROUTINE MP_IMPROVE_PS_POINT_PRECISION(P)
45
PARAMETER (NEXTERNAL=4)
49
REAL*16 P(0:3,NEXTERNAL)
54
INTEGER ERRCODE,ERRCODETMP
55
REAL*16 NEWP(0:3,NEXTERNAL)
59
LOGICAL MP_IS_PHYSICAL
63
INCLUDE 'MadLoopParams.inc'
71
DATA TOLD_SUPPRESS/.FALSE./
76
C ERROR CODES CONVENTION
78
C 1 :: None physical PS point input
79
C 100-1000 :: Error in the origianl method for restoring
81
C 1000-9999 :: Error when restoring precision ala PSMC
92
C Check the sanity of the original PS point
93
IF (.NOT.MP_IS_PHYSICAL(NEWP,WARNED)) THEN
95
WRITE(*,*) 'ERROR:: The input PS point is not precise enough.'
99
C Now restore the precision
100
IF (IMPROVEPSPOINT.EQ.1) THEN
101
CALL MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE,WARNED)
102
ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN
103
CALL MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE,WARNED)
105
IF (ERRCODE.NE.0) THEN
106
IF (WARNED.LT.20) THEN
107
WRITE(*,*) 'INFO:: Attempting to rescue the precision
108
$ improvement with an alternative method.'
111
IF (IMPROVEPSPOINT.EQ.1) THEN
112
CALL MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODETMP
114
ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN
115
CALL MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODETMP
118
IF (ERRCODETMP.NE.0) GOTO 100
121
C Report to the user or update the PS point.
125
IF (WARNED.LT.20) THEN
126
WRITE(*,*) 'WARNING:: This PS point could not be improved.
127
$ Error code = ',ERRCODE,ERRCODETMP
140
IF (WARNED.GE.20.AND..NOT.TOLD_SUPPRESS) THEN
141
WRITE(*,*) 'INFO:: Further warnings from the improve_ps
142
$ routine will now be supressed.'
149
FUNCTION MP_IS_CLOSE(P,NEWP,WARNED)
155
PARAMETER (NEXTERNAL=4)
157
PARAMETER (ZERO=0.0E+00_16)
159
PARAMETER (THRS_CLOSE=1.0E-02_16)
163
REAL*16 P(0:3,NEXTERNAL), NEWP(0:3,NEXTERNAL)
172
C NOW MAKE SURE THE SHIFTED POINT IS NOT TOO FAR FROM THE ORIGINAL
179
REF2 = REF2 + ABS(P(I,J))
180
REF = REF + ABS(P(I,J)-NEWP(I,J))
184
IF ((REF/REF2).GT.THRS_CLOSE) THEN
185
MP_IS_CLOSE = .FALSE.
186
IF (WARNED.LT.20) THEN
187
WRITE(*,*) 'WARNING:: The improved PS point is too far from
188
$ the original one',(REF/REF2)
195
FUNCTION MP_IS_PHYSICAL(P,WARNED)
201
PARAMETER (NEXTERNAL=4)
203
PARAMETER (NINITIAL=2)
205
PARAMETER (ZERO=0.0E+00_16)
207
PARAMETER (MP__ZERO=ZERO)
209
PARAMETER (ONE=1.0E+00_16)
211
PARAMETER (TWO=2.0E+00_16)
212
REAL*16 THRES_ONSHELL
213
PARAMETER (THRES_ONSHELL=1.0E-02_16)
214
REAL*16 THRES_FOURMOM
215
PARAMETER (THRES_FOURMOM=1.0E-06_16)
219
REAL*16 P(0:3,NEXTERNAL)
220
LOGICAL MP_IS_PHYSICAL
227
REAL*16 MASSES(NEXTERNAL)
231
INCLUDE 'mp_coupl.inc'
242
MP_IS_PHYSICAL = .TRUE.
244
C WE FIRST CHECK THAT THE INPUT PS POINT IS REASONABLY PHYSICAL
245
C FOR THAT WE NEED A REFERENCE SCALE
255
DO J=NINITIAL+1,NEXTERNAL
258
IF ((BUFF/REF).GT.THRES_FOURMOM) THEN
259
IF (WARNED.LT.20) THEN
260
WRITE(*,*) 'ERROR:: Four-momentum conservation is not
261
$ accurate enough, ',(BUFF/REF)
265
MP_IS_PHYSICAL = .FALSE.
268
REF = REF / (ONE*NEXTERNAL)
270
REF=ABS(P(0,I))+ABS(P(1,I))+ABS(P(2,I))+ABS(P(3,I))
271
IF ((SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2
272
$ -MASSES(I)**2))/REF).GT.THRES_ONSHELL) THEN
273
IF (WARNED.LT.20) THEN
274
WRITE(*,*) 'ERROR:: Onshellness of the momentum of
275
$ particle ',I,' of mass ',MASSES(I),' is not accurate
276
$ enough, ', (SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2
277
$ -P(3,I)**2-MASSES(I)**2))/REF)
281
MP_IS_PHYSICAL = .FALSE.
287
SUBROUTINE WRITE_MOM(P)
290
PARAMETER (NEXTERNAL=4)
292
PARAMETER (NINITIAL=2)
293
DOUBLE PRECISION ZERO
294
PARAMETER (ZERO=0.0D0)
295
DOUBLE PRECISION MDOT
302
DOUBLE PRECISION P(0:3,NEXTERNAL),PSUM(0:3)
306
PSUM(I)=PSUM(I)+P(I,J)
308
DO J=NINITIAL+1,NEXTERNAL
309
PSUM(I)=PSUM(I)-P(I,J)
312
WRITE (*,*) ' Phase space point:'
313
WRITE (*,*) ' ---------------------'
314
WRITE (*,*) ' E | px | py | pz | m '
316
WRITE (*,'(1x,5e27.17)') P(0,I),P(1,I),P(2,I),P(3,I),SQRT(ABS(M
317
$ DOT(P(0,I),P(0,I))))
319
WRITE (*,*) ' Four-momentum conservation sum:'
320
WRITE (*,'(1x,4e27.17)') PSUM(0),PSUM(1),PSUM(2),PSUM(3)
321
WRITE (*,*) ' ---------------------'
324
DOUBLE PRECISION FUNCTION MDOT(P1,P2)
326
DOUBLE PRECISION P1(0:3),P2(0:3)
327
MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3)
331
SUBROUTINE MP_WRITE_MOM(P)
334
PARAMETER (NEXTERNAL=4)
336
PARAMETER (NINITIAL=2)
338
PARAMETER (ZERO=0.0E+00_16)
346
REAL*16 P(0:3,NEXTERNAL),PSUM(0:3),DOT
347
DOUBLE PRECISION DP_P(0:3,NEXTERNAL),DP_PSUM(0:3),DP_DOT
352
PSUM(I)=PSUM(I)+P(I,J)
354
DO J=NINITIAL+1,NEXTERNAL
355
PSUM(I)=PSUM(I)-P(I,J)
359
C The GCC4.7 compiler on SLC machines has trouble to write out
360
C quadruple precision variable with the write(*,*) statement. I
361
C therefore perform the cast by hand
369
WRITE (*,*) ' Phase space point:'
370
WRITE (*,*) ' ---------------------'
371
WRITE (*,*) ' E | px | py | pz | m '
373
DOT=SQRT(ABS(MP_MDOT(P(0,I),P(0,I))))
375
WRITE (*,'(1x,5e27.17)') DP_P(0,I),DP_P(1,I),DP_P(2,I),DP_P(3
378
WRITE (*,*) ' Four-momentum conservation sum:'
379
WRITE (*,'(1x,4e27.17)') DP_PSUM(0),DP_PSUM(1),DP_PSUM(2)
381
WRITE (*,*) ' ---------------------'
384
REAL*16 FUNCTION MP_MDOT(P1,P2)
386
REAL*16 P1(0:3),P2(0:3)
387
MP_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3)
391
C Rotate_PS rotates the PS point PS (without modifying it)
392
C stores the result in P and for the quadruple precision
393
C version , it also modifies the global variables
394
C PS and MP_DONE accordingly.
396
SUBROUTINE ROTATE_PS(P_IN,P,ROTATION)
402
PARAMETER (NEXTERNAL=4)
406
DOUBLE PRECISION P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL)
418
C rotation=1 => (xp=z,yp=-x,zp=-y)
419
IF(ROTATION.EQ.1) THEN
424
C rotation=2 => (xp=-z,yp=y,zp=x)
425
ELSEIF(ROTATION.EQ.2) THEN
441
SUBROUTINE MP_ROTATE_PS(P_IN,P,ROTATION)
447
PARAMETER (NEXTERNAL=4)
451
REAL*16 P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL)
461
COMMON/MP_DONE/MP_DONE
468
C rotation=1 => (xp=z,yp=-x,zp=-y)
469
IF(ROTATION.EQ.1) THEN
474
C rotation=2 => (xp=-z,yp=y,zp=x)
475
ELSEIF(ROTATION.EQ.2) THEN
492
C *****************************************************************
493
C Beginning of the routine for restoring precision with V.H. method
494
C *****************************************************************
496
SUBROUTINE MP_ORIG_IMPROVE_PS_POINT_PRECISION(P,ERRCODE,WARNED)
502
PARAMETER (NEXTERNAL=4)
504
PARAMETER (NINITIAL=2)
506
PARAMETER (ZERO=0.0E+00_16)
508
PARAMETER (MP__ZERO=ZERO)
510
PARAMETER (ONE=1.0E+00_16)
512
PARAMETER (TWO=2.0E+00_16)
514
PARAMETER (THRS_TEST=1.0E-15_16)
518
REAL*16 P(0:3,NEXTERNAL)
519
INTEGER ERRCODE, WARNED
529
REAL*16 PT(0:3), NEWP(0:3,NEXTERNAL)
530
REAL*16 BUFF,REF,REF2,DISCR
531
REAL*16 MASSES(NEXTERNAL)
532
REAL*16 SHIFTE(2),SHIFTZ(2)
536
INCLUDE 'mp_coupl.inc'
548
C NOW WE MAKE SURE THAT THE PS POINT CAN BE IMPROVED BY THE
555
IF (NINITIAL.NE.2) ERRCODE = 100
557
IF (ABS(P(1,1)/REF).GT.THRS_TEST.OR.ABS(P(2,1)/REF).GT.THRS_TEST.
558
$ OR.ABS(P(1,2)/REF).GT.THRS_TEST.OR.ABS(P(2,2)/REF).GT.THRS_TEST
561
IF (MASSES(1).NE.ZERO.OR.MASSES(2).NE.ZERO) ERRCODE = 300
564
IF (P(0,I).LT.ZERO) ERRCODE = 400 + I
567
IF (ERRCODE.NE.0) GOTO 100
569
C WE FIRST SHIFT ALL THE FINAL STATE PARTICLES TO MAKE THEM
575
DO I=NINITIAL+1,NEXTERNAL
578
NEWP(3,I)=SIGN(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2
579
$ -MASSES(I)**2)),P(3,I))
583
PT(J)=PT(J)+NEWP(J,I)
587
C WE CHOOSE P1 IN THE ALGORITHM TO ALWAYS BE THE PARTICLE WITH
589
IF (P(3,1).GT.ZERO) THEN
592
ELSEIF (P(3,2).GT.ZERO) THEN
600
C Now we calculate the shift to bring to P1 and P2
602
C ptotC = {ptotE, ptotX, ptotY, ptotZ};
603
C pm1C = {pm1E + sm1E, pm1X, pm1Y, pm1Z + sm1Z};
604
C {pm0E + sm0E, ptotX - pm1X, ptotY - pm1Y, pm0Z + sm0Z};
605
C sol = Solve[{ptotC[[1]] - pm1C[[1]] - pm0C[[1]] == 0,
606
C ptotC[[4]] - pm1C[[4]] - pm0C[[4]] == 0,
607
C pm1C[[1]]^2 - pm1C[[2]]^2 - pm1C[[3]]^2 - pm1C[[4]]^2 == m1M^2,
608
C pm0C[[1]]^2 - pm0C[[2]]^2 - pm0C[[3]]^2 - pm0C[[4]]^2 == m2M^2},
609
C {sm1E, sm1Z, sm0E, sm0Z}] // FullSimplify;
610
C (solC[[1]] /. {m1M -> 0, m2M -> 0} /. {pm1X -> 0, pm1Y -> 0})
613
DISCR = -PT(0)**2 + PT(1)**2 + PT(2)**2 + PT(3)**2
614
IF (DISCR.LT.ZERO) DISCR = -DISCR
616
SHIFTE(1) = (PT(0)*(-TWO*P(0,P1)*PT(0) + PT(0)**2 + PT(1)**2
617
$ + PT(2)**2) + (TWO*P(0,P1) - PT(0))*PT(3)**2 + PT(3)*DISCR)
618
$ /(TWO*(PT(0) - PT(3))*(PT(0) + PT(3)))
619
SHIFTE(2) = -(PT(0)*(TWO*P(0,P2)*PT(0) - PT(0)**2 + PT(1)**2
620
$ + PT(2)**2) + (-TWO*P(0,P2) + PT(0))*PT(3)**2 + PT(3)*DISCR)
621
$ /(TWO*(PT(0) - PT(3))*(PT(0) + PT(3)))
622
SHIFTZ(1) = (-TWO*P(3,P1)*(PT(0)**2 - PT(3)**2) + PT(3)*(PT(0)*
623
$ *2 + PT(1)**2 + PT(2)**2 - PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0)
625
SHIFTZ(2) = -(TWO*P(3,P2)*(PT(0)**2 - PT(3)**2) + PT(3)*(
626
$ -PT(0)**2 + PT(1)**2 + PT(2)**2 + PT(3)**2) + PT(0)*DISCR)/(TWO
627
$ *(PT(0)**2 - PT(3)**2))
628
NEWP(0,P1) = P(0,P1)+SHIFTE(1)
629
NEWP(3,P1) = P(3,P1)+SHIFTZ(1)
630
NEWP(0,P2) = P(0,P2)+SHIFTE(2)
631
NEWP(3,P2) = P(3,P2)+SHIFTZ(2)
636
DO I=NINITIAL+1,NEXTERNAL
643
IF (.NOT.MP_IS_CLOSE(P,NEWP,WARNED)) THEN
658
C *****************************************************************
659
C Beginning of the routine for restoring precision a la PSMC
660
C *****************************************************************
662
SUBROUTINE MP_PSMC_IMPROVE_PS_POINT_PRECISION(P,ERRCODE,WARNED)
668
PARAMETER (NEXTERNAL=4)
670
PARAMETER (NINITIAL=2)
672
PARAMETER (ZERO=0.0E+00_16)
674
PARAMETER (MP__ZERO=ZERO)
676
PARAMETER (ONE=1.0E+00_16)
678
PARAMETER (TWO=2.0E+00_16)
679
REAL*16 CONSISTENCY_THRES
680
PARAMETER (CONSISTENCY_THRES=1.0E-25_16)
683
PARAMETER (NAPPROXZEROS=3)
688
REAL*16 P(0:3,NEXTERNAL)
689
INTEGER ERRCODE,ERROR,WARNED
698
REAL*16 NEWP(0:3,NEXTERNAL), PBUFF(0:3)
699
REAL*16 BUFF, BUFF2, XSCALE, APPROX_ZEROS(NAPPROXZEROS)
700
REAL*16 MASSES(NEXTERNAL)
704
INCLUDE 'mp_coupl.inc'
718
C Define the seeds which should be tried
719
APPROX_ZEROS(1)=1.0E+00_16
720
APPROX_ZEROS(2)=1.1E+00_16
721
APPROX_ZEROS(3)=0.9E+00_16
723
C Start by copying the momenta
730
C First make sur that the space like momentum is exactly conserved
736
PBUFF(J)=PBUFF(J)+NEWP(J,I)
739
DO I=NINITIAL+1,NEXTERNAL-1
741
PBUFF(J)=PBUFF(J)-NEWP(J,I)
745
NEWP(J,NEXTERNAL)=PBUFF(J)
748
C Now find the 'x' rescaling factor
750
CALL FINDX(NEWP,APPROX_ZEROS(I),XSCALE,ERROR)
754
ERRCODE=ERRCODE+(10**(I-1))*ERROR
757
IF (WARNED.LT.20) THEN
758
WRITE(*,*) 'WARNING:: Could not find the proper rescaling
759
$ factor x. Restoring precision ala PSMC will therefore not be
763
IF (ERRCODE.LT.1000) THEN
770
C Apply the rescaling
773
NEWP(J,I)=NEWP(J,I)*XSCALE
777
C Now restore exact onshellness of the particles.
781
BUFF=BUFF+NEWP(J,I)**2
791
BUFF2=BUFF2+NEWP(0,I)
793
DO I=NINITIAL+1,NEXTERNAL
795
BUFF2=BUFF2+NEWP(0,I)
797
IF ((ABS(BUFF)/BUFF2).GT.CONSISTENCY_THRES) THEN
798
IF (WARNED.LT.20) THEN
799
WRITE(*,*) 'WARNING:: The consistency check in the a la PSMC
800
$ precision restoring algorithm failed. The result will
801
$ therefore not be used.'
808
IF (.NOT.MP_IS_CLOSE(P,NEWP,WARNED)) THEN
824
SUBROUTINE FINDX(P,SEED,XSCALE,ERROR)
830
PARAMETER (NEXTERNAL=4)
832
PARAMETER (NINITIAL=2)
834
PARAMETER (ZERO=0.0E+00_16)
836
PARAMETER (MP__ZERO=ZERO)
838
PARAMETER (ONE=1.0E+00_16)
840
PARAMETER (TWO=2.0E+00_16)
841
INTEGER MAXITERATIONS
842
PARAMETER (MAXITERATIONS=8)
844
PARAMETER (CONVERGED=1.0E-26_16)
848
REAL*16 P(0:3,NEXTERNAL),SEED,XSCALE
854
REAL*16 PVECSQ(NEXTERNAL)
855
REAL*16 XN, XNP1,FVAL,DVAL
867
PVECSQ(I)=P(1,I)**2+P(2,I)**2+P(3,I)**2
871
CALL FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL)
876
CALL FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL)
882
IF((ABS(((XNP1-XN)*TWO)/(XNP1+XN))).LT.CONVERGED) THEN
892
C For good measure, we iterate one last time
893
CALL FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL)
898
CALL FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL)
904
XSCALE=XN-(FVAL/DVAL)
910
SUBROUTINE FUNCT(PVECSQ,X,DERIVATIVE,ERROR,RES)
916
PARAMETER (NEXTERNAL=4)
918
PARAMETER (NINITIAL=2)
920
PARAMETER (ZERO=0.0E+00_16)
922
PARAMETER (MP__ZERO=ZERO)
924
PARAMETER (ONE=1.0E+00_16)
926
PARAMETER (TWO=2.0E+00_16)
930
REAL*16 PVECSQ(NEXTERNAL),X,RES
938
REAL*16 MASSES(NEXTERNAL)
942
INCLUDE 'mp_coupl.inc'
958
IF (I.LE.NINITIAL) THEN
963
BUFF=MASSES(I)**2+PVECSQ(I)*X**2
964
IF (BUFF.LT.ZERO) THEN
970
RES=RES + FACTOR*((X*PVECSQ(I))/SQRT(BUFF))
972
RES=RES + FACTOR*SQRT(BUFF)