1
SUBROUTINE ML5_0_IMPROVE_PS_POINT_PRECISION(P)
7
PARAMETER (NEXTERNAL=5)
11
DOUBLE PRECISION P(0:3,NEXTERNAL)
12
REAL*16 QP_P(0:3,NEXTERNAL)
28
CALL ML5_0_MP_IMPROVE_PS_POINT_PRECISION(QP_P)
39
SUBROUTINE ML5_0_MP_IMPROVE_PS_POINT_PRECISION(P)
45
PARAMETER (NEXTERNAL=5)
49
REAL*16 P(0:3,NEXTERNAL)
54
INTEGER ERRCODE,ERRCODETMP
55
REAL*16 NEWP(0:3,NEXTERNAL)
59
LOGICAL ML5_0_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.ML5_0_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 ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE
103
ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN
104
CALL ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE
107
IF (ERRCODE.NE.0) THEN
108
IF (WARNED.LT.20) THEN
109
WRITE(*,*) 'INFO:: Attempting to rescue the precision'
110
$ //' improvement with an alternative method.'
113
IF (IMPROVEPSPOINT.EQ.1) THEN
114
CALL ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP
115
$ ,ERRCODETMP,WARNED)
116
ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN
117
CALL ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP
118
$ ,ERRCODETMP,WARNED)
120
IF (ERRCODETMP.NE.0) GOTO 100
123
C Report to the user or update the PS point.
127
IF (WARNED.LT.20) THEN
128
WRITE(*,*) 'WARNING:: This PS point could not be improved.'
129
$ //' Error code = ',ERRCODE,ERRCODETMP
130
CALL ML5_0_MP_WRITE_MOM(P)
142
IF (WARNED.GE.20.AND..NOT.TOLD_SUPPRESS) THEN
143
WRITE(*,*) 'INFO:: Further warnings from the improve_ps'
144
$ //' routine will now be supressed.'
151
FUNCTION ML5_0_MP_IS_CLOSE(P,NEWP,WARNED)
157
PARAMETER (NEXTERNAL=5)
159
PARAMETER (ZERO=0.0E+00_16)
161
PARAMETER (THRS_CLOSE=1.0E-02_16)
165
REAL*16 P(0:3,NEXTERNAL), NEWP(0:3,NEXTERNAL)
166
LOGICAL ML5_0_MP_IS_CLOSE
173
DOUBLE PRECISION BUFFDP
175
C NOW MAKE SURE THE SHIFTED POINT IS NOT TOO FAR FROM THE ORIGINAL
177
ML5_0_MP_IS_CLOSE = .TRUE.
182
REF2 = REF2 + ABS(P(I,J))
183
REF = REF + ABS(P(I,J)-NEWP(I,J))
187
IF ((REF/REF2).GT.THRS_CLOSE) THEN
188
ML5_0_MP_IS_CLOSE = .FALSE.
189
IF (WARNED.LT.20) THEN
191
WRITE(*,*) 'WARNING:: The improved PS point is too far from'
192
$ //' the original one',BUFFDP
199
FUNCTION ML5_0_MP_IS_PHYSICAL(P,WARNED)
205
PARAMETER (NEXTERNAL=5)
207
PARAMETER (NINITIAL=2)
209
PARAMETER (ZERO=0.0E+00_16)
211
PARAMETER (MP__ZERO=ZERO)
213
PARAMETER (ONE=1.0E+00_16)
215
PARAMETER (TWO=2.0E+00_16)
216
REAL*16 THRES_ONSHELL
217
PARAMETER (THRES_ONSHELL=1.0E-02_16)
218
REAL*16 THRES_FOURMOM
219
PARAMETER (THRES_FOURMOM=1.0E-06_16)
223
REAL*16 P(0:3,NEXTERNAL)
224
LOGICAL ML5_0_MP_IS_PHYSICAL
231
REAL*16 MASSES(NEXTERNAL)
232
DOUBLE PRECISION BUFFDPA,BUFFDPB
236
INCLUDE 'mp_coupl.inc'
248
ML5_0_MP_IS_PHYSICAL = .TRUE.
250
C WE FIRST CHECK THAT THE INPUT PS POINT IS REASONABLY PHYSICAL
251
C FOR THAT WE NEED A REFERENCE SCALE
261
DO J=NINITIAL+1,NEXTERNAL
264
IF ((BUFF/REF).GT.THRES_FOURMOM) THEN
265
IF (WARNED.LT.20) THEN
267
WRITE(*,*) 'ERROR:: Four-momentum conservation is not'
268
$ //' accurate enough, ',BUFFDPA
269
CALL ML5_0_MP_WRITE_MOM(P)
272
ML5_0_MP_IS_PHYSICAL = .FALSE.
275
REF = REF / (ONE*NEXTERNAL)
277
REF=ABS(P(0,I))+ABS(P(1,I))+ABS(P(2,I))+ABS(P(3,I))
278
IF ((SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2-MASSES(I)
279
$ **2))/REF).GT.THRES_ONSHELL) THEN
280
IF (WARNED.LT.20) THEN
282
BUFFDPB=(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2
283
$ -MASSES(I)**2))/REF)
284
WRITE(*,*) 'ERROR:: Onshellness of the momentum of'
285
$ //' particle ',I,' of mass ',BUFFDPA,' is not accurate'
286
$ //' enough, ',BUFFDPB
287
CALL ML5_0_MP_WRITE_MOM(P)
290
ML5_0_MP_IS_PHYSICAL = .FALSE.
296
SUBROUTINE ML5_0_WRITE_MOM(P)
299
PARAMETER (NEXTERNAL=5)
301
PARAMETER (NINITIAL=2)
302
DOUBLE PRECISION ZERO
303
PARAMETER (ZERO=0.0D0)
304
DOUBLE PRECISION ML5_0_MDOT
311
DOUBLE PRECISION P(0:3,NEXTERNAL),PSUM(0:3)
315
PSUM(I)=PSUM(I)+P(I,J)
317
DO J=NINITIAL+1,NEXTERNAL
318
PSUM(I)=PSUM(I)-P(I,J)
321
WRITE (*,*) ' Phase space point:'
322
WRITE (*,*) ' ---------------------'
323
WRITE (*,*) ' E | px | py | pz | m '
325
WRITE (*,'(1x,5e27.17)') P(0,I),P(1,I),P(2,I),P(3,I)
326
$ ,SQRT(ABS(ML5_0_MDOT(P(0,I),P(0,I))))
328
WRITE (*,*) ' Four-momentum conservation sum:'
329
WRITE (*,'(1x,4e27.17)') PSUM(0),PSUM(1),PSUM(2),PSUM(3)
330
WRITE (*,*) ' ---------------------'
333
DOUBLE PRECISION FUNCTION ML5_0_MDOT(P1,P2)
335
DOUBLE PRECISION P1(0:3),P2(0:3)
336
ML5_0_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3)
340
SUBROUTINE ML5_0_MP_WRITE_MOM(P)
343
PARAMETER (NEXTERNAL=5)
345
PARAMETER (NINITIAL=2)
347
PARAMETER (ZERO=0.0E+00_16)
348
REAL*16 ML5_0_MP_MDOT
355
REAL*16 P(0:3,NEXTERNAL),PSUM(0:3),DOT
356
DOUBLE PRECISION DP_P(0:3,NEXTERNAL),DP_PSUM(0:3),DP_DOT
361
PSUM(I)=PSUM(I)+P(I,J)
363
DO J=NINITIAL+1,NEXTERNAL
364
PSUM(I)=PSUM(I)-P(I,J)
368
C The GCC4.7 compiler on SLC machines has trouble to write out
369
C quadruple precision variable with the write(*,*) statement. I
370
C therefore perform the cast by hand
378
WRITE (*,*) ' Phase space point:'
379
WRITE (*,*) ' ---------------------'
380
WRITE (*,*) ' E | px | py | pz | m '
382
DOT=SQRT(ABS(ML5_0_MP_MDOT(P(0,I),P(0,I))))
384
WRITE (*,'(1x,5e27.17)') DP_P(0,I),DP_P(1,I),DP_P(2,I),DP_P(3
387
WRITE (*,*) ' Four-momentum conservation sum:'
388
WRITE (*,'(1x,4e27.17)') DP_PSUM(0),DP_PSUM(1),DP_PSUM(2)
390
WRITE (*,*) ' ---------------------'
393
REAL*16 FUNCTION ML5_0_MP_MDOT(P1,P2)
395
REAL*16 P1(0:3),P2(0:3)
396
ML5_0_MP_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3)
400
C Rotate_PS rotates the PS point PS (without modifying it)
401
C stores the result in P and for the quadruple precision
402
C version , it also modifies the global variables
403
C PS and MP_DONE accordingly.
405
SUBROUTINE ML5_0_ROTATE_PS(P_IN,P,ROTATION)
411
PARAMETER (NEXTERNAL=5)
415
DOUBLE PRECISION P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL)
427
C rotation=1 => (xp=z,yp=-x,zp=-y)
428
IF(ROTATION.EQ.1) THEN
433
C rotation=2 => (xp=-z,yp=y,zp=x)
434
ELSEIF(ROTATION.EQ.2) THEN
450
SUBROUTINE ML5_0_MP_ROTATE_PS(P_IN,P,ROTATION)
456
PARAMETER (NEXTERNAL=5)
460
REAL*16 P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL)
470
COMMON/ML5_0_MP_DONE/MP_DONE
477
C rotation=1 => (xp=z,yp=-x,zp=-y)
478
IF(ROTATION.EQ.1) THEN
483
C rotation=2 => (xp=-z,yp=y,zp=x)
484
ELSEIF(ROTATION.EQ.2) THEN
501
C *****************************************************************
502
C Beginning of the routine for restoring precision with V.H. method
503
C *****************************************************************
505
SUBROUTINE ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(P,ERRCODE
512
PARAMETER (NEXTERNAL=5)
514
PARAMETER (NINITIAL=2)
516
PARAMETER (ZERO=0.0E+00_16)
518
PARAMETER (MP__ZERO=ZERO)
520
PARAMETER (ONE=1.0E+00_16)
522
PARAMETER (TWO=2.0E+00_16)
524
PARAMETER (THRS_TEST=1.0E-15_16)
528
REAL*16 P(0:3,NEXTERNAL)
529
INTEGER ERRCODE, WARNED
533
LOGICAL ML5_0_MP_IS_CLOSE
539
REAL*16 PT(0:3), NEWP(0:3,NEXTERNAL)
540
REAL*16 BUFF,REF,REF2,DISCR
541
REAL*16 MASSES(NEXTERNAL)
542
REAL*16 SHIFTE(2),SHIFTZ(2)
546
INCLUDE 'mp_coupl.inc'
559
C NOW WE MAKE SURE THAT THE PS POINT CAN BE IMPROVED BY THE
566
IF (NINITIAL.NE.2) ERRCODE = 100
568
IF (ABS(P(1,1)/REF).GT.THRS_TEST.OR.ABS(P(2,1)/REF)
569
$ .GT.THRS_TEST.OR.ABS(P(1,2)/REF).GT.THRS_TEST.OR.ABS(P(2,2)/REF)
570
$ .GT.THRS_TEST) ERRCODE = 200
572
IF (MASSES(1).NE.ZERO.OR.MASSES(2).NE.ZERO) ERRCODE = 300
575
IF (P(0,I).LT.ZERO) ERRCODE = 400 + I
578
IF (ERRCODE.NE.0) GOTO 100
580
C WE FIRST SHIFT ALL THE FINAL STATE PARTICLES TO MAKE THEM
586
DO I=NINITIAL+1,NEXTERNAL
589
NEWP(3,I)=SIGN(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2
590
$ -MASSES(I)**2)),P(3,I))
594
PT(J)=PT(J)+NEWP(J,I)
598
C WE CHOOSE P1 IN THE ALGORITHM TO ALWAYS BE THE PARTICLE WITH
600
IF (P(3,1).GT.ZERO) THEN
603
ELSEIF (P(3,2).GT.ZERO) THEN
611
C Now we calculate the shift to bring to P1 and P2
613
C ptotC = {ptotE, ptotX, ptotY, ptotZ};
614
C pm1C = {pm1E + sm1E, pm1X, pm1Y, pm1Z + sm1Z};
615
C {pm0E + sm0E, ptotX - pm1X, ptotY - pm1Y, pm0Z + sm0Z};
616
C sol = Solve[{ptotC[[1]] - pm1C[[1]] - pm0C[[1]] == 0,
617
C ptotC[[4]] - pm1C[[4]] - pm0C[[4]] == 0,
618
C pm1C[[1]]^2 - pm1C[[2]]^2 - pm1C[[3]]^2 - pm1C[[4]]^2 == m1M^2,
619
C pm0C[[1]]^2 - pm0C[[2]]^2 - pm0C[[3]]^2 - pm0C[[4]]^2 == m2M^2},
620
C {sm1E, sm1Z, sm0E, sm0Z}] // FullSimplify;
621
C (solC[[1]] /. {m1M -> 0, m2M -> 0} /. {pm1X -> 0, pm1Y -> 0})
624
DISCR = -PT(0)**2 + PT(1)**2 + PT(2)**2 + PT(3)**2
625
IF (DISCR.LT.ZERO) DISCR = -DISCR
627
SHIFTE(1) = (PT(0)*(-TWO*P(0,P1)*PT(0) + PT(0)**2 + PT(1)**2 +
628
$ PT(2)**2) + (TWO*P(0,P1) - PT(0))*PT(3)**2 + PT(3)*DISCR)/(TWO
629
$ *(PT(0) - PT(3))*(PT(0) + PT(3)))
630
SHIFTE(2) = -(PT(0)*(TWO*P(0,P2)*PT(0) - PT(0)**2 + PT(1)**2 +
631
$ PT(2)**2) + (-TWO*P(0,P2) + PT(0))*PT(3)**2 + PT(3)*DISCR)
632
$ /(TWO*(PT(0) - PT(3))*(PT(0) + PT(3)))
633
SHIFTZ(1) = (-TWO*P(3,P1)*(PT(0)**2 - PT(3)**2) + PT(3)*(PT(0)*
634
$ *2 + PT(1)**2 + PT(2)**2 - PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0)
636
SHIFTZ(2) = -(TWO*P(3,P2)*(PT(0)**2 - PT(3)**2) + PT(3)*(-PT(0)*
637
$ *2 + PT(1)**2 + PT(2)**2 + PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0)
639
NEWP(0,P1) = P(0,P1)+SHIFTE(1)
640
NEWP(3,P1) = P(3,P1)+SHIFTZ(1)
641
NEWP(0,P2) = P(0,P2)+SHIFTE(2)
642
NEWP(3,P2) = P(3,P2)+SHIFTZ(2)
647
DO I=NINITIAL+1,NEXTERNAL
654
IF (.NOT.ML5_0_MP_IS_CLOSE(P,NEWP,WARNED)) THEN
669
C *****************************************************************
670
C Beginning of the routine for restoring precision a la PSMC
671
C *****************************************************************
673
SUBROUTINE ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(P,ERRCODE
680
PARAMETER (NEXTERNAL=5)
682
PARAMETER (NINITIAL=2)
684
PARAMETER (ZERO=0.0E+00_16)
686
PARAMETER (MP__ZERO=ZERO)
688
PARAMETER (ONE=1.0E+00_16)
690
PARAMETER (TWO=2.0E+00_16)
691
REAL*16 CONSISTENCY_THRES
692
PARAMETER (CONSISTENCY_THRES=1.0E-25_16)
695
PARAMETER (NAPPROXZEROS=3)
700
REAL*16 P(0:3,NEXTERNAL)
701
INTEGER ERRCODE,ERROR,WARNED
705
LOGICAL ML5_0_MP_IS_CLOSE
710
REAL*16 NEWP(0:3,NEXTERNAL), PBUFF(0:3)
711
REAL*16 BUFF, BUFF2, XSCALE, APPROX_ZEROS(NAPPROXZEROS)
712
REAL*16 MASSES(NEXTERNAL)
716
INCLUDE 'mp_coupl.inc'
731
C Define the seeds which should be tried
732
APPROX_ZEROS(1)=1.0E+00_16
733
APPROX_ZEROS(2)=1.1E+00_16
734
APPROX_ZEROS(3)=0.9E+00_16
736
C Start by copying the momenta
743
C First make sur that the space like momentum is exactly conserved
749
PBUFF(J)=PBUFF(J)+NEWP(J,I)
752
DO I=NINITIAL+1,NEXTERNAL-1
754
PBUFF(J)=PBUFF(J)-NEWP(J,I)
758
NEWP(J,NEXTERNAL)=PBUFF(J)
761
C Now find the 'x' rescaling factor
763
CALL ML5_0_FINDX(NEWP,APPROX_ZEROS(I),XSCALE,ERROR)
767
ERRCODE=ERRCODE+(10**(I-1))*ERROR
770
IF (WARNED.LT.20) THEN
771
WRITE(*,*) 'WARNING:: Could not find the proper rescaling'
772
$ //' factor x. Restoring precision ala PSMC will therefore not'
776
IF (ERRCODE.LT.1000) THEN
783
C Apply the rescaling
786
NEWP(J,I)=NEWP(J,I)*XSCALE
790
C Now restore exact onshellness of the particles.
794
BUFF=BUFF+NEWP(J,I)**2
804
BUFF2=BUFF2+NEWP(0,I)
806
DO I=NINITIAL+1,NEXTERNAL
808
BUFF2=BUFF2+NEWP(0,I)
810
IF ((ABS(BUFF)/BUFF2).GT.CONSISTENCY_THRES) THEN
811
IF (WARNED.LT.20) THEN
812
WRITE(*,*) 'WARNING:: The consistency check in the a la PSMC'
813
$ //' precision restoring algorithm failed. The result will'
814
$ //' therefore not be used.'
821
IF (.NOT.ML5_0_MP_IS_CLOSE(P,NEWP,WARNED)) THEN
837
SUBROUTINE ML5_0_FINDX(P,SEED,XSCALE,ERROR)
843
PARAMETER (NEXTERNAL=5)
845
PARAMETER (NINITIAL=2)
847
PARAMETER (ZERO=0.0E+00_16)
849
PARAMETER (MP__ZERO=ZERO)
851
PARAMETER (ONE=1.0E+00_16)
853
PARAMETER (TWO=2.0E+00_16)
854
INTEGER MAXITERATIONS
855
PARAMETER (MAXITERATIONS=8)
857
PARAMETER (CONVERGED=1.0E-26_16)
861
REAL*16 P(0:3,NEXTERNAL),SEED,XSCALE
867
REAL*16 PVECSQ(NEXTERNAL)
868
REAL*16 XN, XNP1,FVAL,DVAL
880
PVECSQ(I)=P(1,I)**2+P(2,I)**2+P(3,I)**2
884
CALL ML5_0_FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL)
889
CALL ML5_0_FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL)
895
IF((ABS(((XNP1-XN)*TWO)/(XNP1+XN))).LT.CONVERGED) THEN
905
C For good measure, we iterate one last time
906
CALL ML5_0_FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL)
911
CALL ML5_0_FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL)
917
XSCALE=XN-(FVAL/DVAL)
923
SUBROUTINE ML5_0_FUNCT(PVECSQ,X,DERIVATIVE,ERROR,RES)
929
PARAMETER (NEXTERNAL=5)
931
PARAMETER (NINITIAL=2)
933
PARAMETER (ZERO=0.0E+00_16)
935
PARAMETER (MP__ZERO=ZERO)
937
PARAMETER (ONE=1.0E+00_16)
939
PARAMETER (TWO=2.0E+00_16)
943
REAL*16 PVECSQ(NEXTERNAL),X,RES
951
REAL*16 MASSES(NEXTERNAL)
955
INCLUDE 'mp_coupl.inc'
972
IF (I.LE.NINITIAL) THEN
977
BUFF=MASSES(I)**2+PVECSQ(I)*X**2
978
IF (BUFF.LT.ZERO) THEN
984
RES=RES + FACTOR*((X*PVECSQ(I))/SQRT(BUFF))
986
RES=RES + FACTOR*SQRT(BUFF)