1
SUBROUTINE IMPROVE_PS_POINT_PRECISION(P)
7
PARAMETER (NEXTERNAL=3)
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=3)
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=3)
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)
171
DOUBLE PRECISION BUFFDP
173
C NOW MAKE SURE THE SHIFTED POINT IS NOT TOO FAR FROM THE ORIGINAL
180
REF2 = REF2 + ABS(P(I,J))
181
REF = REF + ABS(P(I,J)-NEWP(I,J))
185
IF ((REF/REF2).GT.THRS_CLOSE) THEN
186
MP_IS_CLOSE = .FALSE.
187
IF (WARNED.LT.20) THEN
189
WRITE(*,*) 'WARNING:: The improved PS point is too far from'
190
$ //' the original one',BUFFDP
197
FUNCTION MP_IS_PHYSICAL(P,WARNED)
203
PARAMETER (NEXTERNAL=3)
205
PARAMETER (NINITIAL=2)
207
PARAMETER (ZERO=0.0E+00_16)
209
PARAMETER (MP__ZERO=ZERO)
211
PARAMETER (ONE=1.0E+00_16)
213
PARAMETER (TWO=2.0E+00_16)
214
REAL*16 THRES_ONSHELL
215
PARAMETER (THRES_ONSHELL=1.0E-02_16)
216
REAL*16 THRES_FOURMOM
217
PARAMETER (THRES_FOURMOM=1.0E-06_16)
221
REAL*16 P(0:3,NEXTERNAL)
222
LOGICAL MP_IS_PHYSICAL
229
REAL*16 MASSES(NEXTERNAL)
230
DOUBLE PRECISION BUFFDPA,BUFFDPB
234
INCLUDE 'mp_coupl.inc'
244
MP_IS_PHYSICAL = .TRUE.
246
C WE FIRST CHECK THAT THE INPUT PS POINT IS REASONABLY PHYSICAL
247
C FOR THAT WE NEED A REFERENCE SCALE
257
DO J=NINITIAL+1,NEXTERNAL
260
IF ((BUFF/REF).GT.THRES_FOURMOM) THEN
261
IF (WARNED.LT.20) THEN
263
WRITE(*,*) 'ERROR:: Four-momentum conservation is not'
264
$ //' accurate enough, ',BUFFDPA
268
MP_IS_PHYSICAL = .FALSE.
271
REF = REF / (ONE*NEXTERNAL)
273
REF=ABS(P(0,I))+ABS(P(1,I))+ABS(P(2,I))+ABS(P(3,I))
274
IF ((SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2-MASSES(I)
275
$ **2))/REF).GT.THRES_ONSHELL) THEN
276
IF (WARNED.LT.20) THEN
278
BUFFDPB=(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2
279
$ -MASSES(I)**2))/REF)
280
WRITE(*,*) 'ERROR:: Onshellness of the momentum of'
281
$ //' particle ',I,' of mass ',BUFFDPA,' is not accurate'
282
$ //' enough, ',BUFFDPB
286
MP_IS_PHYSICAL = .FALSE.
292
SUBROUTINE WRITE_MOM(P)
295
PARAMETER (NEXTERNAL=3)
297
PARAMETER (NINITIAL=2)
298
DOUBLE PRECISION ZERO
299
PARAMETER (ZERO=0.0D0)
300
DOUBLE PRECISION MDOT
307
DOUBLE PRECISION P(0:3,NEXTERNAL),PSUM(0:3)
311
PSUM(I)=PSUM(I)+P(I,J)
313
DO J=NINITIAL+1,NEXTERNAL
314
PSUM(I)=PSUM(I)-P(I,J)
317
WRITE (*,*) ' Phase space point:'
318
WRITE (*,*) ' ---------------------'
319
WRITE (*,*) ' E | px | py | pz | m '
321
WRITE (*,'(1x,5e27.17)') P(0,I),P(1,I),P(2,I),P(3,I)
322
$ ,SQRT(ABS(MDOT(P(0,I),P(0,I))))
324
WRITE (*,*) ' Four-momentum conservation sum:'
325
WRITE (*,'(1x,4e27.17)') PSUM(0),PSUM(1),PSUM(2),PSUM(3)
326
WRITE (*,*) ' ---------------------'
329
DOUBLE PRECISION FUNCTION MDOT(P1,P2)
331
DOUBLE PRECISION P1(0:3),P2(0:3)
332
MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3)
336
SUBROUTINE MP_WRITE_MOM(P)
339
PARAMETER (NEXTERNAL=3)
341
PARAMETER (NINITIAL=2)
343
PARAMETER (ZERO=0.0E+00_16)
351
REAL*16 P(0:3,NEXTERNAL),PSUM(0:3),DOT
352
DOUBLE PRECISION DP_P(0:3,NEXTERNAL),DP_PSUM(0:3),DP_DOT
357
PSUM(I)=PSUM(I)+P(I,J)
359
DO J=NINITIAL+1,NEXTERNAL
360
PSUM(I)=PSUM(I)-P(I,J)
364
C The GCC4.7 compiler on SLC machines has trouble to write out
365
C quadruple precision variable with the write(*,*) statement. I
366
C therefore perform the cast by hand
374
WRITE (*,*) ' Phase space point:'
375
WRITE (*,*) ' ---------------------'
376
WRITE (*,*) ' E | px | py | pz | m '
378
DOT=SQRT(ABS(MP_MDOT(P(0,I),P(0,I))))
380
WRITE (*,'(1x,5e27.17)') DP_P(0,I),DP_P(1,I),DP_P(2,I),DP_P(3
383
WRITE (*,*) ' Four-momentum conservation sum:'
384
WRITE (*,'(1x,4e27.17)') DP_PSUM(0),DP_PSUM(1),DP_PSUM(2)
386
WRITE (*,*) ' ---------------------'
389
REAL*16 FUNCTION MP_MDOT(P1,P2)
391
REAL*16 P1(0:3),P2(0:3)
392
MP_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3)
396
C Rotate_PS rotates the PS point PS (without modifying it)
397
C stores the result in P and for the quadruple precision
398
C version , it also modifies the global variables
399
C PS and MP_DONE accordingly.
401
SUBROUTINE ROTATE_PS(P_IN,P,ROTATION)
407
PARAMETER (NEXTERNAL=3)
411
DOUBLE PRECISION P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL)
423
C rotation=1 => (xp=z,yp=-x,zp=-y)
424
IF(ROTATION.EQ.1) THEN
429
C rotation=2 => (xp=-z,yp=y,zp=x)
430
ELSEIF(ROTATION.EQ.2) THEN
446
SUBROUTINE MP_ROTATE_PS(P_IN,P,ROTATION)
452
PARAMETER (NEXTERNAL=3)
456
REAL*16 P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL)
466
COMMON/MP_DONE/MP_DONE
473
C rotation=1 => (xp=z,yp=-x,zp=-y)
474
IF(ROTATION.EQ.1) THEN
479
C rotation=2 => (xp=-z,yp=y,zp=x)
480
ELSEIF(ROTATION.EQ.2) THEN
497
C *****************************************************************
498
C Beginning of the routine for restoring precision with V.H. method
499
C *****************************************************************
501
SUBROUTINE MP_ORIG_IMPROVE_PS_POINT_PRECISION(P,ERRCODE,WARNED)
507
PARAMETER (NEXTERNAL=3)
509
PARAMETER (NINITIAL=2)
511
PARAMETER (ZERO=0.0E+00_16)
513
PARAMETER (MP__ZERO=ZERO)
515
PARAMETER (ONE=1.0E+00_16)
517
PARAMETER (TWO=2.0E+00_16)
519
PARAMETER (THRS_TEST=1.0E-15_16)
523
REAL*16 P(0:3,NEXTERNAL)
524
INTEGER ERRCODE, WARNED
534
REAL*16 PT(0:3), NEWP(0:3,NEXTERNAL)
535
REAL*16 BUFF,REF,REF2,DISCR
536
REAL*16 MASSES(NEXTERNAL)
537
REAL*16 SHIFTE(2),SHIFTZ(2)
541
INCLUDE 'mp_coupl.inc'
552
C NOW WE MAKE SURE THAT THE PS POINT CAN BE IMPROVED BY THE
559
IF (NINITIAL.NE.2) ERRCODE = 100
561
IF (ABS(P(1,1)/REF).GT.THRS_TEST.OR.ABS(P(2,1)/REF)
562
$ .GT.THRS_TEST.OR.ABS(P(1,2)/REF).GT.THRS_TEST.OR.ABS(P(2,2)/REF)
563
$ .GT.THRS_TEST) ERRCODE = 200
565
IF (MASSES(1).NE.ZERO.OR.MASSES(2).NE.ZERO) ERRCODE = 300
568
IF (P(0,I).LT.ZERO) ERRCODE = 400 + I
571
IF (ERRCODE.NE.0) GOTO 100
573
C WE FIRST SHIFT ALL THE FINAL STATE PARTICLES TO MAKE THEM
579
DO I=NINITIAL+1,NEXTERNAL
582
NEWP(3,I)=SIGN(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2
583
$ -MASSES(I)**2)),P(3,I))
587
PT(J)=PT(J)+NEWP(J,I)
591
C WE CHOOSE P1 IN THE ALGORITHM TO ALWAYS BE THE PARTICLE WITH
593
IF (P(3,1).GT.ZERO) THEN
596
ELSEIF (P(3,2).GT.ZERO) THEN
604
C Now we calculate the shift to bring to P1 and P2
606
C ptotC = {ptotE, ptotX, ptotY, ptotZ};
607
C pm1C = {pm1E + sm1E, pm1X, pm1Y, pm1Z + sm1Z};
608
C {pm0E + sm0E, ptotX - pm1X, ptotY - pm1Y, pm0Z + sm0Z};
609
C sol = Solve[{ptotC[[1]] - pm1C[[1]] - pm0C[[1]] == 0,
610
C ptotC[[4]] - pm1C[[4]] - pm0C[[4]] == 0,
611
C pm1C[[1]]^2 - pm1C[[2]]^2 - pm1C[[3]]^2 - pm1C[[4]]^2 == m1M^2,
612
C pm0C[[1]]^2 - pm0C[[2]]^2 - pm0C[[3]]^2 - pm0C[[4]]^2 == m2M^2},
613
C {sm1E, sm1Z, sm0E, sm0Z}] // FullSimplify;
614
C (solC[[1]] /. {m1M -> 0, m2M -> 0} /. {pm1X -> 0, pm1Y -> 0})
617
DISCR = -PT(0)**2 + PT(1)**2 + PT(2)**2 + PT(3)**2
618
IF (DISCR.LT.ZERO) DISCR = -DISCR
620
SHIFTE(1) = (PT(0)*(-TWO*P(0,P1)*PT(0) + PT(0)**2 + PT(1)**2 +
621
$ PT(2)**2) + (TWO*P(0,P1) - PT(0))*PT(3)**2 + PT(3)*DISCR)/(TWO
622
$ *(PT(0) - PT(3))*(PT(0) + PT(3)))
623
SHIFTE(2) = -(PT(0)*(TWO*P(0,P2)*PT(0) - PT(0)**2 + PT(1)**2 +
624
$ PT(2)**2) + (-TWO*P(0,P2) + PT(0))*PT(3)**2 + PT(3)*DISCR)
625
$ /(TWO*(PT(0) - PT(3))*(PT(0) + PT(3)))
626
SHIFTZ(1) = (-TWO*P(3,P1)*(PT(0)**2 - PT(3)**2) + PT(3)*(PT(0)*
627
$ *2 + PT(1)**2 + PT(2)**2 - PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0)
629
SHIFTZ(2) = -(TWO*P(3,P2)*(PT(0)**2 - PT(3)**2) + PT(3)*(-PT(0)*
630
$ *2 + PT(1)**2 + PT(2)**2 + PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0)
632
NEWP(0,P1) = P(0,P1)+SHIFTE(1)
633
NEWP(3,P1) = P(3,P1)+SHIFTZ(1)
634
NEWP(0,P2) = P(0,P2)+SHIFTE(2)
635
NEWP(3,P2) = P(3,P2)+SHIFTZ(2)
640
DO I=NINITIAL+1,NEXTERNAL
647
IF (.NOT.MP_IS_CLOSE(P,NEWP,WARNED)) THEN
662
C *****************************************************************
663
C Beginning of the routine for restoring precision a la PSMC
664
C *****************************************************************
666
SUBROUTINE MP_PSMC_IMPROVE_PS_POINT_PRECISION(P,ERRCODE,WARNED)
672
PARAMETER (NEXTERNAL=3)
674
PARAMETER (NINITIAL=2)
676
PARAMETER (ZERO=0.0E+00_16)
678
PARAMETER (MP__ZERO=ZERO)
680
PARAMETER (ONE=1.0E+00_16)
682
PARAMETER (TWO=2.0E+00_16)
683
REAL*16 CONSISTENCY_THRES
684
PARAMETER (CONSISTENCY_THRES=1.0E-25_16)
687
PARAMETER (NAPPROXZEROS=3)
692
REAL*16 P(0:3,NEXTERNAL)
693
INTEGER ERRCODE,ERROR,WARNED
702
REAL*16 NEWP(0:3,NEXTERNAL), PBUFF(0:3)
703
REAL*16 BUFF, BUFF2, XSCALE, APPROX_ZEROS(NAPPROXZEROS)
704
REAL*16 MASSES(NEXTERNAL)
708
INCLUDE 'mp_coupl.inc'
721
C Define the seeds which should be tried
722
APPROX_ZEROS(1)=1.0E+00_16
723
APPROX_ZEROS(2)=1.1E+00_16
724
APPROX_ZEROS(3)=0.9E+00_16
726
C Start by copying the momenta
733
C First make sur that the space like momentum is exactly conserved
739
PBUFF(J)=PBUFF(J)+NEWP(J,I)
742
DO I=NINITIAL+1,NEXTERNAL-1
744
PBUFF(J)=PBUFF(J)-NEWP(J,I)
748
NEWP(J,NEXTERNAL)=PBUFF(J)
751
C Now find the 'x' rescaling factor
753
CALL FINDX(NEWP,APPROX_ZEROS(I),XSCALE,ERROR)
757
ERRCODE=ERRCODE+(10**(I-1))*ERROR
760
IF (WARNED.LT.20) THEN
761
WRITE(*,*) 'WARNING:: Could not find the proper rescaling'
762
$ //' factor x. Restoring precision ala PSMC will therefore not'
766
IF (ERRCODE.LT.1000) THEN
773
C Apply the rescaling
776
NEWP(J,I)=NEWP(J,I)*XSCALE
780
C Now restore exact onshellness of the particles.
784
BUFF=BUFF+NEWP(J,I)**2
794
BUFF2=BUFF2+NEWP(0,I)
796
DO I=NINITIAL+1,NEXTERNAL
798
BUFF2=BUFF2+NEWP(0,I)
800
IF ((ABS(BUFF)/BUFF2).GT.CONSISTENCY_THRES) THEN
801
IF (WARNED.LT.20) THEN
802
WRITE(*,*) 'WARNING:: The consistency check in the a la PSMC'
803
$ //' precision restoring algorithm failed. The result will'
804
$ //' therefore not be used.'
811
IF (.NOT.MP_IS_CLOSE(P,NEWP,WARNED)) THEN
827
SUBROUTINE FINDX(P,SEED,XSCALE,ERROR)
833
PARAMETER (NEXTERNAL=3)
835
PARAMETER (NINITIAL=2)
837
PARAMETER (ZERO=0.0E+00_16)
839
PARAMETER (MP__ZERO=ZERO)
841
PARAMETER (ONE=1.0E+00_16)
843
PARAMETER (TWO=2.0E+00_16)
844
INTEGER MAXITERATIONS
845
PARAMETER (MAXITERATIONS=8)
847
PARAMETER (CONVERGED=1.0E-26_16)
851
REAL*16 P(0:3,NEXTERNAL),SEED,XSCALE
857
REAL*16 PVECSQ(NEXTERNAL)
858
REAL*16 XN, XNP1,FVAL,DVAL
870
PVECSQ(I)=P(1,I)**2+P(2,I)**2+P(3,I)**2
874
CALL FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL)
879
CALL FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL)
885
IF((ABS(((XNP1-XN)*TWO)/(XNP1+XN))).LT.CONVERGED) THEN
895
C For good measure, we iterate one last time
896
CALL FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL)
901
CALL FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL)
907
XSCALE=XN-(FVAL/DVAL)
913
SUBROUTINE FUNCT(PVECSQ,X,DERIVATIVE,ERROR,RES)
919
PARAMETER (NEXTERNAL=3)
921
PARAMETER (NINITIAL=2)
923
PARAMETER (ZERO=0.0E+00_16)
925
PARAMETER (MP__ZERO=ZERO)
927
PARAMETER (ONE=1.0E+00_16)
929
PARAMETER (TWO=2.0E+00_16)
933
REAL*16 PVECSQ(NEXTERNAL),X,RES
941
REAL*16 MASSES(NEXTERNAL)
945
INCLUDE 'mp_coupl.inc'
960
IF (I.LE.NINITIAL) THEN
965
BUFF=MASSES(I)**2+PVECSQ(I)*X**2
966
IF (BUFF.LT.ZERO) THEN
972
RES=RES + FACTOR*((X*PVECSQ(I))/SQRT(BUFF))
974
RES=RES + FACTOR*SQRT(BUFF)