diff --git a/madgraph/iolibs/export_v4.py b/madgraph/iolibs/export_v4.py index 562762448d..6d5e1a4feb 100755 --- a/madgraph/iolibs/export_v4.py +++ b/madgraph/iolibs/export_v4.py @@ -12600,9 +12600,11 @@ def create_param_card(self, write_special=True): write_special=write_special) # Output formats with a loop backend for a loop-induced ([noborn=]) process -# coming through the tree-level do_output. Test membership EXACTLY: 'standalone' -# is a prefix of standalone_cpp / _mg7 / _msP / _msF / _rw, which have none. -LOOP_INDUCED_FORMATS = ['madevent', 'plugin', 'standalone'] +# coming through the tree-level do_output. Test membership EXACTLY: it is the +# Fortran standalone that has the MadLoop backend, and 'standalone' -- which +# now names the MadMatrix (C++) output -- is a prefix of it, as it is of +# standalone_msP / _msF / _rw. None of those has a loop backend. +LOOP_INDUCED_FORMATS = ['madevent', 'plugin', 'standalone_fortran'] def loop_induced_not_supported_msg(format, process=None): """Refusal text for a format that cannot write a LoopHelasMatrixElement.""" @@ -12773,8 +12775,8 @@ def ExportV4Factory(cmd, noclean, output_type='default', group_subprocesses=True if format == 'matrix' or format.startswith('standalone'): if cmd._curr_amps and isinstance( cmd._curr_amps[0], loop_diagram_generation.LoopAmplitude): - # of the formats sharing this branch only 'standalone' has a - # MadLoop backend; ProcessExporterFortranSA has none + # of the formats sharing this branch only 'standalone_fortran' + # has a MadLoop backend; ProcessExporterFortranSA has none if format not in LOOP_INDUCED_FORMATS: raise InvalidCmd( loop_induced_not_supported_msg(format, curr_proc)) diff --git a/tests/acceptance_tests/test_cmd.py b/tests/acceptance_tests/test_cmd.py index bca5ccd9cf..1e11bf5938 100755 --- a/tests/acceptance_tests/test_cmd.py +++ b/tests/acceptance_tests/test_cmd.py @@ -5134,7 +5134,7 @@ def testIO_FDgauge_standalone_fortran(self): # different spins (VVV1_VVS1_VSV2_VSS1_0 and # VVV1_VSV2_VSS2_SVV2_SVS2_SSV3_0), which only exist because a # massive vector and its Goldstone are the same wavefunction here. - self.generate_fd('standalone', pjoin(self.IOpath, 'FD_fortran')) + self.generate_fd('standalone_fortran', pjoin(self.IOpath, 'FD_fortran')) @IOTests.createIOTest() def testIO_FDgauge_madmatrix(self): diff --git a/tests/acceptance_tests/test_cmd_madloop.py b/tests/acceptance_tests/test_cmd_madloop.py index 7dd0b42313..f715e4e25c 100755 --- a/tests/acceptance_tests/test_cmd_madloop.py +++ b/tests/acceptance_tests/test_cmd_madloop.py @@ -1373,7 +1373,7 @@ def testIO_loop_induced_standalone_output(self): # no 'import model': validate_model must bootstrap sm -> loop_sm itself interface.exec_cmd('generate g g > h [noborn=QCD]', errorhandling=False, printcmd=False, precmd=True, postcmd=True) - interface.onecmd('output standalone %s -f' % + interface.onecmd('output standalone_fortran %s -f' % str(pjoin(self.IOpath,'gghLI_IOTest'))) diff --git a/tests/input_files/IOTestsComparison/IOTestFDGauge/FDgauge_standalone_fortran/%FD_fortran%Source%DHELAS%FFV6M_3.f b/tests/input_files/IOTestsComparison/IOTestFDGauge/FDgauge_standalone_fortran/%FD_fortran%Source%DHELAS%FFV6M_3.f new file mode 100644 index 0000000000..d1d1743022 --- /dev/null +++ b/tests/input_files/IOTestsComparison/IOTestFDGauge/FDgauge_standalone_fortran/%FD_fortran%Source%DHELAS%FFV6M_3.f @@ -0,0 +1,148 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,-1)*ProjP(-1,1) +C + SUBROUTINE FFV6M_3(F1, F2, MCOUP, M3, W3,V3) + USE ALOHA_OBJECT + USE MODEL_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 CZERO + PARAMETER (CZERO=(0D0,0D0)) + TYPE(FLV_COUPLING) MCOUP + DOUBLE COMPLEX COUP + INTEGER FLV_INDEX + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + COMPLEX*16 FDJS1 + COMPLEX*16 FDJS2 + REAL*8 FDN(0:4) + REAL*8 FDNQ + COMPLEX*16 FDQ(0:4) + REAL*8 M3 + REAL*8 P3(0:3) + TYPE(ALOHA) V3 + REAL*8 W3 + COMPLEX*16 DENOM + INTEGER*4 I + V3%P(:) = +F1%P(:)+F2%P(:) + P3(:) = -V3 % P (:) + V3 % W(:) = CZERO + FDQ(0:3) = -V3 % P(:) + FDQ(4) = -CI*M3 + CALL DEFINE_GAUGE_DIR(FDQ, FDN) + FDNQ = FDN(0)*DBLE(FDQ(0))-FDN(1)*DBLE(FDQ(1))-FDN(2)*DBLE(FDQ(2) + $ )-FDN(3)*DBLE(FDQ(3)) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.EQ.0.OR.FLV_INDEX2.EQ.0)THEN + V3%W(:) = (0D0,0D0) + RETURN + ENDIF + IF(MCOUP % PARTNER(FLV_INDEX1).NE.FLV_INDEX2)THEN + V3%W(:) = (0D0,0D0) + RETURN + ENDIF + COUP = MCOUP % VAL(FLV_INDEX1) % P + DENOM = COUP/(P3(0)**2-P3(1)**2-P3(2)**2-P3(3)**2 - M3 * (M3 -CI + $ * W3)) + V3%W(1)= DENOM*(-CI)*(F2 % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) + V3%W(2)= DENOM*(-CI)*(F2 % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) + V3%W(3)= DENOM*(-CI)*(+CI*(F2 % W(2)*F1 % W(3))-CI*(F2 % W(1)*F1 + $ % W(4))) + V3%W(4)= DENOM*(-CI)*(F2 % W(1)*F1 % W(3)-F2 % W(2)*F1 % W(4)) + FDJS1 = (FDN(0)*V3%W(1)-FDN(1)*V3%W(2)-FDN(2)*V3%W(3)-FDN(3) + $ *V3%W(4))/FDNQ + FDJS2 = (FDQ(0)*V3%W(1)-FDQ(1)*V3%W(2)-FDQ(2)*V3%W(3)-FDQ(3) + $ *V3%W(4)-DCONJG(FDQ(4))*V3%W(5))/FDNQ + V3%W(1) = V3%W(1)-FDQ(0)*FDJS1-FDN(0)*FDJS2 + V3%W(2) = V3%W(2)-FDQ(1)*FDJS1-FDN(1)*FDJS2 + V3%W(3) = V3%W(3)-FDQ(2)*FDJS1-FDN(2)*FDJS2 + V3%W(4) = V3%W(4)-FDQ(3)*FDJS1-FDN(3)*FDJS2 + V3%W(5) = V3%W(5)-FDQ(4)*FDJS1-FDN(4)*FDJS2 + END + + +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Coup(1) * (Gamma(3,2,-1)*ProjP(-1,1)) + Coup(2) * +C (Gamma(3,2,-1)*ProjM(-1,1)) +C + SUBROUTINE FFV6_2M_3(F1, F2, MCOUP1, MCOUP2, M3, W3,V3) + USE ALOHA_OBJECT + USE MODEL_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 CZERO + PARAMETER (CZERO=(0D0,0D0)) + TYPE(FLV_COUPLING) MCOUP1 + DOUBLE COMPLEX COUP1 + INTEGER FLV_INDEX + TYPE(FLV_COUPLING) MCOUP2 + DOUBLE COMPLEX COUP2 + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + COMPLEX*16 FDJS1 + COMPLEX*16 FDJS2 + REAL*8 FDN(0:4) + REAL*8 FDNQ + COMPLEX*16 FDQ(0:4) + REAL*8 M3 + REAL*8 P3(0:3) + TYPE(ALOHA) V3 + REAL*8 W3 + COMPLEX*16 DENOM + INTEGER*4 I + V3%P(:) = +F1%P(:)+F2%P(:) + P3(:) = -V3 % P (:) + V3 % W(:) = CZERO + FDQ(0:3) = -V3 % P(:) + FDQ(4) = -CI*M3 + CALL DEFINE_GAUGE_DIR(FDQ, FDN) + FDNQ = FDN(0)*DBLE(FDQ(0))-FDN(1)*DBLE(FDQ(1))-FDN(2)*DBLE(FDQ(2) + $ )-FDN(3)*DBLE(FDQ(3)) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.EQ.0.OR.FLV_INDEX2.EQ.0)THEN + V3%W(:) = (0D0,0D0) + RETURN + ENDIF + IF(MCOUP1 % PARTNER(FLV_INDEX1).NE.FLV_INDEX2.AND.MCOUP2 % + $ PARTNER(FLV_INDEX1).NE.FLV_INDEX2)THEN + V3%W(:) = (0D0,0D0) + RETURN + ENDIF + COUP1 = MCOUP1 % VAL(FLV_INDEX1) % P + COUP2 = (0D0,0D0) + IF(MCOUP2 % PARTNER(FLV_INDEX1).EQ.FLV_INDEX2) COUP2 = MCOUP2 % + $ VAL(FLV_INDEX1) % P + DENOM = 1D0/(P3(0)**2-P3(1)**2-P3(2)**2-P3(3)**2 - M3 * (M3 -CI* + $ W3)) + V3%W(1)= DENOM*(-CI)*(COUP1*(F2 % W(1)*F1 % W(3)+F2 % W(2)*F1 % + $ W(4))+COUP2*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2))) + V3%W(2)= DENOM*(-CI)*(COUP1*(F2 % W(2)*F1 % W(3)+F2 % W(1)*F1 % + $ W(4))-COUP2*(F2 % W(4)*F1 % W(1)+F2 % W(3)*F1 % W(2))) + V3%W(3)= DENOM*(-CI)*(COUP1*(+CI*(F2 % W(2)*F1 % W(3))-CI*(F2 % + $ W(1)*F1 % W(4)))+COUP2*(-CI*(F2 % W(4)*F1 % W(1))+CI*(F2 % W(3) + $ *F1 % W(2)))) + V3%W(4)= DENOM*(-CI)*(COUP1*(F2 % W(1)*F1 % W(3)-F2 % W(2)*F1 % + $ W(4))+COUP2*(-F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2))) + FDJS1 = (FDN(0)*V3%W(1)-FDN(1)*V3%W(2)-FDN(2)*V3%W(3)-FDN(3) + $ *V3%W(4))/FDNQ + FDJS2 = (FDQ(0)*V3%W(1)-FDQ(1)*V3%W(2)-FDQ(2)*V3%W(3)-FDQ(3) + $ *V3%W(4)-DCONJG(FDQ(4))*V3%W(5))/FDNQ + V3%W(1) = V3%W(1)-FDQ(0)*FDJS1-FDN(0)*FDJS2 + V3%W(2) = V3%W(2)-FDQ(1)*FDJS1-FDN(1)*FDJS2 + V3%W(3) = V3%W(3)-FDQ(2)*FDJS1-FDN(2)*FDJS2 + V3%W(4) = V3%W(4)-FDQ(3)*FDJS1-FDN(3)*FDJS2 + V3%W(5) = V3%W(5)-FDQ(4)*FDJS1-FDN(4)*FDJS2 + END + + + diff --git a/tests/input_files/IOTestsComparison/IOTestFDGauge/FDgauge_standalone_fortran/%FD_fortran%Source%DHELAS%VVV1_0.f b/tests/input_files/IOTestsComparison/IOTestFDGauge/FDgauge_standalone_fortran/%FD_fortran%Source%DHELAS%VVV1_0.f new file mode 100644 index 0000000000..6969057bbe --- /dev/null +++ b/tests/input_files/IOTestsComparison/IOTestFDGauge/FDgauge_standalone_fortran/%FD_fortran%Source%DHELAS%VVV1_0.f @@ -0,0 +1,202 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + +C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) +C + SUBROUTINE VVV1_0(V1, V2, V3, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 CZERO + PARAMETER (CZERO=(0D0,0D0)) + COMPLEX*16 COUP + REAL*8 P1(0:3) + REAL*8 P2(0:3) + REAL*8 P3(0:3) + COMPLEX*16 TMP1 + COMPLEX*16 TMP2 + COMPLEX*16 TMP3 + COMPLEX*16 TMP4 + COMPLEX*16 TMP5 + COMPLEX*16 TMP6 + COMPLEX*16 TMP7 + COMPLEX*16 TMP8 + COMPLEX*16 TMP9 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + INTEGER*4 I + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + TMP1 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + TMP2 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP3 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP4 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP5 = (V3 % W(1)*V1 % W(1)-V3 % W(2)*V1 % W(2)-V3 % W(3)*V1 % + $ W(3)-V3 % W(4)*V1 % W(4)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP7 = (V3 % W(1)*V2 % W(1)-V3 % W(2)*V2 % W(2)-V3 % W(3)*V2 % + $ W(3)-V3 % W(4)*V2 % W(4)) + TMP8 = (P2(0)*V1 % W(1)-P2(1)*V1 % W(2)-P2(2)*V1 % W(3)-P2(3)*V1 + $ % W(4)) + TMP9 = (V1 % W(1)*P3(0)-V1 % W(2)*P3(1)-V1 % W(3)*P3(2)-V1 % W(4) + $ *P3(3)) + VERTEX = COUP*(TMP1*(-CI*(TMP2)+CI*(TMP3))+(TMP5*(+CI*(TMP4)-CI + $ *(TMP6))+TMP7*(-CI*(TMP8)+CI*(TMP9)))) + END + + +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Coup(1) * (P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - +C P(2,1)*Metric(1,3) + P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - +C P(1,3)*Metric(2,3)) +C Coup(2) * (Metric(1,2)) +C Coup(3) * (Metric(1,3)) +C Coup(4) * (P(1,2) - P(1,3)) +C + SUBROUTINE VVV1_VVS1_VSV2_VSS1_0(V1, V2, V3, COUP1, COUP2, COUP3 + $ , COUP4,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 CZERO + PARAMETER (CZERO=(0D0,0D0)) + COMPLEX*16 COUP1 + COMPLEX*16 COUP2 + COMPLEX*16 COUP3 + COMPLEX*16 COUP4 + REAL*8 P1(0:3) + REAL*8 P2(0:3) + REAL*8 P3(0:3) + COMPLEX*16 TMP1 + COMPLEX*16 TMP2 + COMPLEX*16 TMP3 + COMPLEX*16 TMP4 + COMPLEX*16 TMP5 + COMPLEX*16 TMP6 + COMPLEX*16 TMP7 + COMPLEX*16 TMP8 + COMPLEX*16 TMP9 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + INTEGER*4 I + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + VERTEX = (0D0,0D0) + TMP1 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + TMP2 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP3 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP4 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP5 = (V3 % W(1)*V1 % W(1)-V3 % W(2)*V1 % W(2)-V3 % W(3)*V1 % + $ W(3)-V3 % W(4)*V1 % W(4)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP7 = (V3 % W(1)*V2 % W(1)-V3 % W(2)*V2 % W(2)-V3 % W(3)*V2 % + $ W(3)-V3 % W(4)*V2 % W(4)) + TMP8 = (P2(0)*V1 % W(1)-P2(1)*V1 % W(2)-P2(2)*V1 % W(3)-P2(3)*V1 + $ % W(4)) + TMP9 = (V1 % W(1)*P3(0)-V1 % W(2)*P3(1)-V1 % W(3)*P3(2)-V1 % W(4) + $ *P3(3)) + VERTEX = VERTEX + COUP1*(TMP1*(-CI*(TMP2)+CI*(TMP3))+(TMP5*(+CI + $ *(TMP4)-CI*(TMP6))+TMP7*(-CI*(TMP8)+CI*(TMP9)))) + VERTEX = VERTEX + COUP2*(-CI * TMP1*V3 % W(5)) + VERTEX = VERTEX + COUP3*(-CI * TMP5*V2 % W(5)) + VERTEX = VERTEX + COUP4*V2 % W(5)*V3 % W(5)*(-CI*(TMP8)+CI*(TMP9) + $ ) + END + + +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Coup(1) * (P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - +C P(2,1)*Metric(1,3) + P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - +C P(1,3)*Metric(2,3)) +C Coup(2) * (Metric(1,3)) +C Coup(3) * (P(1,3) - P(1,2)) +C Coup(4) * (Metric(2,3)) +C Coup(5) * (P(2,3) - P(2,1)) +C Coup(6) * (P(3,1) - P(3,2)) +C + SUBROUTINE VVV1_VSV2_VSS2_SVV2_SVS2_SSV3_0(V1, V2, V3, COUP1, + $ COUP2, COUP3, COUP4, COUP5, COUP6,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 CZERO + PARAMETER (CZERO=(0D0,0D0)) + COMPLEX*16 COUP1 + COMPLEX*16 COUP2 + COMPLEX*16 COUP3 + COMPLEX*16 COUP4 + COMPLEX*16 COUP5 + COMPLEX*16 COUP6 + REAL*8 P1(0:3) + REAL*8 P2(0:3) + REAL*8 P3(0:3) + COMPLEX*16 TMP1 + COMPLEX*16 TMP2 + COMPLEX*16 TMP3 + COMPLEX*16 TMP4 + COMPLEX*16 TMP5 + COMPLEX*16 TMP6 + COMPLEX*16 TMP7 + COMPLEX*16 TMP8 + COMPLEX*16 TMP9 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + INTEGER*4 I + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + VERTEX = (0D0,0D0) + TMP1 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + TMP2 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP3 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP4 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP5 = (V3 % W(1)*V1 % W(1)-V3 % W(2)*V1 % W(2)-V3 % W(3)*V1 % + $ W(3)-V3 % W(4)*V1 % W(4)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP7 = (V3 % W(1)*V2 % W(1)-V3 % W(2)*V2 % W(2)-V3 % W(3)*V2 % + $ W(3)-V3 % W(4)*V2 % W(4)) + TMP8 = (P2(0)*V1 % W(1)-P2(1)*V1 % W(2)-P2(2)*V1 % W(3)-P2(3)*V1 + $ % W(4)) + TMP9 = (V1 % W(1)*P3(0)-V1 % W(2)*P3(1)-V1 % W(3)*P3(2)-V1 % W(4) + $ *P3(3)) + VERTEX = VERTEX + COUP1*(TMP1*(-CI*(TMP2)+CI*(TMP3))+(TMP5*(+CI + $ *(TMP4)-CI*(TMP6))+TMP7*(-CI*(TMP8)+CI*(TMP9)))) + VERTEX = VERTEX + COUP2*(-CI * TMP5*V2 % W(5)) + VERTEX = VERTEX + COUP3*V2 % W(5)*V3 % W(5)*(-CI*(TMP9)+CI*(TMP8) + $ ) + VERTEX = VERTEX + COUP4*(-CI * TMP7*V1 % W(5)) + VERTEX = VERTEX + COUP5*V1 % W(5)*V3 % W(5)*(-CI*(TMP6)+CI*(TMP4) + $ ) + VERTEX = VERTEX + COUP6*V1 % W(5)*V2 % W(5)*(-CI*(TMP2)+CI*(TMP3) + $ ) + END + + diff --git a/tests/unit_tests/iolibs/test_ufo_parsers.py b/tests/unit_tests/iolibs/test_ufo_parsers.py index 698e2ffdb0..86c62963ba 100755 --- a/tests/unit_tests/iolibs/test_ufo_parsers.py +++ b/tests/unit_tests/iolibs/test_ufo_parsers.py @@ -17,6 +17,7 @@ from __future__ import absolute_import import tests.unit_tests as unittest +import aloha import madgraph.interface.master_interface as Cmd import madgraph.iolibs.ufo_expression_parsers as parsers @@ -28,9 +29,18 @@ class UFOParserTest(unittest.TestCase): def setUp(self): if not hasattr(UFOParserTest, 'model'): - self.cmd = Cmd.MasterCmd() - self.cmd.exec_cmd("import model loop_qcd_qed_sm") - UFOParserTest.model = self.cmd._curr_model + # 'import model' of a loop model switches the gauge to Feynman, and + # the gauge is a *global* (aloha.unitary_gauge) that nothing here + # switches back: every test running afterwards in this process + # inherits it, and any output generated in Feynman gauge keeps the + # Goldstones. Put it back once the model is loaded. + gauge = aloha.unitary_gauge + try: + self.cmd = Cmd.MasterCmd() + self.cmd.exec_cmd("import model loop_qcd_qed_sm") + UFOParserTest.model = self.cmd._curr_model + finally: + aloha.unitary_gauge = gauge if not hasattr(self, 'calc'): self.calc = parsers.UFOExpressionParserFortran(UFOParserTest.model) diff --git a/tests/unit_tests/loop/test_loop_exporters.py b/tests/unit_tests/loop/test_loop_exporters.py index 9d512661f1..d9d48d365d 100755 --- a/tests/unit_tests/loop/test_loop_exporters.py +++ b/tests/unit_tests/loop/test_loop_exporters.py @@ -203,6 +203,20 @@ def load_IOTestsUnit(self): exporters = 'default', orders = {'QCD': 2, 'QED': 2} ) + # The references were recorded in the default (unitary) gauge, and the + # gauge is a global: without this decorator the test exports whatever gauge + # an earlier test happened to leave behind -- in Feynman gauge loop_sm + # keeps the charged Goldstone, and get_color.f then starts at CASE(-251) + # instead of the ghost CASE(-82). That is how it passed alone and failed + # in the full suite, after tests/unit_tests/iolibs/test_ufo_parsers. + # + # It does NOT cover every way an earlier test can move this output: + # tests/unit_tests/fks/test_ewsudakov imports loop_qcd_qed_sm_Gmu_forSudakov + # and a later import_ufo.import_model('loop_sm') then groups mdl_MW under + # ('aEWM1', 'Gf') instead of ('aEWM1',), which reorders + # mp_intparam_definition.inc. That is a leak between UFO model imports, not + # a gauge one, and it is still open. + @IOTests.set_global() def testIO_UnitProcOutputIOTests(self, load_only=False): """ Run the iotests """ diff --git a/tests/unit_tests/loop/test_loop_induced_output.py b/tests/unit_tests/loop/test_loop_induced_output.py index b1ff8e6668..4d60a43ddc 100644 --- a/tests/unit_tests/loop/test_loop_induced_output.py +++ b/tests/unit_tests/loop/test_loop_induced_output.py @@ -24,18 +24,23 @@ LoopAmplitude and the matrix element a LoopHelasMatrixElement. Every format used to hand that loop matrix element to a tree-level exporter and -die deep inside it -- 'output standalone' with an IndexError in write_check_sa, -'output matrix' with "wavefunction_rank has not been computed", 'output mg7' -with a KeyError on the first loop leg, which the mg7 exporter's edge-name map -does not contain. Two things were wrong: +die deep inside it -- 'output standalone_fortran' with an IndexError in +write_check_sa, 'output matrix' with "wavefunction_rank has not been computed", +'output mg7' with a KeyError on the first loop leg, which the mg7 exporter's +edge-name map does not contain. Two things were wrong: * `HelasMatrixElement._flavor_enumeration_context` counted *every* motherless wavefunction as an external leg. A LoopHelasMatrixElement's L-cut wavefunctions are motherless too, so `get_external_flavors()` returned tuples of length nexternal+2 -- which is what write_check_sa tripped over; - * the exporter itself was the tree-level one. 'standalone' is now routed to - the MadLoop standalone exporter (LOOP_INDUCED_FORMATS), joining 'madevent' - which has always had the LoopInducedExporterME* exporters. + * the exporter itself was the tree-level one. 'standalone_fortran' is now + routed to the MadLoop standalone exporter (LOOP_INDUCED_FORMATS), joining + 'madevent' which has always had the LoopInducedExporterME* exporters. + +Mind the vocabulary: the format with the MadLoop backend is the *Fortran* +standalone, which is spelled 'standalone_fortran' since the export formats were +renamed. Plain 'standalone' now names the MadMatrix (C++) output, which has no +loop backend and must be refused like any other. The formats with no MadLoop backend at all still cannot serve the process, and refuse it up front pointing at [sqrvirt=...], which stays in the MadLoop @@ -164,7 +169,7 @@ def tearDown(self): #=========================================================================== # helpers #=========================================================================== - def get_exporter(self, interface, format='standalone'): + def get_exporter(self, interface, format='standalone_fortran'): """The exporter ExportV4Factory picks for 'format'.""" interface._export_format = format @@ -199,7 +204,7 @@ def assert_output_refused(self, format): "'output %s' silently accepted %s; no exporter for that format can " "write a LoopHelasMatrixElement" % (format, LOOP_INDUCED_PROCESS)) - def assert_output_succeeds(self, process, format='standalone'): + def assert_output_succeeds(self, process, format='standalone_fortran'): """'output ' must go through, and write a MadLoop directory.""" interface = get_interface(process) @@ -213,7 +218,7 @@ def assert_output_succeeds(self, process, format='standalone'): '%s did not produce a MadLoop output' % process) #=========================================================================== - # 'standalone' is served by the MadLoop standalone exporter + # 'standalone_fortran' is served by the MadLoop standalone exporter #=========================================================================== def test_standalone_factory_uses_the_madloop_exporter(self): """ExportV4Factory must not hand a loop-induced process to the @@ -236,8 +241,8 @@ def test_standalone_factory_unchanged_for_tree(self): self.assertFalse(isinstance( exporter, loop_exporters.LoopProcessExporterFortranSA)) - def test_output_standalone_accepts_loop_induced(self): - """'output standalone' used to die with an IndexError in + def test_output_standalone_fortran_accepts_loop_induced(self): + """'output standalone_fortran' used to die with an IndexError in write_check_sa; it now writes a MadLoop standalone directory.""" self.assert_output_succeeds(LOOP_INDUCED_PROCESS) @@ -257,10 +262,14 @@ def test_no_model_imported(self): # ... the formats with no MadLoop backend refuse it #=========================================================================== def test_loop_induced_formats_are_matched_exactly(self): - """'standalone' is a prefix of formats that have no loop backend; the - allow-list must never be tested with startswith.""" + """The allow-list must never be tested with startswith. + + 'standalone' is a prefix of the format that does have a loop backend + ('standalone_fortran') and it names the MadMatrix output, which does + not -- so a startswith test would get this exactly backwards. + """ - for format in ['standalone_cpp', 'standalone_mg7', 'standalone_msP', + for format in ['standalone', 'standalone_mg7', 'standalone_msP', 'standalone_msF', 'standalone_rw']: self.assertNotIn(format, export_v4.LOOP_INDUCED_FORMATS) @@ -276,10 +285,16 @@ def test_output_mg7_refuses_loop_induced(self): self.assert_output_refused('mg7') - def test_output_standalone_cpp_refuses_loop_induced(self): - """The prefix trap: standalone_cpp must not ride on 'standalone'.""" + def test_output_standalone_refuses_loop_induced(self): + """The prefix trap: plain 'standalone' is the MadMatrix output. + + It must not ride on the 'standalone_fortran' entry of the allow-list. + While it did, it reached the mg7 exporter and died there with a + KeyError on the first loop leg -- the very crash the guard in + ExportCPPFactory exists to prevent. + """ - self.assert_output_refused('standalone_cpp') + self.assert_output_refused('standalone') def test_output_standalone_msP_refuses_loop_induced(self): """Same for the MadSpin standalone variants."""