Merge lp:~maddevelopers/mg5amcnlo/2.7.3_tflipping into lp:mg5amcnlo/lts

Proposed by Olivier Mattelaer
Status: Merged
Merged at revision: 293
Proposed branch: lp:~maddevelopers/mg5amcnlo/2.7.3_tflipping
Merge into: lp:mg5amcnlo/lts
Diff against target: 14231 lines (+5206/-1853)
263 files modified
Template/LO/Cards/run_card.dat (+8/-5)
Template/LO/Source/.make_opts (+2/-1)
Template/LO/Source/PDF/pdf.f (+8/-3)
Template/LO/Source/dsample.f (+10/-2)
Template/LO/Source/invarients.f (+16/-4)
Template/LO/Source/run.inc (+6/-1)
Template/LO/SubProcesses/cluster.f (+4/-2)
Template/LO/SubProcesses/genps.f (+472/-19)
Template/LO/SubProcesses/makefile (+13/-4)
Template/LO/SubProcesses/myamp.f (+11/-6)
Template/LO/SubProcesses/reweight.f (+6/-1)
Template/LO/SubProcesses/setcuts.f (+4/-2)
Template/LO/SubProcesses/unwgt.f (+6/-1)
UpdateNotes.txt (+25/-0)
VERSION (+1/-1)
aloha/aloha_parsers.py (+1/-1)
aloha/aloha_writers.py (+24/-12)
aloha/create_aloha.py (+20/-1)
aloha/template_files/Makefile_F (+2/-0)
aloha/template_files/aloha_functions.f (+34/-1)
madgraph/core/diagram_generation.py (+1/-1)
madgraph/core/helas_objects.py (+4/-6)
madgraph/interface/common_run_interface.py (+19/-1)
madgraph/interface/madevent_interface.py (+18/-2)
madgraph/interface/madgraph_interface.py (+93/-27)
madgraph/interface/reweight_interface.py (+1/-1)
madgraph/iolibs/export_fks.py (+15/-16)
madgraph/iolibs/export_v4.py (+613/-42)
madgraph/iolibs/file_writers.py (+18/-16)
madgraph/iolibs/gen_infohtml.py (+2/-1)
madgraph/iolibs/template_files/auto_dsig_v4.inc (+6/-0)
madgraph/iolibs/template_files/b_sf_xxx_fks.inc (+1/-0)
madgraph/iolibs/template_files/born_fks.inc (+4/-3)
madgraph/iolibs/template_files/born_fks_hel.inc (+1/-0)
madgraph/iolibs/template_files/check_sa.f (+1/-1)
madgraph/iolibs/template_files/check_sa_splitOrders.f (+1/-1)
madgraph/iolibs/template_files/loop/check_sa.inc (+1/-1)
madgraph/iolibs/template_files/loop/check_sa_loop_induced.inc (+1/-1)
madgraph/iolibs/template_files/madevent_driver.f (+17/-1)
madgraph/iolibs/template_files/madevent_symmetry.f (+3/-1)
madgraph/iolibs/template_files/matrix_madevent_group_v4.inc (+114/-20)
madgraph/iolibs/template_files/matrix_madevent_group_v4_hel.inc (+281/-0)
madgraph/iolibs/template_files/matrix_madevent_v4.inc (+3/-3)
madgraph/iolibs/template_files/matrix_madweight_group_v4.inc (+2/-2)
madgraph/iolibs/template_files/matrix_standalone_matchbox.inc (+3/-3)
madgraph/iolibs/template_files/matrix_standalone_matchbox_splitOrders_v4.inc (+3/-3)
madgraph/iolibs/template_files/matrix_standalone_msF_v4.inc (+2/-2)
madgraph/iolibs/template_files/matrix_standalone_msP_v4.inc (+2/-2)
madgraph/iolibs/template_files/matrix_standalone_splitOrders_v4.inc (+2/-2)
madgraph/iolibs/template_files/matrix_standalone_v4.inc (+4/-4)
madgraph/iolibs/template_files/realmatrix_fks.inc (+3/-2)
madgraph/iolibs/template_files/super_auto_dsig_group_v4.inc (+15/-5)
madgraph/madevent/gen_ximprove.py (+181/-5)
madgraph/madevent/hel_recycle.py (+924/-0)
madgraph/various/banner.py (+89/-10)
madgraph/various/lhe_parser.py (+53/-18)
madgraph/various/misc.py (+7/-2)
madgraph/various/systematics.py (+17/-7)
models/__init__.py (+3/-5)
models/import_ufo.py (+9/-4)
tests/acceptance_tests/test_cmd.py (+9/-6)
tests/acceptance_tests/test_cmd_madevent.py (+4/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_001.f (+6/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_002.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_003.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_004.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_005.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_006.f (+5/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_007.f (+6/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%b_sf_008.f (+5/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%born.f (+10/-9)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_gg_ttx%born_hel.f (+7/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_001.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_002.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_003.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_004.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_005.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_006.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_007.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%b_sf_008.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%born.f (+10/-9)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uux_ttx%born_hel.f (+7/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_001.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_002.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_003.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_004.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_005.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_006.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_007.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%b_sf_008.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%born.f (+10/-9)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fks_loonly/%SubProcesses%P0_uxu_ttx%born_hel.f (+7/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_001.f (+6/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_002.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_003.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_004.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_005.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_006.f (+5/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_007.f (+6/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%b_sf_008.f (+5/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%born.f (+10/-9)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%born_hel.f (+7/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%matrix_1.f (+43/-26)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%matrix_2.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%matrix_3.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%matrix_4.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_gg_ttx%matrix_5.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_001.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_002.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_003.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_004.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_005.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_006.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_007.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%b_sf_008.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%born.f (+10/-9)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%born_hel.f (+7/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%matrix_1.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%matrix_2.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uux_ttx%matrix_3.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_001.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_002.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_003.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_004.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_005.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_006.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_007.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%b_sf_008.f (+5/-4)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%born.f (+10/-9)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%born_hel.f (+7/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%matrix_1.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%matrix_2.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_pptt_fksreal/%SubProcesses%P0_uxu_ttx%matrix_3.f (+19/-14)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%born_matrix.f (+4/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%V0_dxu_wp%check_sa_born_splitOrders.f (+1/-1)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%b_sf_001.f (+3/-2)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%born.f (+6/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%born_hel.f (+3/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%matrix_1.f (+5/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%matrix_2.f (+5/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_dxu_wp%matrix_3.f (+5/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%born_matrix.f (+4/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%V0_udx_wp%check_sa_born_splitOrders.f (+1/-1)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%b_sf_001.f (+3/-2)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%born.f (+6/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%born_hel.f (+3/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%matrix_1.f (+5/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%matrix_2.f (+5/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_ppw_fksall/%SubProcesses%P0_udx_wp%matrix_3.f (+5/-5)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_001.f (+3/-2)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_002.f (+3/-2)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_003.f (+4/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_004.f (+4/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_005.f (+3/-2)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_006.f (+4/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_007.f (+4/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%b_sf_008.f (+3/-2)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%born.f (+6/-6)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%born_hel.f (+3/-3)
tests/input_files/IOTestsComparison/IOExportFKSTest/test_tdecay_fksreal/%SubProcesses%P0_t_budx%matrix_1.f (+9/-8)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_madevent_group/auto_dsig.f (+5/-0)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_madevent_group/configs.inc (+5/-0)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_madevent_group/matrix1.f (+127/-31)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_madevent_group/super_auto_dsig.f (+16/-5)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_madevent_nogroup/auto_dsig.f (+5/-0)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_madevent_nogroup/configs.inc (+3/-0)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_madevent_nogroup/matrix.f (+9/-9)
tests/input_files/IOTestsComparison/IOExportV4IOTest/export_matrix_element_v4_standalone/matrix.f (+4/-5)
tests/input_files/IOTestsComparison/MadLoop_output_from_the_interface/TIR_output/%ggttx_IOTest%SubProcesses%P0_gg_ttx%born_matrix.f (+6/-6)
tests/input_files/IOTestsComparison/MadLoop_output_from_the_interface/TIR_output/%ggttx_IOTest%SubProcesses%P0_gg_ttx%check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/MadLoop_output_from_the_interface/TIR_output/%ggttx_IOTest%SubProcesses%P0_gg_ttx%check_sa_born_splitOrders.f (+1/-1)
tests/input_files/IOTestsComparison/MadLoop_output_from_the_interface/TIR_output/%ggttx_IOTest%SubProcesses%P0_gg_ttx%helas_calls_uvct_1.f (+12/-12)
tests/input_files/IOTestsComparison/MadLoop_output_from_the_interface/TIR_output/%ggttx_IOTest%SubProcesses%P0_gg_ttx%mp_helas_calls_uvct_1.f (+12/-12)
tests/input_files/IOTestsComparison/SquaredOrder_IOTest/sqso_uux_uuxuuxx/matrix_NoSQSO.f (+21/-15)
tests/input_files/IOTestsComparison/SquaredOrder_IOTest/sqso_uux_uuxuuxx/matrix_QCDsq_le_6.f (+20/-14)
tests/input_files/IOTestsComparison/SquaredOrder_IOTest/sqso_uux_uuxuuxx/matrix_ampOrderQED2_eq_2_WGTsq_le_14_QCDsq_gt_4.f (+20/-14)
tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P0_wpwm_wpwm%matrix.f (+5/-7)
tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P1_uux_uux%born_matrix.f (+11/-11)
tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P1_uux_uux%check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P1_uux_uux%check_sa_born_splitOrders.f (+1/-1)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%coupl.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%input.inc (+4/-4)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%mp_coupl.inc (+10/-10)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%mp_coupl_same_name.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%mp_input.inc (+32/-32)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/%..%..%Source%MODEL%mp_intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/born_matrix.f (+4/-5)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/loop_matrix.f (+2/-2)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/dux_mumvmxg/mp_born_amps_and_wfs.f (+2/-2)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%coupl.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%input.inc (+4/-4)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%mp_coupl.inc (+10/-10)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%mp_coupl_same_name.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%mp_input.inc (+32/-32)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/%..%..%Source%MODEL%mp_intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/born_matrix.f (+7/-7)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/loop_matrix.f (+32/-32)
tests/input_files/IOTestsComparison/long_ML_SMQCD_default/gg_wmtbx/mp_born_amps_and_wfs.f (+32/-32)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%coupl.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%input.inc (+4/-4)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%mp_coupl.inc (+10/-10)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%mp_coupl_same_name.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%mp_input.inc (+32/-32)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/%..%..%Source%MODEL%mp_intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/born_matrix.f (+4/-5)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/helas_calls_uvct_1.f (+2/-2)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/dux_mumvmxg/mp_helas_calls_uvct_1.f (+2/-2)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%coupl.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%input.inc (+4/-4)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%mp_coupl.inc (+10/-10)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%mp_coupl_same_name.inc (+8/-8)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%mp_input.inc (+32/-32)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/%..%..%Source%MODEL%mp_intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/born_matrix.f (+7/-7)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/helas_calls_uvct_1.f (+32/-32)
tests/input_files/IOTestsComparison/long_ML_SMQCD_optimized/gg_wmtbx/mp_helas_calls_uvct_1.f (+32/-32)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%coupl.inc (+8/-8)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%input.inc (+10/-10)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%mp_coupl.inc (+10/-10)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%mp_coupl_same_name.inc (+8/-8)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%mp_input.inc (+26/-27)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/%..%..%Source%MODEL%mp_intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/short_ML_SMQCD_LoopInduced/gg_hh/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/ddx_ttx/born_matrix.f (+7/-7)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/ddx_ttx/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%coupl.inc (+8/-8)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%input.inc (+10/-10)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%mp_coupl.inc (+10/-10)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%mp_coupl_same_name.inc (+8/-8)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%mp_input.inc (+32/-32)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/%..%..%Source%MODEL%mp_intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/born_matrix.f (+7/-7)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/loop_matrix.f (+12/-12)
tests/input_files/IOTestsComparison/short_ML_SMQCD_default/gg_ttx/mp_born_amps_and_wfs.f (+12/-12)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/ddx_ttx/born_matrix.f (+7/-7)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/ddx_ttx/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%coupl.inc (+8/-8)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%input.inc (+10/-10)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%mp_coupl.inc (+10/-10)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%mp_coupl_same_name.inc (+8/-8)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%mp_input.inc (+32/-32)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/%..%..%Source%MODEL%mp_intparam_definition.inc (+6/-6)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/born_matrix.f (+7/-7)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/check_sa.f (+1/-1)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/helas_calls_uvct_1.f (+12/-12)
tests/input_files/IOTestsComparison/short_ML_SMQCD_optimized/gg_ttx/mp_helas_calls_uvct_1.f (+12/-12)
tests/parallel_tests/test_aloha.py (+50/-0)
tests/unit_tests/core/test_helas_objects.py (+3/-2)
tests/unit_tests/iolibs/test_export_v4.py (+181/-70)
To merge this branch: bzr merge lp:~maddevelopers/mg5amcnlo/2.7.3_tflipping
Reviewer Review Type Date Requested Status
MadTeam Pending
Review via email: mp+394923@code.launchpad.net

Commit message

implement helicity recycling at LO and new phase-space integration strategy

Description of the change

This branch implements some significant speed-up to the LO code

with two types of speed-up
1) faster method to evaluation tree-level (for LO) matrix-element --same can be implemented at NLO--
2) improved phase-space integration method.

The Paper is close to be finalized.

The new phase-space improves (even more since 2.8.0 started to improve it already) the speed mainly for VBF processes. This branch has been extensively used for muon collider study where the previous version of the code was not even converging.

The modification of the matrix-element provides a factor of ~2 in speed for complicated process (like g g > t t~ g g) but does not improves the situation much for very simple process.

This will be released as 2.9.0

To post a comment you must log in.
Revision history for this message
marco zaro (marco-zaro) wrote :

Thanks Olivier,
how did you achieve the speed improvement for the matrix elements?
Cheers,

Marco

On Sun, Dec 6, 2020 at 10:08 PM Olivier Mattelaer <
<email address hidden>> wrote:

> Olivier Mattelaer has proposed merging
> lp:~maddevelopers/mg5amcnlo/2.7.3_tflipping into lp:mg5amcnlo.
>
> Commit message:
> implement helicity recycling at LO and new phase-space integration strategy
>
> Requested reviews:
> MadTeam (madteam)
>
> For more details, see:
>
> https://code.launchpad.net/~maddevelopers/mg5amcnlo/2.7.3_tflipping/+merge/394923
>
> This branch implements some significant speed-up to the LO code
>
> with two types of speed-up
> 1) faster method to evaluation tree-level (for LO) matrix-element --same
> can be implemented at NLO--
> 2) improved phase-space integration method.
>
> The Paper is close to be finalized.
>
>
> The new phase-space improves (even more since 2.8.0 started to improve it
> already) the speed mainly for VBF processes. This branch has been
> extensively used for muon collider study where the previous version of the
> code was not even converging.
>
> The modification of the matrix-element provides a factor of ~2 in speed
> for complicated process (like g g > t t~ g g) but does not improves the
> situation much for very simple process.
>
>
> This will be released as 2.9.0
>
> --
> Your team MadDevelopers is subscribed to branch
> lp:~maddevelopers/mg5amcnlo/2.7.3_tflipping.
>

Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :

This is the method that I describe in our last meeting and you have one talk about it here:
https://indico.cern.ch/event/955391/contributions/4075843/attachments/2137914/3601421/beamer.pdf

To sum up the initial idea is to remove the explicit loop over helicty and to implement a recycling avoiding to compute twice the same term (in the same spirit as the current recycling between Feynman Diagram).
This also allows up to split the amplitude routine FFV1_0 in two successive call which the first one can be recycle and the second one being a very simple scalar product of two complex vector. This is crucial since we are dominated by the amplitude function in general.

This can (and should) be implemented for the real in a later stage

Revision history for this message
marco zaro (marco-zaro) wrote :

Right, I remember now, thanks a lot!

Cheers,

Marco

> On 9 Dec 2020, at 10:50, Olivier Mattelaer <email address hidden> wrote:
>
> This is the method that I describe in our last meeting and you have one talk about it here:
> https://indico.cern.ch/event/955391/contributions/4075843/attachments/2137914/3601421/beamer.pdf
>
> To sum up the initial idea is to remove the explicit loop over helicty and to implement a recycling avoiding to compute twice the same term (in the same spirit as the current recycling between Feynman Diagram).
> This also allows up to split the amplitude routine FFV1_0 in two successive call which the first one can be recycle and the second one being a very simple scalar product of two complex vector. This is crucial since we are dominated by the amplitude function in general.
>
> This can (and should) be implemented for the real in a later stage
>
> --
> https://code.launchpad.net/~maddevelopers/mg5amcnlo/2.7.3_tflipping/+merge/394923
> Your team MadTeam is requested to review the proposed merge of lp:~maddevelopers/mg5amcnlo/2.7.3_tflipping into lp:mg5amcnlo.

336. By olivier-mattelaer

change option name in the run-card

337. By olivier-mattelaer

fix logger debugging issue

338. By olivier-mattelaer

fix bug reported by Luca

339. By olivier-mattelaer

include code for better jamp computation (not default)

340. By olivier-mattelaer

pass to exponential suppression for tmin

341. By olivier-mattelaer

fix issue with the auto-setting of SDE

342. By olivier-mattelaer

fix s-channel suppression factor

343. By olivier-mattelaer

set jamp_optim as default + remove denom

344. By olivier-mattelaer

better color matrix + fix to t channel ordering

345. By Olivier Mattelaer

add t_strategy -1 in the mix

346. By Olivier Mattelaer

display sde_strat in the run_card, add option for more ps parameter and better default for sde_strat, and fix issue with update frame

347. By olivier-mattelaer

improve smart t-channel ordering

348. By olivier-mattelaer

fix ordering related issue in gensym and other

349. By olivier-mattelaer

fixing SDE default and fixing MLM/CKKW run_card issue

350. By olivier-mattelaer

update the UpdateNote

351. By olivier-mattelaer

allow to specify fortran flag via the run_card

352. By olivier-mattelaer

merge with latest 2.8.3.py3

353. By olivier-mattelaer

fix a lot of tests

354. By olivier-mattelaer

merge with 2.8.3

355. By olivier-mattelaer

merge with latest 2.8.3

356. By olivier-mattelaer

fixing more tests

357. By olivier-mattelaer

fix issue with default make_opts

358. By olivier-mattelaer

set founds-check for debug mode by default

359. By olivier-mattelaer

merge with official 2.8.3

360. By olivier-mattelaer

Update Notes update

361. By olivier-mattelaer

prevent future issue with renamed directory regexp

362. By olivier-mattelaer

fix python2 issue --integer division--, an issue with elastic photon and systematics, and some unittests

363. By olivier-mattelaer

merge with some 2.8.3.py2

364. By Kiran Ostrolenk

Allow for non-sequential calls to NHEL

365. By olivier-mattelaer

update IO test

366. By olivier-mattelaer

add an options to force the model conversion to py3

367. By olivier-mattelaer

fixing one more tests

368. By olivier-mattelaer

add functionality for adding information/message from online

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Template/LO/Cards/run_card.dat'
2--- Template/LO/Cards/run_card.dat 2020-08-07 14:49:25 +0000
3+++ Template/LO/Cards/run_card.dat 2021-01-30 10:13:29 +0000
4@@ -58,16 +58,19 @@
5 %(gridpack)s = gridpack !True = setting up the grid pack
6 %(time_of_flight)s = time_of_flight ! threshold (in mm) below which the invariant livetime is not written (-1 means not written)
7 %(event_norm)s = event_norm ! average/sum. Normalization of the weight in the LHEF
8-$MLM
9-$CKKW
10+$mlm
11+$ckkw
12 #*********************************************************************
13 #
14 #*********************************************************************
15-# handling of the helicities:
16-# 0: sum over all helicities
17-# 1: importance sampling over helicities
18+# Phase-Space Optimization strategy (basic options)
19 #*********************************************************************
20 %(nhel)s = nhel ! using helicities importance sampling or not.
21+ ! 0: sum over helicity, 1: importance sampling
22+ %(sde_strategy)s = sde_strategy ! default integration strategy (hep-ph/2021.xxxxx)
23+ ! 1 is old strategy (using amp square)
24+ ! 2 is new strategy (using only the denominator)
25+$psoptim
26 #*********************************************************************
27 # Generation bias, check the wiki page below for more information: *
28 # 'cp3.irmp.ucl.ac.be/projects/madgraph/wiki/LOEventGenerationBias' *
29
30=== modified file 'Template/LO/Source/.make_opts'
31--- Template/LO/Source/.make_opts 2019-01-23 16:03:38 +0000
32+++ Template/LO/Source/.make_opts 2021-01-30 10:13:29 +0000
33@@ -13,10 +13,11 @@
34
35 # Rest of the makefile
36 ifeq ($(origin FFLAGS),undefined)
37-FFLAGS= -O -w -fbounds-check -fPIC
38+FFLAGS= -w -fPIC
39 #FFLAGS+= -g -fbounds-check -ffpe-trap=invalid,zero,overflow,underflow,denormal -Wall
40 endif
41
42+FFLAGS += $(GLOBAL_FLAG)
43
44 # REMOVE MACFLAG IF NOT ON MAC OR FOR F2PY
45 UNAME := $(shell uname -s)
46
47=== modified file 'Template/LO/Source/PDF/pdf.f'
48--- Template/LO/Source/PDF/pdf.f 2020-08-07 14:49:25 +0000
49+++ Template/LO/Source/PDF/pdf.f 2021-01-30 10:13:29 +0000
50@@ -297,9 +297,14 @@
51 c a "diffractive" photon
52 c
53 q2max=xmu*xmu
54- if(abs(ih) .eq. 3.or.abs(ih) .eq. 4) then !from the electron
55- fx(7)=epa_lepton(x,q2max, ih)
56- elseif(ih .eq. 2) then !from a proton without breaking
57+ if(abs(ih) .eq. 3.or.abs(ih) .eq. 4) then !from the electron
58+ write(*,*) 'impossible call (or was it) to pdf-> please reporrt'
59+ stop 23
60+ fx(7)=epa_lepton(x,q2max, ih)
61+ elseif(ih .eq. 2) then !from a proton without breaking
62+ write(*,*) 'impossible call (or was it) to pdf-> please reporrt'
63+ stop 23
64+ ! isssue with next call since this function takes now a third argument (beamid not define here)
65 fx(7)=epa_proton(x,q2max)
66 endif
67
68
69=== removed file 'Template/LO/Source/PDF/pdf_lhapdf.f'
70=== modified file 'Template/LO/Source/dsample.f'
71--- Template/LO/Source/dsample.f 2020-09-09 12:43:23 +0000
72+++ Template/LO/Source/dsample.f 2021-01-30 10:13:29 +0000
73@@ -257,6 +257,7 @@
74 c Need to start from scratch. This is clunky but I'll just
75 c remove the grid, so we are clean
76 c
77+ goto 200
78 write(*,*) "Trying w/ fresh grid"
79 open(unit=25,file='ftn25',status='unknown',err=102)
80 write(25,*) ' '
81@@ -329,7 +330,7 @@
82 c
83 c All done
84 c
85- open(unit=66,file='results.dat',status='unknown')
86+200 open(unit=66,file='results.dat',status='unknown')
87 i=1
88 do while(xmean(i) .ne. 0 .and. i .lt. cur_it)
89 i=i+1
90@@ -2274,7 +2275,11 @@
91 integer nsteps
92 character*40 result_file,where_file
93 common /sample_status/result_file,where_file,nsteps
94-
95+c
96+c
97+c
98+ logical init_mode
99+ common/to_determine_zero_hel/init_mode
100 c----
101 c Begin Code
102 c----
103@@ -2282,6 +2287,9 @@
104 write(*,*) nb_pass_cuts,
105 & ' points passed the cut but all returned zero'
106 write(*,*) 'therefore considering this contribution as zero'
107+ if (init_mode) then
108+ call print_zero_amp()
109+ endif
110 else if (nb_pass_cuts.gt.0.and.nb_pass_cuts.lt.1000)then
111 write(*,*) 'only', nb_pass_cuts,
112 & ' points passed the cut and they all returned zero'
113
114=== modified file 'Template/LO/Source/invarients.f'
115--- Template/LO/Source/invarients.f 2011-04-16 05:25:14 +0000
116+++ Template/LO/Source/invarients.f 2021-01-30 10:13:29 +0000
117@@ -185,10 +185,10 @@
118 end
119
120
121- subroutine map_invarients(Minvar,nconfigs,ninvar,mincfig,maxcfig,nexternal,nincoming)
122+ subroutine map_invarients(Minvar,nconfigs,ninvar,mincfig,maxcfig,nexternal,nincoming,nb_tchannel)
123 c****************************************************************************
124 c Determines mappings for each structure of invarients onto integration
125-c variables. Input: Ninvar, iforest. Output: Minvar, ninvar
126+c variables. Input: Ninvar, iforest. Output: Minvar, ninvar, nb_tchannel
127 c****************************************************************************
128 implicit none
129 c
130@@ -201,11 +201,13 @@
131 c
132 integer Minvar(maxdim,lmaxconfigs),nconfigs,ninvar,nexternal,nincoming
133 integer mincfig,maxcfig
134+ integer nb_tchannel
135 c
136 c Local
137 c
138 integer iconfig, jgrid,j, nbranch
139 logical found,tchannel
140+ integer ns_channel
141 c
142 c Global
143 c
144@@ -224,20 +226,30 @@
145 c
146 c Try simple mapping if nconfigs = 1
147 c
148-
149+ nb_tchannel = 0
150 if (nconfigs .eq. 1) then
151 c do j=1,3*nbranch-4+2
152 do j=1,maxdim
153 minvar(j,mincfig)=j
154 enddo
155 jgrid=j-1
156+
157+ write(*,*) 'Determine nb_t'
158+ ns_channel=1
159+ do while((iforest(1,-ns_channel,mincfig) .ne. 1.and.iforest(1,-ns_channel,mincfig) .ne. 2).and.ns_channel.lt.nbranch)
160+ ns_channel=ns_channel+1
161+ enddo
162+ ns_channel=ns_channel - 1
163+ nb_tchannel=nbranch-ns_channel-1
164+ write(*,*) 'T-channel found: ',nb_tchannel
165+
166 else
167 c if (ep) jgrid=1
168 c if (pp) jgrid=2
169 do iconfig=mincfig,maxcfig
170 tchannel = .false.
171 do j=1,nbranch-1
172- if (iforest(1,-j,iconfig) .eq. 1) then
173+ if (iforest(1,-j,iconfig) .eq. 1.or.(nincoming.eq.2.and.iforest(1,-j,iconfig) .eq. 2)) then
174 tchannel=.true.
175 endif
176 jgrid=jgrid+1
177
178=== modified file 'Template/LO/Source/run.inc'
179--- Template/LO/Source/run.inc 2019-03-23 22:04:23 +0000
180+++ Template/LO/Source/run.inc 2021-01-30 10:13:29 +0000
181@@ -97,4 +97,9 @@
182 &etamax4pdg, mxxmin4pdg,mxxpart_antipart
183
184 double precision small_width_treatment
185- common/narrow_width/small_width_treatment
186\ No newline at end of file
187+ common/narrow_width/small_width_treatment
188+
189+ double precision tmin_for_channel
190+ integer sde_strat ! 1 means standard single diagram enhancement strategy,
191+c 2 means approximation by the denominator of the propagator
192+ common/TO_CHANNEL_STRAT/tmin_for_channel, sde_strat
193\ No newline at end of file
194
195=== modified file 'Template/LO/SubProcesses/cluster.f'
196--- Template/LO/SubProcesses/cluster.f 2013-03-21 12:45:09 +0000
197+++ Template/LO/SubProcesses/cluster.f 2021-01-30 10:13:29 +0000
198@@ -210,7 +210,8 @@
199 integer ignum, ipnum, ipids(nexternal,4,2:nexternal)
200 C $B$ IFOREST $B$ !this is a tag for MadWeight
201 integer i, iforest(2,-max_branch:-1,lmaxconfigs)
202- common/to_forest/iforest
203+ integer tstrategy(lmaxconfigs)
204+ common/to_forest/iforest, tstrategy
205 integer sprop(maxsproc,-max_branch:-1,lmaxconfigs)
206 integer tprid(-max_branch:-1,lmaxconfigs)
207 common/to_sprop/sprop,tprid
208@@ -404,7 +405,8 @@
209 common/to_mconfigs/mapconfig, this_config
210 C $B$ IFOREST $B$ !this is a tag for MadWeight
211 integer i, iforest(2,-max_branch:-1,lmaxconfigs)
212- common/to_forest/ iforest
213+ integer tstrategy(lmaxconfigs)
214+ common/to_forest/iforest, tstrategy
215 C $E$ IFOREST $E$ !this is a tag for MadWeight
216 C $B$ DECAYBW $E$ !this is a tag for MadWeight
217
218
219=== modified file 'Template/LO/SubProcesses/genps.f'
220--- Template/LO/SubProcesses/genps.f 2020-08-10 19:06:52 +0000
221+++ Template/LO/SubProcesses/genps.f 2021-01-30 10:13:29 +0000
222@@ -163,7 +163,8 @@
223
224
225 integer iforest(2,-max_branch:-1,lmaxconfigs)
226- common/to_forest/ iforest
227+ integer tstrategy(lmaxconfigs)
228+ common/to_forest/ iforest, tstrategy
229
230 integer mapconfig(0:lmaxconfigs), this_config
231 common/to_mconfigs/mapconfig, this_config
232@@ -321,7 +322,7 @@
233 endif
234 pswgt = 1d0
235 jac = 1d0
236- call one_tree(iforest(1,-max_branch,iconfig),mincfig,
237+ call one_tree(iforest(1,-max_branch,iconfig), tstrategy(iconfig),mincfig,
238 & nbranch,P,M,S,X,jac,pswgt)
239 c
240 c Add what I think are the essentials
241@@ -520,7 +521,7 @@
242 integer nbranch,ndim,nconfigs
243 integer ninvar
244 integer nparticles,nfinal
245-
246+ integer nb_tchannel
247
248 c
249 c Arguments
250@@ -595,7 +596,7 @@
251 nconfigs = 1
252 mincfig=iconfig
253 maxcfig=iconfig
254- call map_invarients(minvar,nconfigs,ninvar,mincfig,maxcfig,nexternal,nincoming)
255+ call map_invarients(minvar,nconfigs,ninvar,mincfig,maxcfig,nexternal,nincoming,nb_tchannel)
256 maxwgt=0d0
257 nparticles = nexternal
258 nfinal = nparticles-nincoming
259@@ -632,7 +633,7 @@
260 return
261 end
262
263- subroutine one_tree(itree,iconfig,nbranch,P,M,S,X,jac,pswgt)
264+ subroutine one_tree(itree,tstrategy,iconfig,nbranch,P,M,S,X,jac,pswgt)
265 c************************************************************************
266 c Calculates the momentum for everything below in the tree until
267 c it reaches the end.
268@@ -652,8 +653,10 @@
269 c Arguments
270 c
271 integer itree(2,-max_branch:-1) !Structure of configuration
272+ integer tstrategy ! current strategy for t-channel
273 integer iconfig !Which configuration working on
274 double precision P(0:3,-max_branch:max_particles)
275+ double precision pother(0:3), ptemp(0:3), pboost(0:3), ptemp2(0:3)
276 double precision M(-max_branch:max_particles)
277 double precision S(-max_branch:0)
278 c double precision spole(-max_branch:0),swidth(-max_branch:0)
279@@ -664,12 +667,13 @@
280 c Local
281 c
282 logical pass
283+ double precision tmass(-max_branch:-1)
284 integer ibranch,i,ns_channel,nt_channel,ix !,nerr
285-c data nerr/0/
286+ integer iopposite ! index for t-channel mapping for the part not handle by itree
287+c data nerr/0/
288 double precision smin,smax,totmass,totmassin,xa2,xb2,wgt
289 double precision costh,phi,tmin,tmax,t
290 double precision ma2,mb2,m12,mn2,s1, mi2
291- double precision tmass(-max_branch:-1)
292 c
293 c External
294 c
295@@ -703,7 +707,12 @@
296 c the s channel p1+p2
297 c
298 ns_channel=1
299- do while(itree(1,-ns_channel) .ne. 1 .and.ns_channel.lt.nbranch)
300+ iopposite = 1
301+ if (abs(tstrategy).eq.1) then
302+ iopposite = 2
303+ endif
304+
305+ do while(itree(1,-ns_channel) .ne. iopposite .and.ns_channel.lt.nbranch)
306 m(-ns_channel)=0d0
307 ns_channel=ns_channel+1
308 enddo
309@@ -713,7 +722,6 @@
310 if (nt_channel .eq. 0 .and. nincoming .eq. 2) then
311 ns_channel=ns_channel-1
312 endif
313-
314 c
315 c Determine masses for all intermediate states. Starting
316 c from outer most (real particle) states
317@@ -811,7 +819,7 @@
318 totmass=totmass-m(itree(2,ibranch)) !for remaining particles
319 smin = totmass**2 !This affects t_min/max
320 smax = (m(ibranch) - m(itree(2,ibranch)))**2
321-
322+
323 if (smin .gt. smax) then
324 jac=-3d0
325 return
326@@ -837,18 +845,239 @@
327 c
328 c From here, on we can just pretend this is a 2->2 scattering with
329 c Pa + Pb -> P1 + P2
330+
331+ if (tstrategy.eq.-2.or.tstrategy.eq.-1) then
332+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
333+cc T-channel ping-pong strategy starting with 2
334+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
335+
336+c No -flipping case:
337+c p(0,itree(ibranch,1)) + p(0,2) -> p(0,ibranch)+ p(0,itree(ibranch,2))
338+c - M(ibranch) is the total mass available (Pa+Pb)^2
339+c - M(ibranch-1) is the mass of P2 (all the remaining particles)
340+c
341+c With flipping case
342+c p(0,itree(ibranch,1)) + pother -> p(0,ibranch)+ p(0,itree(ibranch,2))
343+c - pother = p(0,itree(ibranch,1)) -p(0,itree(ibranch,2))
344+c - M(ibranch) is the total mass available (Pa+Pb)^2
345+c - M(ibranch-1) is the mass of P2 (all the remaining particles)
346+c
347+c This assumes that P(0, ibranch) is set to the T-channel propa (likely)
348+c do ibranch = -ns_channel-1,-nbranch,-1
349+c totmass=totmass+m(itree(2,ibranch))
350+c enddo
351+ do ibranch=-ns_channel-1,-nbranch+1,-1
352+c totmass=totmass-m(itree(2,ibranch)) !for remaining particles
353+c smin = totmass**2 !This affects t_min/max
354+c smax = (m(ibranch) - m(itree(2,ibranch)))**2
355+
356+ if (ibranch.ne.-ns_channel-1)then
357+ pother(:) = P(:,ibranch+1)
358+ iopposite = ibranch +1
359+ else
360+ pother(:) = p(:,2)
361+ iopposite = abs(tstrategy)
362+ endif
363+ s1 = m(ibranch)**2 !Total mass available
364+ ma2 = dot(pother, pother)
365+ mb2 = dot(P(0,itree(1,ibranch)),P(0,itree(1,ibranch)))
366+ m12 = m(itree(2,ibranch))**2
367+ mn2 = m(ibranch-1)**2
368+c
369+c$$$ write(*,*) itree(1, ibranch), '-----------T----------', itree(2, ibranch), 'm=', m(itree(2, ibranch))
370+c$$$ write(*,*) ' | '
371+c$$$ write(*,*) ' | '
372+c$$$ write(*,*) ' | ',ibranch
373+c$$$ write(*,*) ' | '
374+c$$$ write(*,*) ' | '
375+c$$$ if (ibranch.ne.-ns_channel-1)then
376+c$$$ write(*,*) iopposite, '-----------T---------- m=', m(ibranch-1)
377+c$$$ else
378+c$$$ write(*,*) 2, '-----------T---------- m=', m(ibranch-1)
379+c$$$ write(*,*) m(1), m(2), m(3), m(4), m(5)
380+c$$$ endif
381+c$$$ write(*,*) 'Pa', P(0,itree(1, ibranch)),P(1,itree(1, ibranch)),P(2,itree(1, ibranch)),P(3,itree(1, ibranch))
382+c$$$ if (ibranch.ne.-ns_channel-1) then
383+c$$$ write(*,*) 'Pb', P(0,iopposite),P(1,iopposite),P(2,iopposite), P(3,iopposite)
384+c$$$ do i=0,3
385+c$$$ pother(i) = P(i,itree(1, ibranch)) + P(i,ibranch+1)
386+c$$$ enddo
387+c$$$ else
388+c$$$ write(*,*) 'Pb', P(0,2),P(1,2),P(2,2),P(3,2)
389+c$$$ do i=0,3
390+c$$$ pother(i) = P(i,1) + P(i,2)
391+c$$$ enddo
392+c$$$ endif
393+c$$$ do i=0,3
394+c$$$ pother(i) = P(i,itree(1, ibranch)) + P(i,iopposite)
395+c$$$ enddo
396+c$$$ write(*,*) 'DSQRT(s1) = ', m(ibranch), DSQRT(dot(pother, pother))
397+c$$$c if (m(ibranch)**2.ne.dot(pother, pother)) stop 1
398+c$$$ write(*,*) 'm12= Pd**2 = ', m12 ,DSQRT(m12)
399+c$$$ write(*,*) 'mn2 = Pc**2 =', mn2, DSQRT(mn2)
400+
401+C WRITE(*,*) 'Enertering yminmax',sqrt(s1),sqrt(m12),sqrt(mn2)
402+
403+ call yminmax(s1,0d0,m12,ma2,mb2,mn2,tmin,tmax)
404+c call yminmax(s1,0d0,m12,ma2,mb2,smax,tmin_temp,tmax_temp)
405+c if (tmin_temp.lt.tmin) tmin = tmin_temp
406+c if (tmax_temp.gt.tmax) tmax = tmax_temp
407+
408+c
409+c Call for 0<x<1
410+c
411+c call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
412+c & .5d0*(tmin/stot+1d0),
413+c & .5d0*(tmax/stot+1d0))
414+c t = Stot*(x(-ibranch)*2d0-1d0)
415+c
416+c call for -1<x<1
417+c
418+
419+c write(*,*) 'tmin, tmax/ temp',tmin,tmax, tmin_temp, tmax_temp
420+
421+c if (nt_channel.ge.2)then
422+c tmin = max(tmin, -stot)
423+c endif
424+c if ((tmax-tmin)/stot.gt.0.1)then
425+c call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
426+c $ 0d0, 1d0)
427+c t = stot*(-x(-ibranch))
428+
429+c else if (tmax/stot.gt.-0.01.and.tmin/stot.lt.-0.02)then
430+c set tmax to 0. The idea is to be sure to be able to hit zero
431+c and not to be block by numerical inacuracy
432+c tmax = max(tmax,0d0) !This line if want really t freedom
433+c call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
434+c $ 0d0, -tmin/stot)
435+c t = stot*(-x(-ibranch))
436+
437+c else
438+ call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
439+ $ -tmax/stot, -tmin/stot)
440+ t = stot*(-x(-ibranch))
441+c endif
442+
443+c call yminmax(s1,0d0,m12,ma2,mb2,mn2,tmin_temp,tmax_temp)
444+ if (t .lt. tmin .or. t .gt. tmax) then
445+ jac=-3d0
446+ return
447+ endif
448+c
449+c tmin and tmax set to -s,+s for jacobian because part of jacobian
450+c was determined from choosing the point x from the grid based on
451+c tmin and tmax. (ie wgt contains some of the jacobian)
452+c
453+ tmin=-stot
454+ tmax= stot
455+ call sample_get_x(wgt,x(nbranch+(-ibranch-1)*2),
456+ & nbranch+(-ibranch-1)*2,iconfig,0d0,1d0)
457+ phi = 2d0*pi*x(nbranch+(-ibranch-1)*2)
458+ jac = jac*(tmax-tmin)*2d0*pi /2d0 ! I need /2d0 if -1<x<1
459+
460+
461+c
462+c Finally generate the momentum. The call is of the form
463+c pa+pb -> p1+ p2; t=(pa-p1)**2; pr = pa-p1
464+c gentcms(pa,pb,t,phi,m1,m2,p1,pr)
465+c
466+ if (itree(1,ibranch).gt.-ns_channel-1)then
467+ mi2 = m(itree(1,ibranch))**2
468+ else
469+ mi2 = tmass(itree(1,ibranch))
470+ endif
471+ tmass(ibranch) = t
472+ call gentcms(p(0,itree(1,ibranch)),p(0,iopposite),t,phi,mi2,
473+ & m(itree(2,ibranch)),m(ibranch-1),p(0,itree(2,ibranch)),
474+ & p(0,ibranch),jac)
475+c$$$ write(*,*) 'RESULT'
476+c$$$ write(*,*) 'pa', p(0,itree(1,ibranch)),p(1,itree(1,ibranch)),p(2,itree(1,ibranch)),p(3,itree(1,ibranch))
477+c$$$ write(*,*) 'pb', p(0,iopposite),p(1,iopposite),p(2,iopposite),p(3,iopposite)
478+c$$$ write(*,*) '->'
479+c$$$ write(*,*) 'pc', p(0,itree(2,ibranch)),p(1,itree(2,ibranch)),p(2,itree(2,ibranch)),p(3,itree(2,ibranch))
480+c$$$ do i =0,3
481+c$$$ pother(i) = p(i,itree(1,ibranch)) + p(i,iopposite) - p(i,itree(2,ibranch))
482+c$$$ enddo
483+c$$$ write(*,*) 'pc', p(0,itree(2,ibranch)),p(1,itree(2,ibranch)),p(2,itree(2,ibranch)),p(3,itree(2,ibranch))
484+c$$$ write(*,*) 'pd', pother(0), pother(1), pother(2), pother(3) , DSQRT(dot(pother,pother))
485+c$$$ write(*,*) 'T channel'
486+c$$$ write(*,*) 'pr', p(0,ibranch),p(1,ibranch),p(2,ibranch),p(3,ibranch)
487+c$$$ write(*,*) 'pa-pc', p(0,itree(1,ibranch))-p(0,itree(2,ibranch)),p(1,itree(1,ibranch))-p(1,itree(2,ibranch))
488+
489+
490+
491+ if (jac .lt. 0d0) then
492+c nerr=nerr+1
493+c if(nerr.le.5)
494+c $ write(*,*) 'Failed gentcms',iconfig,ibranch
495+ return !Failed, probably due to negative x
496+ endif
497+
498+ pswgt = pswgt/(4d0*dsqrt(lambda(s1,ma2,mb2)))
499+ enddo
500+
501+c
502+c We need to get the momentum of the last external particle.
503+c This should just be the sum of p(0,2) and the remaining
504+c momentum from our last t channel 2->2
505+c
506+ if (nt_channel.eq.1) then
507+c$$$ write(*,*) 'need to assign last', itree(2,-nbranch)
508+c$$$ write(*,*) 'nbranch is at', nbranch
509+c$$$ do i=-nbranch,nexternal
510+c$$$ write(*,*) 'p',i, p(0,i),p(1,i),p(2,i),p(3,i)
511+c$$$ enddo
512+ do i=0,3
513+ p(i,itree(2,-nbranch)) = p(i,-nbranch+1)+p(i,2)
514+ enddo
515+ else
516+c$$$ write(*,*) 'need to assign last', itree(2,-nbranch)
517+c$$$ write(*,*) 'nbranch is at', nbranch
518+c$$$ do i=-nbranch,nexternal
519+c$$$ write(*,*) 'p',i, p(0,i),p(1,i),p(2,i),p(3,i)
520+c$$$ enddo
521+ do i=0,3
522+ p(i,itree(2,-nbranch)) = p(i,-nbranch+1)+p(i,-nbranch+2)
523+ enddo
524+ endif
525+
526+
527+ else if (tstrategy.eq.2.or.tstrategy.eq.1) then
528+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
529+cc T-channel One side eat all strategy ending with 2
530+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
531+c
532+c Now perform the t-channel decay sequence. Most of this comes from:
533+c Particle Kinematics Chapter 6 section 3 page 166
534+c
535+c From here, on we can just pretend this is a 2->2 scattering with
536+c Pa + Pb -> P1 + P2
537 c p(0,itree(ibranch,1)) + p(0,2) -> p(0,ibranch)+ p(0,itree(ibranch,2))
538 c M(ibranch) is the total mass available (Pa+Pb)^2
539 c M(ibranch-1) is the mass of P2 (all the remaining particles)
540 c
541 do ibranch=-ns_channel-1,-nbranch+1,-1
542 s1 = m(ibranch)**2 !Total mass available
543- ma2 = m(2)**2
544+ ma2 = m(tstrategy)**2
545 mb2 = dot(P(0,itree(1,ibranch)),P(0,itree(1,ibranch)))
546 m12 = m(itree(2,ibranch))**2
547 mn2 = m(ibranch-1)**2
548 c write(*,*) 'Enertering yminmax',sqrt(s1),sqrt(m12),sqrt(mn2)
549 call yminmax(s1,0d0,m12,ma2,mb2,mn2,tmin,tmax)
550+
551+ if(.false.) then
552+ write(*,*) itree(1, ibranch), 'a----------T----------', itree(2, ibranch), 'm=', m(itree(2, ibranch))
553+ write(*,*) ' | '
554+ write(*,*) ' | '
555+ write(*,*) ' | ',ibranch
556+ write(*,*) ' | '
557+ write(*,*) ' | '
558+ write(*,*) tstrategy, '-----------T---------- m=', m(ibranch-1), ibranch-1
559+ write(*,*) 'S', dsqrt(s1), 'm_top=', dsqrt(mb2), 'M_bottom', dsqrt(ma2)
560+
561+c write(*,*) m(1), m(2), m(3), m(4), m(5)
562+ write(*,*) 'Pa', P(0,itree(1, ibranch)),P(1,itree(1, ibranch)),P(2,itree(1, ibranch)),P(3,itree(1, ibranch))
563+ endif
564 c
565 c Call for 0<x<1
566 c
567@@ -861,15 +1090,80 @@
568 c
569
570 c write(*,*) 'tmin, tmax',tmin,tmax
571-
572- if (tmax.gt.-0.01.and.tmin.lt.-0.02)then
573+ if(.false.) then
574+ ! NOT VALIDATED METHOD, momenta are ok but not jacobian
575+
576+ call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
577+ $ 0d0, 1d0)
578+ costh= 2d0*x(-ibranch)-1d0
579+ call sample_get_x(wgt,x(nbranch+(-ibranch-1)*2),
580+ & nbranch+(-ibranch-1)*2,iconfig,0d0,1d0)
581+ phi = 2d0*pi*x(nbranch+(-ibranch-1)*2)
582+ jac = jac * 4d0*pi
583+ m12 = m(itree(2,ibranch))**2
584+ mn2 = m(ibranch-1)**2
585+ call mom2cx(dsqrt(s1),m(itree(2,ibranch)),m(ibranch-1),costh,phi,
586+ & p(0,itree(2,ibranch)),pother)
587+
588+ I= itree(2,ibranch)
589+ DO I=0,3
590+ pboost(I) = P(I,tstrategy) + P(I,itree(1, ibranch))
591+ ENDDO
592+
593+ call boostm(p(0,itree(2,ibranch)),pboost,m(itree(2,ibranch)),p(0,itree(2,ibranch)))
594+ call boostm(pother,pboost,m(ibranch),pother)
595+
596+ do I=0,3
597+ p(I,ibranch) = pother(i) - p(i, tstrategy)
598+ enddo
599+ if(.false.)then
600+ write(*,*) 'input'
601+ write(*,*) 'p(tstrategy=',tstrategy,')', p(0,tstrategy), p(1,tstrategy), p(2,tstrategy), p(3,tstrategy)
602+ I=itree(1, ibranch)
603+ write(*,*) 'p(',I,',)', p(0,i), p(1,i), p(2,i), p(3,i)
604+ write(*,*) 'output'
605+ I= itree(2,ibranch)
606+ write(*,*) 'p(',I,',)', p(0,i), p(1,i), p(2,i), p(3,i)
607+ write(*,*) 'pother', pother(0),pother(1),pother(2),pother(3)
608+ write(*,*) 'check'
609+ do i=0,3
610+ ptemp(i) = p(i,tstrategy) + p(i, itree(1, ibranch))
611+ enddo
612+ write(*,*) 'pa+pb', ptemp(0), ptemp(1), ptemp(2), ptemp(3), dsqrt(dot(ptemp, ptemp))
613+ do i=0,3
614+ ptemp(i) = pother(i) + p(i,itree(2,ibranch))
615+ enddo
616+ write(*,*) 'p1+p2', ptemp(0), ptemp(1), ptemp(2), ptemp(3), dsqrt(dot(ptemp, ptemp))
617+
618+ write(*,*) 'Tchannel'
619+ I = ibranch
620+ write(*,*) 'p(',I,',)', p(0,i), p(1,i), p(2,i), p(3,i), dot(p(0,I), p(0,I))
621+ endif
622+
623+ pswgt = pswgt/(4d0*dsqrt(lambda(s1,ma2,mb2)))
624+
625+ else
626+
627+c test of impact of low t part
628+ if (nt_channel.ge.2)then
629+ tmin = max(tmin, -stot)
630+ endif
631+ if ((tmax-tmin)/stot.gt.0.1)then
632+ call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
633+ $ 0d0, 1d0)
634+ t = stot*(-x(-ibranch))
635+c if (dabs(tmax - tmin)/stot.gt.0.05d0) then
636+c call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
637+c $ 0d0, 1d0)
638+c set tmax to 0 and tmin to -1 The idea is to avoid dimension correlation
639+c the condition ensure a minimum efficiency in the generation of events
640+c t = stot*(-x(-ibranch))
641+ else if (tmax.gt.-0.01.and.tmin.lt.-0.02)then
642 c set tmax to 0. The idea is to be sure to be able to hit zero
643 c and not to be block by numerical inacuracy
644-c tmax = max(tmax,0d0) !This line if want really t freedom
645 call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
646 $ 0d0, -tmin/stot)
647 t = stot*(-x(-ibranch))
648-
649 else
650 call sample_get_x(wgt,x(-ibranch),-ibranch,iconfig,
651 $ -tmax/stot, -tmin/stot)
652@@ -903,7 +1197,7 @@
653 mi2 = tmass(itree(1,ibranch))
654 endif
655 tmass(ibranch) = t
656- call gentcms(p(0,itree(1,ibranch)),p(0,2),t,phi, mi2,
657+ call gentcms(p(0,itree(1,ibranch)),p(0,tstrategy),t,phi, mi2,
658 & m(itree(2,ibranch)),m(ibranch-1),p(0,itree(2,ibranch)),
659 & p(0,ibranch),jac)
660
661@@ -915,6 +1209,7 @@
662 endif
663
664 pswgt = pswgt/(4d0*dsqrt(lambda(s1,ma2,mb2)))
665+ endif
666 enddo
667 c
668 c We need to get the momentum of the last external particle.
669@@ -922,10 +1217,16 @@
670 c momentum from our last t channel 2->2
671 c
672 do i=0,3
673- p(i,itree(2,-nbranch)) = p(i,-nbranch+1)+p(i,2)
674+ p(i,itree(2,-nbranch)) = p(i,-nbranch+1)+p(i,tstrategy)
675 enddo
676
677
678+
679+ else
680+ write(*,*) 'not supported tstrategy'
681+ stop 2
682+ endif
683+
684 endif !t-channel stuff
685
686
687@@ -960,6 +1261,18 @@
688 call boostm(p(0,itree(1,i)),p(0,i),m(i),p(0,itree(1,i)))
689 call boostm(p(0,itree(2,i)),p(0,i),m(i),p(0,itree(2,i)))
690 enddo
691+c$$$ write(*,*) '****'
692+c$$$ do i=-nbranch,nexternal
693+c$$$ write(*,*) 'mass', i, m(i)
694+c$$$ enddo
695+c$$$ do i=-nbranch,nexternal
696+c$$$ write(*,*) 'p',i, p(0,i),p(1,i),p(2,i),p(3,i)
697+c$$$ enddo
698+c$$$ do i =0,3
699+c$$$ pother(i) = p(i,1) + p(i,2) - p(i,3) -p(i,4)
700+c$$$ enddo
701+c$$$ write(*,*) 'p5 expected', pother(0), pother(1),pother(2),pother(3)
702+
703 jac = jac*wgt
704 if (.not. pass) jac = -99
705 end
706@@ -1024,7 +1337,7 @@
707 c
708 c Arguments
709 c
710- double precision t,phi,m1,m2 !inputs
711+ double precision t,phi,m1,m2,ma !inputs
712 double precision pa(0:3),pb(0:3),jac
713 double precision p1(0:3),pr(0:3) !outputs
714 c
715@@ -1314,6 +1627,146 @@
716 return
717 end
718
719-
720+ double precision function get_channel_cut(p, config)
721+ implicit none
722+
723+ include 'maxconfigs.inc'
724+ include 'nexternal.inc'
725+ include 'genps.inc'
726+ include 'maxamps.inc'
727+ include 'coupl.inc'
728+c include 'run.inc'
729+
730+ double precision p(0:3, nexternal)
731+ integer config
732+
733+
734+ integer iforest(2,-max_branch:-1,lmaxconfigs)
735+ integer tstrategy(lmaxconfigs)
736+ common/to_forest/ iforest, tstrategy
737+
738+ integer sprop(maxsproc,-max_branch:-1,lmaxconfigs)
739+ integer tprid(-max_branch:-1,lmaxconfigs)
740+ common/to_sprop/sprop,tprid
741+
742+ double precision stot,m1,m2
743+ common/to_stot/stot,m1,m2
744+
745+ double precision tmin_for_channel
746+ integer sde_strat ! 1 means standard single diagram enhancement strategy,
747+c 2 means approximation by the denominator of the propagator
748+ common/TO_CHANNEL_STRAT/tmin_for_channel, sde_strat
749+
750+ integer mapconfig(0:lmaxconfigs), this_config
751+ common/to_mconfigs/mapconfig, this_config
752+
753+ double precision spole(maxinvar),swidth(maxinvar),bwjac
754+ common/to_brietwigner/spole ,swidth ,bwjac
755+
756+ double precision ptemp(0:3, -nexternal:nexternal)
757+ integer i,j
758+ integer d1, d2
759+ double precision t
760+ double precision dot
761+ external dot
762+ integer ns_channel
763+ integer nb_tchannel
764+ integer nbranch
765+ double precision tmp, tmp2
766+
767+ double precision ZERO
768+ parameter (ZERO=0d0)
769+ double precision prmass(-nexternal:0,lmaxconfigs)
770+ double precision prwidth(-nexternal:0,lmaxconfigs)
771+ integer pow(-nexternal:0,lmaxconfigs)
772+ logical first_time
773+ save prmass,prwidth,pow
774+ data first_time /.true./
775+
776+ double precision Mass, Width
777+
778+ include 'configs.inc'
779+
780+ if(sde_strat.eq.1.and.tmin_for_channel.eq.-1)then
781+ get_channel_cut = 1d0
782+ return
783+ endif
784+
785+ if (first_time) then
786+ include 'props.inc'
787+ first_time=.false.
788+ endif
789+
790+ do i = 1, nexternal
791+ do j =0,3
792+ ptemp(j,i) = p(j,i)
793+ ptemp(j,-i) = 0d0
794+ enddo
795+ enddo
796+
797+ nbranch = nexternal -2
798+ ns_channel=1
799+ do while((iforest(1,-ns_channel,config) .ne. 1.and.iforest(1,-ns_channel,config) .ne. 2).and.ns_channel.lt.nbranch)
800+ ns_channel=ns_channel+1
801+ enddo
802+ ns_channel=ns_channel - 1
803+ nb_tchannel=nbranch-ns_channel-1
804+c write(*,*) 'T-channel found: ',nb_tchannel
805+
806+
807+
808+
809+
810+
811+ get_channel_cut = 1.
812+ if (nb_tchannel.lt.2.and.sde_strat.eq.1)then
813+ get_channel_cut = 1.
814+ return
815+ endif
816+
817+ do i = 1, nexternal-3
818+ d1 = iforest(1, -i, config)
819+ d2 = iforest(2, -i, config)
820+ do j=0,3
821+ if (d1.gt.0.and.d1.le.2) then
822+ ptemp(j,-i) = ptemp(j,-i) - ptemp(j, d1)
823+ else
824+ ptemp(j,-i) = ptemp(j,-i)+ptemp(j, d1)
825+ endif
826+ if (d2.gt.0.and.d2.le.2) then
827+ ptemp(j,-i) = ptemp(j,-i) - ptemp(j, d2)
828+ else
829+ ptemp(j,-i) = ptemp(j,-i)+ptemp(j, d2)
830+ endif
831+ enddo
832+ if (tprid(-i,config).ne.0)then
833+ if(sde_strat.eq.2)then
834+ t = dot(ptemp(0,-i), ptemp(0,-i))
835+ Mass = prmass(-i, config)
836+ get_channel_cut = get_channel_cut / ((t-Mass)*(t+Mass))**2
837+ endif
838+c write(*,*) i, "t, Mass, fact", t, Mass, ((t-Mass)*(t+Mass))**2,get_channel_cut
839+ t = t/stot
840+ if (t.lt.tmin_for_channel)then
841+ get_channel_cut = get_channel_cut * exp((t-tmin_for_channel)/(t+1))
842+c get_channel_cut = get_channel_cut * (t+1)/(1+tmin_for_channel)
843+c else if(t.gt.2*tmin_for_channel)then
844+c get_channel_cut = get_channel_cut * (2*tmin_for_channel-t)/tmin_for_channel
845+ endif
846+ else
847+ if(sde_strat.eq.2)then
848+ t = dot(ptemp(0,-i), ptemp(0,-i))
849+ Mass = prmass(-i, config)
850+ Width = prwidth(-i, config)
851+ tmp = (t-Mass)*(t+Mass)
852+ tmp2 = Mass*Width
853+ get_channel_cut = get_channel_cut* (tmp**2 - tmp2**2)/(tmp**2 + tmp2**2)**2
854+ endif
855+c write(*,*) i, "s, Mass, Width, fact", t, Mass, Width, (((t-Mass)*(t+Mass) )**2 + Width**2*Mass**2), get_channel_cut
856+ endif
857+ enddo
858+c write(*,*) 'final for config', config, get_channel_cut
859+ return
860+ end
861
862
863
864=== modified file 'Template/LO/SubProcesses/makefile'
865--- Template/LO/SubProcesses/makefile 2017-07-13 10:04:07 +0000
866+++ Template/LO/SubProcesses/makefile 2021-01-30 10:13:29 +0000
867@@ -30,18 +30,27 @@
868
869 # Source files
870
871+MATRIX_HEL = $(patsubst %.f,%.o,$(wildcard matrix*_orig.f))
872+MATRIX = $(patsubst %.f,%.o,$(wildcard matrix*_optim.f))
873+ifeq ($(strip $(MATRIX_HEL)),)
874+ MATRIX = $(patsubst %.f,%.o,$(wildcard matrix*.f))
875+endif
876+
877+
878 PROCESS= driver.o myamp.o genps.o unwgt.o setcuts.o get_color.o \
879 cuts.o cluster.o reweight.o initcluster.o addmothers.o setscales.o \
880 idenparts.o dummy_fct.o \
881 $(patsubst %.f,%.o,$(wildcard auto_dsig*.f)) \
882- $(patsubst %.f,%.o,$(wildcard matrix*.f))
883
884 SYMMETRY = symmetry.o idenparts.o
885
886 # Binaries
887
888-$(PROG): $(PROCESS) auto_dsig.o $(LIBS)
889- $(FC) -o $(PROG) $(PROCESS) $(LINKLIBS) $(LDFLAGS) $(BIASDEPENDENCIES)
890+$(PROG): $(PROCESS) auto_dsig.o $(LIBS) $(MATRIX)
891+ $(FC) -o $(PROG) $(PROCESS) $(MATRIX) $(LINKLIBS) $(LDFLAGS) $(BIASDEPENDENCIES)
892+
893+$(PROG)_forhel: $(PROCESS) auto_dsig.o $(LIBS) $(MATRIX_HEL)
894+ $(FC) -o $(PROG)_forhel $(PROCESS) $(MATRIX_HEL) $(LINKLIBS) $(LDFLAGS) $(BIASDEPENDENCIES)
895
896 gensym: $(SYMMETRY) configs.inc $(LIBDIR)libmodel.$(libext) $(LIBDIR)libgeneric.$(libext)
897 $(FC) -o gensym $(SYMMETRY) -L../../lib/ -lmodel -lgeneric -lpdf $(llhapdf) $(LDFLAGS)
898@@ -78,4 +87,4 @@
899 initcluster.o: message.inc
900
901 clean:
902- $(RM) *.o gensym madevent
903+ $(RM) *.o gensym madevent madevent_forhel
904
905=== modified file 'Template/LO/SubProcesses/myamp.f'
906--- Template/LO/SubProcesses/myamp.f 2019-12-04 21:34:25 +0000
907+++ Template/LO/SubProcesses/myamp.f 2021-01-30 10:13:29 +0000
908@@ -38,7 +38,8 @@
909 c
910 include 'maxamps.inc'
911 integer iforest(2,-max_branch:-1,lmaxconfigs)
912- common/to_forest/ iforest
913+ integer tstrategy(lmaxconfigs)
914+ common/to_forest/iforest, tstrategy
915 integer sprop(maxsproc,-max_branch:-1,lmaxconfigs)
916 integer tprid(-max_branch:-1,lmaxconfigs)
917 common/to_sprop/sprop,tprid
918@@ -77,7 +78,8 @@
919 include 'props.inc'
920 nbw = 0
921 do i=-1,-(nexternal-3),-1
922- if (iforest(1,i,iconfig) .eq. 1 .or. prwidth(i,iconfig).le.0) then
923+ if (iforest(1,i,iconfig) .eq. 1 .or. prwidth(i,iconfig).le.0.or.
924+ & (nincoming.eq.2.and.iforest(1,i,iconfig) .eq. 2)) then
925 cycle
926 endif
927 nbw=nbw+1
928@@ -110,7 +112,7 @@
929 c Start loop over propagators
930 do i=-1,-(nexternal-3),-1
931 onbw(i) = .false.
932- if (iforest(1,i,iconfig) .eq. 1) tsgn=-1d0
933+ if (iforest(1,i,iconfig) .eq. 1.or.(nincoming.eq.2.and.iforest(1,i,iconfig).eq.2)) tsgn=-1d0
934 do j=0,3
935 xp(j,i) = xp(j,iforest(1,i,iconfig))
936 $ +tsgn*xp(j,iforest(2,i,iconfig))
937@@ -247,7 +249,8 @@
938 common/to_smin/ Smin
939
940 integer iforest(2,-max_branch:-1,lmaxconfigs)
941- common/to_forest/ iforest
942+ integer tstrategy(lmaxconfigs)
943+ common/to_forest/iforest, tstrategy
944
945 integer sprop(maxsproc,-max_branch:-1,lmaxconfigs)
946 integer tprid(-max_branch:-1,lmaxconfigs)
947@@ -354,8 +357,10 @@
948
949 c Start loop over propagators
950 do i=-1,-(nexternal-3),-1
951- if (iforest(1,i,iconfig) .eq. 1) tsgn=-1d0
952- if (tsgn .eq. 1d0) then !s channel
953+ if (iforest(1,i,iconfig) .eq. 1.or.iforest(1,i,iconfig) .eq. 2)then
954+ tsgn=-1d0
955+ endif
956+ if (tsgn .eq. 1d0) then !s channel
957 xm(i) = xm(iforest(1,i,iconfig))+xm(iforest(2,i,iconfig))
958 xe(i) = xe(iforest(1,i,iconfig))+xe(iforest(2,i,iconfig))
959 mtot = mtot - xm(i)
960
961=== modified file 'Template/LO/SubProcesses/reweight.f'
962--- Template/LO/SubProcesses/reweight.f 2020-08-07 15:02:30 +0000
963+++ Template/LO/SubProcesses/reweight.f 2021-01-30 10:13:29 +0000
964@@ -590,6 +590,8 @@
965 common /to_specxpt/xptj,xptb,xpta,xptl,xmtc,xetamin,xqcut,deltaeta
966 double precision stot,m1,m2
967 common/to_stot/stot,m1,m2
968+ logical init_mode
969+ common/to_determine_zero_hel/init_mode
970
971 C local variables
972 integer i, j, idi, idj, k,m
973@@ -597,6 +599,7 @@
974 real*8 PI
975 parameter( PI = 3.14159265358979323846d0 )
976 integer iforest(2,-max_branch:-1,lmaxconfigs)
977+ integer tstrategy
978 double precision asref, pt2prev(n_max_cl),pt2min
979 integer n, ibeam(2), iqcd(0:2)
980 integer idfl, idmap(-nexternal:nexternal)
981@@ -650,11 +653,12 @@
982 endif
983 100 clustered = cluster(p(0,1))
984 if(.not.clustered) then
985+ if(init_mode) goto 999
986 open(unit=26,file='../../../error',status='unknown',err=999)
987 write(26,*) 'Error: Clustering failed in cluster.f.'
988 write(*,*) 'Error: Clustering failed in cluster.f.'
989 stop
990- 999 write(*,*) 'error'
991+ 999 write(*,*) 'error for clustering'
992 setclscales=.false.
993 clustered = .false.
994 return
995@@ -1349,6 +1353,7 @@
996 logical setclscales
997 integer mapconfig(0:lmaxconfigs), this_config
998 integer iforest(2,-max_branch:-1,lmaxconfigs)
999+ integer tstrategy(lmaxconfigs)
1000 integer sprop(maxsproc,-max_branch:-1,lmaxconfigs)
1001 integer tprid(-max_branch:-1,lmaxconfigs)
1002 include 'configs.inc'
1003
1004=== modified file 'Template/LO/SubProcesses/setcuts.f'
1005--- Template/LO/SubProcesses/setcuts.f 2019-06-17 14:27:09 +0000
1006+++ Template/LO/SubProcesses/setcuts.f 2021-01-30 10:13:29 +0000
1007@@ -879,7 +879,8 @@
1008 double precision pmass(nexternal)
1009 common/to_mass/ pmass
1010 integer iforest(2,-max_branch:-1,lmaxconfigs)
1011- common/to_forest/ iforest
1012+ integer tstrategy(lmaxconfigs)
1013+ common/to_forest/iforest, tstrategy
1014 integer mapconfig(0:lmaxconfigs), this_config
1015 common/to_mconfigs/mapconfig, this_config
1016
1017@@ -946,7 +947,8 @@
1018 c Global
1019 c
1020 integer iforest(2,-max_branch:-1,lmaxconfigs)
1021- common/to_forest/ iforest
1022+ integer tstrategy(lmaxconfigs)
1023+ common/to_forest/iforest, tstrategy
1024 integer sprop(maxsproc,-max_branch:-1,lmaxconfigs)
1025 integer tprid(-max_branch:-1,lmaxconfigs)
1026 common/to_sprop/sprop,tprid
1027
1028=== modified file 'Template/LO/SubProcesses/unwgt.f'
1029--- Template/LO/SubProcesses/unwgt.f 2020-07-30 21:04:54 +0000
1030+++ Template/LO/SubProcesses/unwgt.f 2021-01-30 10:13:29 +0000
1031@@ -469,6 +469,8 @@
1032 include 'run.inc'
1033 include 'run_config.inc'
1034
1035+
1036+
1037 c
1038 c Arguments
1039 c
1040@@ -505,6 +507,9 @@
1041 C
1042 C GLOBAL
1043 C
1044+ logical init_mode
1045+ common/to_determine_zero_hel/init_mode
1046+
1047 double precision twgt, maxwgt,swgt(maxevents)
1048 integer lun, nw, itmin
1049 common/to_unwgt/twgt, maxwgt, swgt, lun, nw, itmin
1050@@ -552,7 +557,7 @@
1051 C-----
1052
1053 if ((nw .ge. maxevents).and.do_write_events) return
1054-
1055+ if (init_mode) return
1056 C if all the necessary inputs to write the events have already been
1057 C computed in the bias module, then directly jump to write_events
1058 if (AlreadySetInBiasModule) then
1059
1060=== modified file 'UpdateNotes.txt'
1061--- UpdateNotes.txt 2021-01-26 14:28:08 +0000
1062+++ UpdateNotes.txt 2021-01-30 10:13:29 +0000
1063@@ -1,5 +1,30 @@
1064 Update notes for MadGraph5_aMC@NLO (in reverse time order)
1065
1066+2.9.0 () **** Major speed-up update for LO computation ***
1067+ Kiran+OM: Optimization of the matrix-element at run-time using recycling helicity method
1068+ - This fasten LO computation by a factor around 2
1069+ - This can be turned off via the command "output PATH --hel_recycling=False"
1070+ OM: Various optimization fot T-channel integration
1071+ - use different ordering for T-channel. Four different ordering have been implemented
1072+ at generation time, the code decides which ordering to use channel-per-channel.
1073+ This can be turned off via the command "output PATH --t_strategy=2"
1074+ - increase number of maximum iteration for double or more T-channel
1075+ - implement an alternative to the standard multi-channel.
1076+ instead of using the amplitude square it use the product of the denominator
1077+ (the default strategy use depends of the process)
1078+ - speed-up for VBF type of process are often around 100 times faster
1079+ - This fixes a lot of issue for processes failing to generate the targetted number of events.
1080+ OM: Better version of the color-computation (but this leads to only modest gain but for very complex processes.)
1081+ This optimizations leads to a longer generation time of the code (only for complex processes).
1082+ This can be turned off via "output PATH --jamp_optim=False"
1083+ OM: New parameter in the run_card:
1084+ - sde_strategy: allows to change the default multi-channel strategy
1085+ - a new phase-space optimization parameter are now easily availabe via the command "update ps_optim"
1086+ OM: New global parameter "auto_convert_model"
1087+ if set on True (set auto_convert_model T or via input/mg5_configuration.txt)
1088+ all model crashing due to a python3 compatibility issue of the UFO model will be automatically converted
1089+ to a python3 compatible model.
1090+
1091 2.8.3 (26/01/21):
1092 OM: Buch of bunch fixing related to python3 issue (mainly related to unicode encoding)
1093 OM: Various fix for reweighting with loop (mainly with python3 as well)
1094
1095=== modified file 'VERSION'
1096--- VERSION 2021-01-26 14:28:08 +0000
1097+++ VERSION 2021-01-30 10:13:29 +0000
1098@@ -1,4 +1,4 @@
1099-version = 2.8.3
1100+version = 2.9.0
1101 date = 2021-01-26
1102
1103
1104
1105=== modified file 'aloha/aloha_parsers.py'
1106--- aloha/aloha_parsers.py 2020-08-20 21:22:22 +0000
1107+++ aloha/aloha_parsers.py 2021-01-30 10:13:29 +0000
1108@@ -198,7 +198,7 @@
1109
1110 aloha_object = ['P', 'PBar', 'PVec','Gamma','Gamma5','Sigma','Mass','PSlash',
1111 'OverMass2','Width','Scalar','Spinor','Vector',
1112- 'Spin2','Spin32','C','Epsilon','Metric','Identity',
1113+ 'Spin2','Spin32','C','Epsilon','Metric','Identity', 'IdentityL',
1114 'ProjM','ProjP','Coup','Norm', 'EPSL', 'EPST1', 'EPST2', 'PT',
1115 'UFP', 'UFM', 'UFPC', 'UFMC',
1116 'VFP', 'VFM', 'VFPC', 'VFMC',
1117
1118=== modified file 'aloha/aloha_writers.py'
1119--- aloha/aloha_writers.py 2020-08-20 15:33:24 +0000
1120+++ aloha/aloha_writers.py 2021-01-30 10:13:29 +0000
1121@@ -221,7 +221,9 @@
1122 self.declaration.add(('complex',coup))
1123
1124 if self.offshell:
1125- if aloha.complex_mass:
1126+ if 'P1N' in self.tag:
1127+ pass
1128+ elif aloha.complex_mass:
1129 call_arg.append(('complex','M%s' % self.outgoing))
1130 self.declaration.add(('complex','M%s' % self.outgoing))
1131 else:
1132@@ -590,7 +592,7 @@
1133 """Define the Header of the fortran file. This include
1134 - momentum conservation
1135 - definition of the impulsion"""
1136-
1137+
1138 out = StringIO()
1139
1140 # Define all the required momenta
1141@@ -612,11 +614,15 @@
1142
1143 if self.declaration.is_used('P%s' % (i+1)):
1144 self.get_one_momenta_def(i+1, out)
1145-
1146+
1147 # define the resulting momenta
1148- if self.offshell:
1149-
1150-
1151+ bypass = False
1152+ if 'P1N' in self.tag:
1153+ if not self.declaration.is_used('P%s' % (self.outgoing)):
1154+ bypass = True
1155+
1156+ if self.offshell and not bypass:
1157+
1158 energy_pos = out_size -2
1159 type = self.particles[self.outgoing-1]
1160
1161@@ -816,23 +822,29 @@
1162 coeff = 'denom*'
1163 if not aloha.complex_mass:
1164 if self.routine.denominator:
1165- out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1166+ if 'P1N' not in self.tag:
1167+ out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1168 'denom':self.write_obj(self.routine.denominator)})
1169 else:
1170 out.write(' denom = %(COUP)s/(P%(i)s(0)**2-P%(i)s(1)**2-P%(i)s(2)**2-P%(i)s(3)**2 - M%(i)s * (M%(i)s -CI* W%(i)s))\n' % \
1171 {'i': self.outgoing, 'COUP': coup_name})
1172 else:
1173 if self.routine.denominator:
1174- raise Exception('modify denominator are not compatible with complex mass scheme')
1175-
1176- out.write(' denom = %(COUP)s/(P%(i)s(0)**2-P%(i)s(1)**2-P%(i)s(2)**2-P%(i)s(3)**2 - M%(i)s**2)\n' % \
1177+ if 'P1N' not in self.tag:
1178+ raise Exception('modify denominator are not compatible with complex mass scheme', self.tag)
1179+ if 'P1N' not in self.tag:
1180+ out.write(' denom = %(COUP)s/(P%(i)s(0)**2-P%(i)s(1)**2-P%(i)s(2)**2-P%(i)s(3)**2 - M%(i)s**2)\n' % \
1181 {'i': self.outgoing, 'COUP': coup_name})
1182- self.declaration.add(('complex','denom'))
1183+ if 'P1N' not in self.tag:
1184+ self.declaration.add(('complex','denom'))
1185 if aloha.loop_mode:
1186 ptype = 'list_complex'
1187 else:
1188 ptype = 'list_double'
1189- self.declaration.add((ptype,'P%s' % self.outgoing))
1190+ if 'P1N' not in self.tag:
1191+ self.declaration.add((ptype,'P%s' % self.outgoing))
1192+ else:
1193+ coeff = 'COUP*'
1194 else:
1195 if coup_name == 'COUP':
1196 coeff = 'COUP*'
1197
1198=== modified file 'aloha/create_aloha.py'
1199--- aloha/create_aloha.py 2020-11-25 20:43:03 +0000
1200+++ aloha/create_aloha.py 2021-01-30 10:13:29 +0000
1201@@ -312,7 +312,6 @@
1202 propa = [t[1:] for t in self.tag if t.startswith('P')]
1203 if propa == ['0']:
1204 if spin == 3 and aloha.unitary_gauge == 2:
1205- misc.sprint(spin)
1206 lorentz *= complex(0,1) * self.get_custom_propa('1PS', spin, id)
1207 continue
1208 else:
1209@@ -482,6 +481,12 @@
1210 elif propa == "1PS":
1211 numerator = "(-1*(P(-1,id)*PBar(-1,id)) * Metric(1, 2) + P(1,id)*PBar(2,id) + PBar(1,id)*P(2,id))"
1212 denominator = "(P(-3,id)*PBar(-3,id))*P(-2,id)**2"
1213+ elif propa == "1N":
1214+ if spin == 3:
1215+ numerator = '-1*IdentityL(1,2)'
1216+ else:
1217+ numerator = "-1"
1218+ denominator = "1"
1219 else:
1220 raise Exception
1221
1222@@ -539,6 +544,7 @@
1223 return eval(numerator) * propaR
1224 else:
1225 return eval(numerator)
1226+
1227
1228
1229
1230@@ -920,7 +926,20 @@
1231 # self.explicit_combine = False
1232 request = {}
1233
1234+ #handle special outgoing=-1 flag (which means do it for all particle outgoing)
1235+ # use for P1N
1236+ for list_l_name, tag, outgoing in data[:]:
1237+ if outgoing == -1: #means do for all particle.
1238+ data.remove((list_l_name, tag, outgoing))
1239+ l_name = list_l_name[0]
1240+ lorentz = eval('self.model.lorentz.%s' % l_name)
1241+ for i in range(len(lorentz.spins)):
1242+ data.append((list_l_name, tag, i+1))
1243+
1244+
1245+
1246 for list_l_name, tag, outgoing in data:
1247+
1248 #allow tag to have integer for retro-compatibility
1249 all_tag = tag[:]
1250 conjugate = [i for i in tag if isinstance(i, int)]
1251
1252=== modified file 'aloha/template_files/Makefile_F'
1253--- aloha/template_files/Makefile_F 2016-03-02 03:03:20 +0000
1254+++ aloha/template_files/Makefile_F 2021-01-30 10:13:29 +0000
1255@@ -18,6 +18,8 @@
1256
1257 BASIC_OBJS = aloha_functions.o
1258
1259+FFLAGS += $(ALOHA_FLAF)
1260+
1261 include ./aloha_file.inc
1262
1263 all: $(LIBDIR)$(LIBRARY)
1264
1265=== modified file 'aloha/template_files/aloha_functions.f'
1266--- aloha/template_files/aloha_functions.f 2013-11-29 07:28:53 +0000
1267+++ aloha/template_files/aloha_functions.f 2021-01-30 10:13:29 +0000
1268@@ -2036,4 +2036,37 @@
1269 return
1270 end
1271
1272-
1273+ subroutine CombineAmp(nb, ihels, iwfcts, W1, Wall, Amp)
1274+
1275+ integer nb ! size of the vectors
1276+ integer ihels(*), iwfcts(*)
1277+ double complex W1(6)
1278+ double complex Wall(6,*)
1279+ double complex Amp(*)
1280+c local variable
1281+ integer i
1282+
1283+ do i = 1, nb
1284+ Amp(ihels(i)) = W1(3) * Wall(3,iwfcts(i)) +
1285+ & W1(4) * Wall(4,iwfcts(i))+
1286+ & W1(5) * Wall(5,iwfcts(i))+
1287+ & W1(6) * Wall(6,iwfcts(i))
1288+ enddo
1289+ return
1290+ end
1291+
1292+ subroutine CombineAmpS(nb, ihels, iwfcts, W1, Wall, Amp)
1293+
1294+ integer nb ! size of the vectors
1295+ integer ihels(*), iwfcts(*)
1296+ double complex W1(3)
1297+ double complex Wall(6,*)
1298+ double complex Amp(*)
1299+c local variable
1300+ integer i
1301+
1302+ do i = 1, nb
1303+ Amp(ihels(i)) = W1(3) * Wall(3,iwfcts(i))
1304+ enddo
1305+ return
1306+ end
1307
1308=== modified file 'madgraph/core/diagram_generation.py'
1309--- madgraph/core/diagram_generation.py 2020-11-04 20:30:11 +0000
1310+++ madgraph/core/diagram_generation.py 2021-01-30 10:13:29 +0000
1311@@ -574,7 +574,7 @@
1312 process.get('overall_orders')[key])
1313 except KeyError:
1314 process.get('orders')[key] = process.get('overall_orders')[key]
1315-
1316+
1317 assert model.get('particles'), \
1318 "particles are missing in model: %s" % model.get('particles')
1319
1320
1321=== modified file 'madgraph/core/helas_objects.py'
1322--- madgraph/core/helas_objects.py 2021-01-18 08:53:05 +0000
1323+++ madgraph/core/helas_objects.py 2021-01-30 10:13:29 +0000
1324@@ -954,7 +954,6 @@
1325 return False
1326 if self['mothers']:
1327 nb_t_channel= sum(int(wf.is_t_channel()) for wf in self['mothers'])
1328- #raise Exception
1329 else:
1330 return True
1331
1332@@ -3935,11 +3934,10 @@
1333 # Extract all wavefunctions contributing to this amplitude
1334 diagram_wfs = HelasWavefunctionList()
1335 for amplitude in diagram.get('amplitudes'):
1336- wavefunctions = \
1337- sorted(HelasWavefunctionList.\
1338- extract_wavefunctions(amplitude.get('mothers')),
1339- key=lambda wf: wf.get('number'))
1340- for wf in wavefunctions:
1341+ wavefunctions = HelasWavefunctionList.\
1342+ extract_wavefunctions(amplitude.get('mothers'))
1343+
1344+ for wf in reversed(wavefunctions):
1345 # Check if wavefunction already used, otherwise add
1346 if wf.get('number') not in wf_numbers and \
1347 wf not in diagram_wfs:
1348
1349=== modified file 'madgraph/interface/common_run_interface.py'
1350--- madgraph/interface/common_run_interface.py 2021-01-06 14:57:59 +0000
1351+++ madgraph/interface/common_run_interface.py 2021-01-30 10:13:29 +0000
1352@@ -3967,7 +3967,7 @@
1353 return self.deal_multiple_categories(completion, formatting)
1354
1355
1356- def update_make_opts(self):
1357+ def update_make_opts(self, run_card=None):
1358 """update the make_opts file writing the environmental variables
1359 stored in make_opts_var"""
1360 make_opts = os.path.join(self.me_dir, 'Source', 'make_opts')
1361@@ -3982,6 +3982,14 @@
1362
1363 self.make_opts_var['MG5AMC_VERSION'] = misc.get_pkg_info()['version']
1364
1365+ if run_card and run_card.LO:
1366+ if __debug__ and 'global_flag' not in run_card.user_set:
1367+ self.make_opts_var['GLOBAL_FLAG'] = "-O -fbounds-check"
1368+ else:
1369+ self.make_opts_var['ALOHA_FLAG'] = run_card['global_flag']
1370+ self.make_opts_var['ALOHA_FLAG'] = run_card['aloha_flag']
1371+ self.make_opts_var['MATRIX_FLAG'] = run_card['matrix_flag']
1372+
1373 return self.update_make_opts_full(make_opts, self.make_opts_var)
1374
1375 @staticmethod
1376@@ -5924,6 +5932,16 @@
1377 "As your process seems to be impacted by the issue,\n" +\
1378 "You can NOT run with MLM matching/merging. Please check if merging outside MG5aMC are suitable or refrain to use merging with this model")
1379
1380+ #
1381+ if self.run_card and isinstance(self.run_card,banner_mod.RunCardLO):
1382+ if not 'sde_strategy' in self.run_card.user_set:
1383+ if proc_charac['single_color']:
1384+ self.run_card['SDE_strategy'] = 2
1385+ else:
1386+ self.run_card['SDE_strategy'] = 1
1387+ logger.debug("set SDE to %s", self.run_card['SDE_strategy'])
1388+ else:
1389+ logger.debug("keep SDE to %s", self.run_card['SDE_strategy'])
1390
1391 ########################################################################
1392 # NLO specific check
1393
1394=== modified file 'madgraph/interface/madevent_interface.py'
1395--- madgraph/interface/madevent_interface.py 2020-10-09 22:09:19 +0000
1396+++ madgraph/interface/madevent_interface.py 2021-01-30 10:13:29 +0000
1397@@ -3359,7 +3359,23 @@
1398 self.pass_in_difficult_integration_mode()
1399 elif self.run_card['hard_survey']:
1400 self.pass_in_difficult_integration_mode(self.run_card['hard_survey'])
1401-
1402+
1403+ if self.proc_characteristics['hel_recycling'] and self.run_card['hel_recycling']:
1404+ jobs, P_zero_result = ajobcreator.get_helicity()
1405+ else:
1406+ for p in subproc:
1407+ for f in misc.glob('matrix*_orig.f', pjoin(self.me_dir, 'SubProcesses', p)):
1408+ new_file = f.replace('_orig','_optim')
1409+ files.cp(f, f.replace('_orig','_optim'))
1410+ f = '%s.o' % f[:-2]
1411+ if os.path.exists(f):
1412+ files.cp(f, f.replace('_orig','_optim'))
1413+ try:
1414+ os.remove(pjoin(self.me_dir, 'SubProcesses', p, 'Hel', 'selection'))
1415+ except Exception as error:
1416+ logger.debug(error)
1417+ pass
1418+
1419 jobs, P_zero_result = ajobcreator.launch()
1420 # Check if all or only some fails
1421 if P_zero_result:
1422@@ -5692,7 +5708,7 @@
1423 self.treat_ckkw_matching()
1424
1425 # add the make_opts_var to make_opts
1426- self.update_make_opts()
1427+ self.update_make_opts(self.run_card)
1428 # reset list of Gdirectory
1429 self.Gdirs = None
1430
1431
1432=== modified file 'madgraph/interface/madgraph_interface.py'
1433--- madgraph/interface/madgraph_interface.py 2020-11-08 22:23:40 +0000
1434+++ madgraph/interface/madgraph_interface.py 2021-01-30 10:13:29 +0000
1435@@ -300,13 +300,14 @@
1436 """ The Series of help routine for the MadGraphCmd"""
1437
1438 def help_save(self):
1439- logger.info("syntax: save %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
1440+ logger.info("syntax: save %s FILENAME [OPTIONS]" % "|".join(self._save_opts),'$MG:color:BLUE')
1441 logger.info("-- save information as file FILENAME",'$MG:BOLD')
1442 logger.info(" FILENAME is optional for saving 'options'.")
1443 logger.info(' By default it uses ./input/mg5_configuration.txt')
1444 logger.info(' If you put "global" for FILENAME it will use ~/.mg5/mg5_configuration.txt')
1445 logger.info(' If this files exists, it is uses by all MG5 on the system but continues')
1446 logger.info(' to read the local options files.')
1447+ logger.info(' if additional argument are defined for save options, only those arguments will be saved to the configuration file.')
1448
1449 def help_load(self):
1450 logger.info("syntax: load %s FILENAME" % "|".join(self._save_opts),'$MG:color:BLUE')
1451@@ -466,6 +467,9 @@
1452 logger.info(" -nojpeg: no jpeg diagrams will be generated.")
1453 logger.info(" --noeps=True: no jpeg and eps diagrams will be generated.")
1454 logger.info(" -name: the postfix of the main file in pythia8 mode.")
1455+ logger.info(" --jamp_optim=[True|False]: [madevent(default:True)|standalone(default:False)] allows a more efficient code computing the color-factor.")
1456+ logger.info(" --t_strategy: [madevent] allows to change ordering strategy for t-channel.")
1457+ logger.info(" --hel_recycling=False: [madevent] forbids helicity recycling optimization")
1458 logger.info(" Examples:",'$MG:color:GREEN')
1459 logger.info(" output",'$MG:color:GREEN')
1460 logger.info(" output standalone MYRUN -f",'$MG:color:GREEN')
1461@@ -801,7 +805,9 @@
1462 logger.info(" > T channel propagators. Such channel can sometimes be quite slow to integrate")
1463 logger.info("zerowidth_tchannel <value>",'$MG:color:GREEN')
1464 logger.info(" > (default: True) [Used ONLY for tree-level output with madevent]")
1465- logger.info(" > set the width to zero for all T-channel propagator --no impact on complex-mass scheme mode")
1466+ logger.info(" > set the width to zero for all T-channel propagator --no impact on complex-mass scheme mode")
1467+ logger.info("auto_convert_model <value>",'$MG:color:GREEN')
1468+ logger.info(" > (default: False) If set on True any python2 UFO model will be automatically converted to pyton3 format")
1469 #===============================================================================
1470 # CheckValidForCmd
1471 #===============================================================================
1472@@ -2461,7 +2467,8 @@
1473 @cmd.debug()
1474 def complete_output(self, text, line, begidx, endidx,
1475 possible_options = ['f', 'noclean', 'nojpeg'],
1476- possible_options_full = ['-f', '-noclean', '-nojpeg', '--noeps=True']):
1477+ possible_options_full = ['-f', '-noclean', '-nojpeg', '--noeps=True','--hel_recycling=False',
1478+ '--jamp_optim=', '--t_strategy=']):
1479 "Complete the output command"
1480
1481 possible_format = self._export_formats
1482@@ -2470,7 +2477,7 @@
1483 'Calculators', 'MadAnalysis', 'SimpleAnalysis',
1484 'mg5', 'DECAY', 'EventConverter', 'Models',
1485 'ExRootAnalysis', 'HELAS', 'Transfer_Fct', 'aloha',
1486- 'matchbox', 'matchbox_cpp', 'tests']
1487+ 'matchbox', 'matchbox_cpp', 'tests', 'launch']
1488
1489 #name of the run =>proposes old run name
1490 args = self.split_arg(line[0:begidx])
1491@@ -2897,7 +2904,8 @@
1492 'max_npoint_for_channel',
1493 'max_t_for_channel',
1494 'zerowidth_tchannel',
1495- 'default_unset_couplings']
1496+ 'default_unset_couplings',
1497+ ]
1498 _valid_nlo_modes = ['all','real','virt','sqrvirt','tree','noborn','LOonly']
1499 _valid_sqso_types = ['==','<=','=','>']
1500 _valid_amp_so_types = ['=','<=', '==', '>']
1501@@ -2948,7 +2956,8 @@
1502 'cluster_retry_wait':300,
1503 'cluster_size':100,
1504 'output_dependencies':'external',
1505- 'crash_on_error':False
1506+ 'crash_on_error':False,
1507+ 'auto_convert_model': False,
1508 }
1509
1510 options_madgraph= {'group_subprocesses': 'Auto',
1511@@ -3328,10 +3337,12 @@
1512 raise Exception( 'model to convert need to provide a full path')
1513 model_dir = args[0]
1514
1515- answer = self.ask('model conversion to support both py2 and py3 are done in place.\n They are NO guarantee of success.\n It can make the model to stop working under PY2 as well.\n Do you want to proceed?',
1516- 'y', ['y','n'])
1517- if answer != 'y':
1518- return
1519+
1520+ if not ('-f' not in args or self.options['auto_convert_model']):
1521+ answer = self.ask('model conversion to support both py2 and py3 are done in place.\n They are NO guarantee of success.\n It can make the model to stop working under PY2 as well.\n Do you want to proceed?',
1522+ 'y', ['y','n'])
1523+ if answer != 'y':
1524+ return
1525
1526 #Object_library
1527 text = open(pjoin(model_dir, 'object_library.py')).read()
1528@@ -5493,8 +5504,27 @@
1529 else:
1530 aloha.aloha_prefix=''
1531
1532- self._curr_model = import_ufo.import_model(args[1], prefix=prefix,
1533+ try:
1534+ self._curr_model = import_ufo.import_model(args[1], prefix=prefix,
1535 complex_mass_scheme=self.options['complex_mass_scheme'])
1536+ except ufomodels.UFOError as err:
1537+ model_path, _,_ = import_ufo.get_path_restrict(args[1])
1538+ if six.PY3 and self.options['auto_convert_model']:
1539+ logger.info("fail to load model but auto_convert_model is on True. Trying to convert the model")
1540+
1541+ self.exec_cmd('convert model %s' % model_path, errorhandling=False, printcmd=True, precmd=False, postcmd=False)
1542+ logger.info('retry the load of the model')
1543+ tmp_opt = dict(self.options)
1544+ tmp_opt['auto_convert_model'] = False
1545+ with misc.TMP_variable(self, 'options', tmp_opt):
1546+ try:
1547+ self.exec_cmd('import %s' % line, errorhandling=False, printcmd=True, precmd=False, postcmd=False)
1548+ except Exception:
1549+ raise err
1550+ elif six.PY3:
1551+ raise self.InvalidCmd('UFO model not python3 compatible. You can convert it via the command \nconvert model %s\nYou can also type \"set auto_convert_model T\" to automatically convert all python2 module to be python3 compatible in the future.' % model_path)
1552+ else:
1553+ raise
1554 if os.path.sep in args[1] and "import" in self.history[-1]:
1555 self.history[-1] = 'import model %s' % self._curr_model.get('modelpath+restriction')
1556
1557@@ -6013,7 +6043,6 @@
1558 self.options['lhapdf_py2'] = pjoin(prefix,'lhapdf6','bin', 'lhapdf-config')
1559 self.exec_cmd('save options %s lhapdf_py2' % config_file)
1560 self.options['lhapdf'] = self.options['lhapdf_py2']
1561-
1562 elif tool == 'lhapdf5':
1563 self.options['lhapdf'] = pjoin(prefix,'lhapdf5','bin', 'lhapdf-config')
1564 self.exec_cmd('save options %s lhapdf' % config_file, printcmd=False, log=False)
1565@@ -6606,8 +6635,8 @@
1566 """function to apply the patch"""
1567 text = filetext.read().decode()
1568
1569- pattern = re.compile(r'''=== renamed directory \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
1570- #=== renamed directory 'Template' => 'Template/LO'
1571+ pattern = re.compile(r'''^=== renamed directory \'(?P<orig>[^\']*)\' => \'(?P<new>[^\']*)\'''')
1572+ #= = = renamed directory 'Template' => 'Template/LO'
1573 for orig, new in pattern.findall(text):
1574 shutil.copytree(pjoin(MG5DIR, orig), pjoin(MG5DIR, 'UPDATE_TMP'))
1575 full_path = os.path.dirname(pjoin(MG5DIR, new)).split('/')
1576@@ -6790,8 +6819,8 @@
1577 else:
1578 raise self.InvalidCmd('Unknown mode for command install update')
1579
1580- if not os.path.exists(os.path.join(MG5DIR,'input','.autoupdate')) or \
1581- os.path.exists(os.path.join(MG5DIR,'.bzr')):
1582+ if not os.path.exists(os.path.join(MG5DIR,'input','.autoupdate')):# or \
1583+ #os.path.exists(os.path.join(MG5DIR,'.bzr')):
1584 error_text = """This version of MG5 doesn\'t support auto-update. Common reasons are:
1585 1) This version was loaded via bazaar (use bzr pull to update instead).
1586 2) This version is a beta release of MG5."""
1587@@ -6807,7 +6836,7 @@
1588 return
1589
1590 # read the data present in .autoupdate
1591- data = {}
1592+ data = {'last_message':0}
1593 for line in open(os.path.join(MG5DIR,'input','.autoupdate')):
1594 if not line.strip():
1595 continue
1596@@ -6837,9 +6866,16 @@
1597 signal.alarm(timeout)
1598 to_update = 0
1599 try:
1600- filetext = six.moves.urllib.request.urlopen('http://madgraph.phys.ucl.ac.be/mg5amc_build_nb')
1601+ filetext = six.moves.urllib.request.urlopen('http://madgraph.physics.illinois.edu/mg5amc_build_nb')
1602 signal.alarm(0)
1603- web_version = int(filetext.read().strip())
1604+ text = filetext.read().decode().split('\n')
1605+ web_version = int(text[0].strip())
1606+ try:
1607+ msg_version = int(text[1].strip())
1608+ message = '\n'.join(text[2:])
1609+ except:
1610+ msg_version = 0
1611+ message = ""
1612 except (TimeOutError, ValueError, IOError):
1613 signal.alarm(0)
1614 print('failed to connect server')
1615@@ -6847,17 +6883,35 @@
1616 # wait 24h before next check
1617 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
1618 fsock.write("version_nb %s\n" % data['version_nb'])
1619- fsock.write("last_check %s\n" % \
1620- int(time.time()) - 3600 * 24 * (self.options['auto_update'] -1))
1621+ fsock.write("last_check %s\n" % (\
1622+ int(time.time()) - 3600 * 24 * (self.options['auto_update'] -1)))
1623+ fsock.write("last_message %s\n" % data['last_message'])
1624 fsock.close()
1625 return
1626
1627+ if msg_version > data['last_message']:
1628+ data['last_message'] = msg_version
1629+ logger.info("************* INFORMATION *************", '$MG:BOLD')
1630+ logger.info(message.replace('\n','\n '))
1631+ logger.info("************* INFORMATION *************", '$MG:BOLD')
1632+ fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
1633+ fsock.write("version_nb %s\n" % data['version_nb'])
1634+ fsock.write("last_check %s\n" % (\
1635+ int(time.time()) - 3600 * 24 * (int(self.options['auto_update']) -1)))
1636+ fsock.write("last_message %s\n" % data['last_message'])
1637+ fsock.close()
1638+
1639+ if os.path.exists(os.path.join(MG5DIR,'.bzr')):
1640+ logger.info("bzr version: use bzr pull to update")
1641+ return
1642+
1643 if web_version == data['version_nb']:
1644 logger.info('No new version of MG5 available')
1645 # update .autoupdate to prevent a too close check
1646 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
1647 fsock.write("version_nb %s\n" % data['version_nb'])
1648 fsock.write("last_check %s\n" % int(time.time()))
1649+ fsock.write("last_message %s\n" % data['last_message'])
1650 fsock.close()
1651 return
1652 elif data['version_nb'] > web_version:
1653@@ -6865,6 +6919,7 @@
1654 fsock = open(os.path.join(MG5DIR,'input','.autoupdate'),'w')
1655 fsock.write("version_nb %s\n" % data['version_nb'])
1656 fsock.write("last_check %s\n" % int(time.time()))
1657+ fsock.write("last_message %s\n" % data['last_message'])
1658 fsock.close()
1659 return
1660 else:
1661@@ -7760,9 +7815,9 @@
1662 else:
1663 raise self.InvalidCmd('expected bool for notification_center')
1664 # True/False formatting
1665- elif args[0] in ['crash_on_error']:
1666+ elif args[0] in ['crash_on_error', 'auto_convert_model']:
1667 try:
1668- tmp = banner_module.ConfigFile.format_variable(args[1], bool, 'crash_on_error')
1669+ tmp = banner_module.ConfigFile.format_variable(args[1], bool, args[0])
1670 except Exception:
1671 if args[1].lower() in ['never']:
1672 tmp = args[1].lower()
1673@@ -7833,8 +7888,12 @@
1674
1675 if '--postpone_model' in args:
1676 flaglist.append('store_model')
1677-
1678- line_options = dict(arg[2:].split('=') for arg in args if arg.startswith('--') and '=' in arg)
1679+ if '--hel_recycling=False' in args:
1680+ flaglist.append('no_helrecycling')
1681+
1682+ line_options = dict( (arg[2:].split('=') if "=" in arg else (arg[2:], True))
1683+ for arg in args if arg.startswith('--'))
1684+# line_options = dict(arg[2:].split('=') for arg in args if arg.startswith('--') and '=' not in arg)
1685 main_file_name = ""
1686 try:
1687 main_file_name = args[args.index('-name') + 1]
1688@@ -7960,7 +8019,7 @@
1689 || -> add process <proc_def>
1690 """)
1691 group_processes = False
1692-
1693+
1694 #Exporter + Template
1695 if options['exporter'] == 'v4':
1696 self._curr_exporter = export_v4.ExportV4Factory(self, noclean,
1697@@ -8019,7 +8078,7 @@
1698 if self._curr_amps and self._curr_amps[0].get_ninitial() == 1:
1699 options['zerowidth_tchannel'] = False
1700
1701- self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model)
1702+ self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model, options=options)
1703
1704 version = [arg[10:] for arg in args if arg.startswith('--version=')]
1705 if version:
1706@@ -8272,6 +8331,13 @@
1707 # these processes
1708 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
1709 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
1710+
1711+ if self._export_format == 'madevent' and not 'no_helrecycling' in flaglist:
1712+ for (name, flag, out) in wanted_lorentz[:]:
1713+ if out == 0:
1714+ newflag = list(flag) + ['P1N']
1715+ wanted_lorentz.append((name, tuple(newflag), -1))
1716+
1717 # For a unique output of multiple type of exporter need to store this
1718 # information.
1719 if hasattr(self, 'previous_lorentz'):
1720
1721=== modified file 'madgraph/interface/reweight_interface.py'
1722--- madgraph/interface/reweight_interface.py 2021-01-21 13:08:04 +0000
1723+++ madgraph/interface/reweight_interface.py 2021-01-30 10:13:29 +0000
1724@@ -1293,7 +1293,7 @@
1725 scale2 = event.scale**2
1726 else:
1727 scale2 = 0
1728-
1729+
1730 with misc.chdir(Pdir):
1731 with misc.stdchannel_redirected(sys.stdout, os.devnull):
1732 me_value = module.smatrixhel(pdg, pid, p, event.aqcd, scale2, nhel)
1733
1734=== modified file 'madgraph/iolibs/export_fks.py'
1735--- madgraph/iolibs/export_fks.py 2020-09-24 08:52:15 +0000
1736+++ madgraph/iolibs/export_fks.py 2021-01-30 10:13:29 +0000
1737@@ -2016,8 +2016,10 @@
1738 replace_dict['amp2_lines'] = '\n'.join(amp2_lines)
1739
1740 # Extract JAMP lines
1741- jamp_lines = self.get_JAMP_lines(matrix_element)
1742+ jamp_lines, nb_tmp_jamp = self.get_JAMP_lines(matrix_element)
1743 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
1744+ replace_dict['nb_temp_jamp'] = nb_tmp_jamp
1745+
1746
1747 # Set the size of Wavefunction
1748 if not self.model or any([p.get('spin') in [4,5] for p in self.model.get('particles') if p]):
1749@@ -2109,8 +2111,9 @@
1750 replace_dict['amp2_lines'] = '\n'.join(amp2_lines)
1751
1752 # Extract JAMP lines
1753- jamp_lines = self.get_JAMP_lines(matrix_element)
1754+ jamp_lines, nb_tmp_jamp = self.get_JAMP_lines(matrix_element)
1755 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
1756+ replace_dict['nb_temp_jamp'] = nb_tmp_jamp
1757
1758 # Extract den_factor_lines
1759 den_factor_lines = self.get_den_factor_lines(fksborn)
1760@@ -2272,20 +2275,15 @@
1761 replace_dict['amp2_lines'] = '\n'.join(amp2_lines)
1762
1763 # Extract JAMP lines
1764- jamp_lines = self.get_JAMP_lines(matrix_element)
1765- new_jamp_lines = []
1766- for line in jamp_lines:
1767- line = line.replace('JAMP', 'JAMP1')
1768- new_jamp_lines.append(line)
1769- replace_dict['jamp1_lines'] = '\n'.join(new_jamp_lines)
1770+ jamp_lines, nb_tmp_jamp = self.get_JAMP_lines(matrix_element, JAMP_format="JAMP1(%s)")
1771+ replace_dict['jamp1_lines'] = '\n'.join(jamp_lines)
1772+ replace_dict['nb_temp_jamp'] = nb_tmp_jamp
1773
1774+
1775 matrix_element.set('color_basis', link['link_basis'] )
1776- jamp_lines = self.get_JAMP_lines(matrix_element)
1777- new_jamp_lines = []
1778- for line in jamp_lines:
1779- line = line.replace( 'JAMP', 'JAMP2')
1780- new_jamp_lines.append(line)
1781- replace_dict['jamp2_lines'] = '\n'.join(new_jamp_lines)
1782+ jamp_lines, nb_tmp_jamp = self.get_JAMP_lines(matrix_element, JAMP_format="JAMP2(%s)")
1783+ replace_dict['jamp2_lines'] = '\n'.join(jamp_lines)
1784+ replace_dict['nb_temp_jamp'] = max(nb_tmp_jamp, replace_dict['nb_temp_jamp'])
1785
1786
1787 # Extract the number of FKS process
1788@@ -2526,9 +2524,9 @@
1789 replace_dict['wavefunctionsize'] = 8
1790
1791 # Extract JAMP lines
1792- jamp_lines = self.get_JAMP_lines(matrix_element)
1793-
1794+ jamp_lines, nb_tmp_jamp = self.get_JAMP_lines(matrix_element)
1795 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
1796+ replace_dict['nb_temp_jamp'] = nb_tmp_jamp
1797
1798 realfile = open(os.path.join(_file_path, \
1799 'iolibs/template_files/realmatrix_fks.inc')).read()
1800@@ -3389,6 +3387,7 @@
1801 """Class to take care of exporting a set of matrix elements to
1802 Fortran (v4) format."""
1803
1804+ jamp_optim = True
1805
1806 def finalize(self, *args, **opts):
1807 ProcessExporterFortranFKS.finalize(self, *args, **opts)
1808
1809=== modified file 'madgraph/iolibs/export_v4.py'
1810--- madgraph/iolibs/export_v4.py 2021-01-18 22:00:26 +0000
1811+++ madgraph/iolibs/export_v4.py 2021-01-30 10:13:29 +0000
1812@@ -12,10 +12,11 @@
1813 # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
1814 #
1815 ################################################################################
1816-from __future__ import absolute_import
1817+from __future__ import absolute_import, division
1818 from madgraph.iolibs.helas_call_writers import HelasCallWriter
1819 from six.moves import range
1820 from six.moves import zip
1821+from fractions import Fraction
1822 """Methods and classes to export matrix elements to v4 format."""
1823
1824 import copy
1825@@ -33,6 +34,7 @@
1826 import sys
1827 import time
1828 import traceback
1829+import collections
1830
1831 import aloha
1832
1833@@ -164,6 +166,7 @@
1834 'output_options':{}
1835 }
1836 grouped_mode = False
1837+ jamp_optim = False
1838
1839 def __init__(self, dir_path = "", opt=None):
1840 """Initiate the ProcessExporterFortran with directory information"""
1841@@ -174,7 +177,6 @@
1842 self.opt = dict(self.default_opt)
1843 if opt:
1844 self.opt.update(opt)
1845-
1846 self.cmd_options = self.opt['output_options']
1847
1848 #place holder to pass information to the run_interface
1849@@ -1072,7 +1074,7 @@
1850 enumerate(matrix_element.get('color_matrix').\
1851 get_line_denominators()):
1852 # First write the common denominator for this color matrix line
1853- ret_list.append("DATA Denom(%i)/%i/" % (index + 1, denominator))
1854+ #ret_list.append("DATA Denom(%i)/%i/" % (index + 1, denominator))
1855 # Then write the numerators for the matrix elements
1856 num_list = matrix_element.get('color_matrix').\
1857 get_line_numerators(index, denominator)
1858@@ -1082,10 +1084,10 @@
1859 for k in range(0, len(num_list), n):
1860 ret_list.append("DATA (CF(i,%3r),i=%3r,%3r) /%s/" % \
1861 (index + 1, k + 1, min(k + n, len(num_list)),
1862- ','.join(["%5i" % int(i) for i in num_list[k:k + n]])))
1863+ ','.join([("%.15e" % (int(i)/denominator)).replace('e','d') for i in num_list[k:k + n]])))
1864+
1865 my_cs.from_immutable(sorted(matrix_element.get('color_basis').keys())[index])
1866 ret_list.append("C %s" % repr(my_cs))
1867-
1868 return ret_list
1869
1870
1871@@ -1113,6 +1115,7 @@
1872 ','.join([".true." for i in range(configs)])))
1873 return ret_list
1874
1875+
1876 # There is a color basis - create a list showing which JAMPs have
1877 # contributions to which configs
1878
1879@@ -1138,6 +1141,8 @@
1880 # Add this JAMP number to this diag_num
1881 diag_jamp[diag_num] = diag_jamp.setdefault(diag_num, []) + \
1882 [ijamp+1]
1883+ else:
1884+ self.proc_characteristic['single_color'] = False
1885
1886 colamps = ijamp + 1
1887 for iconfig, num_diag in enumerate(mapconfigs):
1888@@ -1154,7 +1159,7 @@
1889
1890 return ret_list
1891
1892- def get_amp2_lines(self, matrix_element, config_map = []):
1893+ def get_amp2_lines(self, matrix_element, config_map = [], replace_dict=None):
1894 """Return the amp2(i) = sum(amp for diag(i))^2 lines"""
1895
1896 nexternal, ninitial = matrix_element.get_nexternal_ninitial()
1897@@ -1195,9 +1200,12 @@
1898 # Not using \sum |M|^2 anymore since this creates troubles
1899 # when ckm is not diagonal due to the JIM mechanism.
1900 if '+' in amp:
1901- line += "(%s)*dconjg(%s)" % (amp, amp)
1902+ amp = "(%s)*dconjg(%s)" % (amp, amp)
1903 else:
1904- line += "%s*dconjg(%s)" % (amp, amp)
1905+ amp = "%s*dconjg(%s)" % (amp, amp)
1906+
1907+ line = line + "%s" % (amp)
1908+ #line += " * get_channel_cut(p, %s) " % (config)
1909 ret_lines.append(line)
1910 else:
1911 for idiag, diag in enumerate(matrix_element.get('diagrams')):
1912@@ -1321,6 +1329,7 @@
1913 # construct the list of color_amplitudes for JAMP to be constructed
1914 # accordingly.
1915 res_list=[]
1916+ max_tmp = 0
1917 for i, amp_order in enumerate(split_order_amps):
1918 col_amps_order = []
1919 for jamp in color_amplitudes:
1920@@ -1332,12 +1341,14 @@
1921 if self.opt['export_format'] in ['madloop_matchbox']:
1922 res_list.extend(self.get_JAMP_lines(col_amps_order,
1923 JAMP_format="JAMP(%s,{0})".format(str(i+1)),
1924- JAMP_formatLC="LNJAMP(%s,{0})".format(str(i+1))))
1925+ JAMP_formatLC="LNJAMP(%s,{0})".format(str(i+1)))[0])
1926 else:
1927- res_list.extend(self.get_JAMP_lines(col_amps_order,
1928- JAMP_format="JAMP(%s,{0})".format(str(i+1))))
1929+ toadd, nb_tmp = self.get_JAMP_lines(col_amps_order,
1930+ JAMP_format="JAMP(%s,{0})".format(str(i+1)))
1931+ res_list.extend(toadd)
1932+ max_tmp = max(max_tmp, nb_tmp)
1933
1934- return res_list
1935+ return res_list, max_tmp
1936
1937
1938 def get_JAMP_lines(self, col_amps, JAMP_format="JAMP(%s)", AMP_format="AMP(%s)",
1939@@ -1361,7 +1372,7 @@
1940 else:
1941 raise MadGraph5Error("Incorrect col_amps argument passed to get_JAMP_lines")
1942
1943-
1944+ all_element = {}
1945 res_list = []
1946 for i, coeff_list in enumerate(color_amplitudes):
1947 # It might happen that coeff_list is empty if this function was
1948@@ -1396,6 +1407,11 @@
1949 for (coefficient, amp_number) in coefs:
1950 if not coefficient:
1951 continue
1952+ value = (1j if coefficient[2] else 1)* coefficient[0] * coefficient[1] * fractions.Fraction(3)**coefficient[3]
1953+ if (i+1, amp_number) not in all_element:
1954+ all_element[(i+1, amp_number)] = value
1955+ else:
1956+ all_element[(i+1, amp_number)] += value
1957 if common_factor:
1958 res = (res + "%s" + AMP_format) % \
1959 (self.coeff(coefficient[0],
1960@@ -1414,8 +1430,151 @@
1961 res = res + ')'
1962
1963 res_list.append(res)
1964+
1965+ if 'jamp_optim' in self.cmd_options:
1966+ jamp_optim = banner_mod.ConfigFile.format_variable(self.cmd_options['jamp_optim'], bool, 'jamp_optim')
1967+ else:
1968+ # class default
1969+ jamp_optim = self.jamp_optim
1970+
1971+ if not jamp_optim:
1972+ return res_list, 0
1973+ else:
1974+ saved = list(res_list)
1975+
1976+ if len(all_element) > 1000:
1977+ logger.info("Computing Color-Flow optimization [%s term]", len(all_element))
1978+ start_time = time.time()
1979+ else:
1980+ start_time = 0
1981+
1982+ res_list = []
1983+ #misc.sprint(len(all_element))
1984+
1985+ self.myjamp_count = 0
1986+ new_mat, defs = self.optimise_jamp(all_element)
1987+ if start_time:
1988+ logger.info("Color-Flow passed to %s term in %ss. Introduce %i contraction", len(new_mat), int(time.time()-start_time), len(defs))
1989+
1990+
1991+ #misc.sprint("number of iteration", self.myjamp_count)
1992+ def format(frac):
1993+ if isinstance(frac, Fraction):
1994+ if frac.denominator == 1:
1995+ return str(frac.numerator)
1996+ else:
1997+ return "%id0/%id0" % (frac.numerator, frac.denominator)
1998+ elif frac.real == frac:
1999+ #misc.sprint(frac.real, frac)
2000+ return str(float(frac.real)).replace('e','d')
2001+ else:
2002+ return str(frac).replace('e','d').replace('j','*imag1')
2003+
2004+
2005+
2006+ for i, amp1, amp2, frac, nb in defs:
2007+ if amp1 > 0:
2008+ amp1 = AMP_format % amp1
2009+ else:
2010+ amp1 = "TMP_JAMP(%d)" % -amp1
2011+ if amp2 > 0:
2012+ amp2 = AMP_format % amp2
2013+ else:
2014+ amp2 = "TMP_JAMP(%d)" % -amp2
2015+
2016+ res_list.append(' TMP_JAMP(%d) = %s + (%s) * %s ! used %d times' % (i,amp1, format(frac), amp2, nb))
2017+
2018+
2019+# misc.sprint(new_mat)
2020+ jamp_res = collections.defaultdict(list)
2021+ max_jamp=0
2022+ for (jamp, var), factor in new_mat.items():
2023+ if var > 0:
2024+ name = AMP_format % var
2025+ else:
2026+ name = "TMP_JAMP(%d)" % -var
2027+ jamp_res[jamp].append("(%s)*%s" % (format(factor), name))
2028+ max_jamp = max(max_jamp, jamp)
2029+
2030+
2031+ for i in range(1,max_jamp+1):
2032+ name = JAMP_format % i
2033+ res_list.append(" %s = %s" %(name, '+'.join(jamp_res[i])))
2034+
2035+ return res_list, len(defs)
2036+
2037+ def optimise_jamp(self, all_element, nb_line=0, nb_col=0, added=0):
2038+ """ optimise problem of type Y = A X
2039+ A is a matrix (all_element)
2040+ X is the fortran name of the input.
2041+ The code iteratively add sub-expression jtemp[sub_add]
2042+ and recall itself (this is add to the X size)
2043+ """
2044+ self.myjamp_count +=1
2045+
2046+ if not nb_line:
2047+ for i,j in all_element:
2048+ if i > nb_line:
2049+ nb_line = i+1
2050+ if j> nb_col:
2051+ nb_col = j+1
2052+
2053+ #misc.sprint(nb_line, nb_col)
2054+
2055+
2056+ max_count = 0
2057+ all_index = []
2058+ operation = collections.defaultdict(lambda: collections.defaultdict(int))
2059+ for i in range(nb_line):
2060+ for j1 in range(-added, nb_col):
2061+ v1 = all_element.get((i,j1), 0)
2062+ if not v1:
2063+ continue
2064+ for j2 in range(j1+1, nb_col):
2065+ R = all_element.get((i,j2), 0)/v1
2066+ if not R:
2067+ continue
2068
2069- return res_list
2070+ #misc.sprint(j1,j2)
2071+ operation[(j1,j2)][R] +=1
2072+ if operation[(j1,j2)][R] > max_count:
2073+ max_count = operation[(j1,j2)][R]
2074+ all_index = [(j1,j2, R)]
2075+ elif operation[(j1,j2)][R] == max_count:
2076+ all_index.append((j1,j2, R))
2077+ if max_count <= 1:
2078+ return all_element, []
2079+ #added += 1
2080+ #misc.sprint(max_count, len(all_index))
2081+ #misc.sprint(operation)
2082+ to_add = []
2083+ for index in all_index:
2084+ j1,j2,R = index
2085+ first = True
2086+ for i in range(nb_line):
2087+ v1 = all_element.get((i,j1), 0)
2088+ v2 = all_element.get((i,j2), 0)
2089+ if not v1 or not v2:
2090+ continue
2091+ if v2/v1 == R:
2092+ if first:
2093+ first = False
2094+ added +=1
2095+ to_add.append((added,j1,j2,R, max_count))
2096+
2097+ all_element[(i,-added)] = v1
2098+ del all_element[(i,j1)] #= 0
2099+ del all_element[(i,j2)] #= 0
2100+
2101+ logger.log(5,"Define %d new shortcut reused %d times", len(to_add), max_count)
2102+ new_element, new_def = self.optimise_jamp(all_element, nb_line=nb_line, nb_col=nb_col, added=added)
2103+ for one_def in to_add:
2104+ new_def.insert(0, one_def)
2105+ return new_element, new_def
2106+
2107+
2108+
2109+
2110
2111 def get_pdf_lines(self, matrix_element, ninitial, subproc_group = False):
2112 """Generate the PDF lines for the auto_dsig.f file"""
2113@@ -1880,8 +2039,9 @@
2114 if not version:# not linux
2115 version = 14 # set version to remove MACFLAG
2116 else:
2117- version = int(version.split('.')[1])
2118- if version >= 14:
2119+ majversion, version = [int(x) for x in version.split('.',3)[:2]]
2120+
2121+ if majversion >= 11 or (majversion ==10 and version >= 14):
2122 for_update['MACFLAG'] = '-mmacosx-version-min=10.8' if is_lc else ''
2123
2124 if not root_dir:
2125@@ -2536,7 +2696,7 @@
2126 if len(split_orders)==0:
2127 replace_dict['nSplitOrders']=''
2128 # Extract JAMP lines
2129- jamp_lines = self.get_JAMP_lines(matrix_element)
2130+ jamp_lines, nb_tmp_jamp = self.get_JAMP_lines(matrix_element)
2131 # Consider the output of a dummy order 'ALL_ORDERS' for which we
2132 # set all amplitude order to weight 1 and only one squared order
2133 # contribution which is of course ALL_ORDERS=2.
2134@@ -2545,6 +2705,8 @@
2135 replace_dict['chosen_so_configs'] = '.TRUE.'
2136 replace_dict['nSqAmpSplitOrders']=1
2137 replace_dict['split_order_str_list']=''
2138+ replace_dict['nb_temp_jamp'] = nb_tmp_jamp
2139+
2140 else:
2141 squared_orders, amp_orders = matrix_element.get_split_orders_mapping()
2142 replace_dict['nAmpSplitOrders']=len(amp_orders)
2143@@ -2556,9 +2718,9 @@
2144 sqamp_so = self.get_split_orders_lines(squared_orders,'SQSPLITORDERS')
2145 replace_dict['ampsplitorders']='\n'.join(amp_so)
2146 replace_dict['sqsplitorders']='\n'.join(sqamp_so)
2147- jamp_lines = self.get_JAMP_lines_split_order(\
2148+ jamp_lines, nb_tmp_jamp = self.get_JAMP_lines_split_order(\
2149 matrix_element,amp_orders,split_order_names=split_orders)
2150-
2151+ replace_dict['nb_temp_jamp'] = nb_tmp_jamp
2152 # Now setup the array specifying what squared split order is chosen
2153 replace_dict['chosen_so_configs']=self.set_chosen_SO_index(
2154 matrix_element.get('processes')[0],squared_orders)
2155@@ -2733,7 +2895,7 @@
2156 else:
2157 raise MadGraph5Error(error_msg % 'col_amps')
2158
2159- text = super(ProcessExporterFortranMatchBox, self).get_JAMP_lines(col_amps,
2160+ text, nb = super(ProcessExporterFortranMatchBox, self).get_JAMP_lines(col_amps,
2161 JAMP_format=JAMP_format,
2162 AMP_format=AMP_format,
2163 split=-1)
2164@@ -2749,12 +2911,13 @@
2165 to_add.append( (coefficient, amp_number) )
2166 LC_col_amps.append(to_add)
2167
2168- text += super(ProcessExporterFortranMatchBox, self).get_JAMP_lines(LC_col_amps,
2169+ text2, nb = super(ProcessExporterFortranMatchBox, self).get_JAMP_lines(LC_col_amps,
2170 JAMP_format=JAMP_formatLC,
2171 AMP_format=AMP_format,
2172 split=-1)
2173+ text += text2
2174
2175- return text
2176+ return text, 0
2177
2178
2179
2180@@ -2767,6 +2930,7 @@
2181 MadGraph v4 - MadWeight format."""
2182
2183 matrix_file="matrix_standalone_v4.inc"
2184+ jamp_optim = False
2185
2186 def copy_template(self, model):
2187 """Additional actions needed for setup of Template
2188@@ -3238,7 +3402,7 @@
2189 replace_dict['helas_calls'] = "\n".join(helas_calls)
2190
2191 # Extract JAMP lines
2192- jamp_lines = self.get_JAMP_lines(matrix_element)
2193+ jamp_lines, nb = self.get_JAMP_lines(matrix_element)
2194 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
2195
2196 replace_dict['template_file'] = os.path.join(_file_path, \
2197@@ -3543,6 +3707,29 @@
2198 matrix_file = "matrix_madevent_v4.inc"
2199 done_warning_tchannel = False
2200
2201+ default_opt = {'clean': False, 'complex_mass':False,
2202+ 'export_format':'madevent', 'mp': False,
2203+ 'v5_model': True,
2204+ 'output_options':{},
2205+ 'hel_recycling': False
2206+ }
2207+ jamp_optim = True
2208+
2209+ def __init__(self, dir_path = "", opt=None):
2210+
2211+ super(ProcessExporterFortranME, self).__init__(dir_path, opt)
2212+
2213+ # check and format the hel_recycling options as it should if provided
2214+ if opt and isinstance(opt['output_options'], dict) and \
2215+ 'hel_recycling' in opt['output_options']:
2216+ self.opt['hel_recycling'] = banner_mod.ConfigFile.format_variable(
2217+ opt['output_options']['hel_recycling'], bool, 'hel_recycling')
2218+
2219+ if opt and isinstance(opt['output_options'], dict) and \
2220+ 't_strategy' in opt['output_options']:
2221+ self.opt['t_strategy'] = banner_mod.ConfigFile.format_variable(
2222+ opt['output_options']['t_strategy'], int, 't_strategy')
2223+
2224 # helper function for customise helas writter
2225 @staticmethod
2226 def custom_helas_call(call, arg):
2227@@ -3708,8 +3895,6 @@
2228 if not self.model:
2229 self.model = matrix_element.get('processes')[0].get('model')
2230
2231-
2232-
2233 #os.chdir(path)
2234 # Create the directory PN_xx_xxxxx in the specified path
2235 subprocdir = "P%s" % matrix_element.get('processes')[0].shell_string()
2236@@ -3736,8 +3921,12 @@
2237 self.write_driver(writers.FortranWriter(filename),ncomb,n_grouped_proc=1,
2238 v5=self.opt['v5_model'])
2239
2240+
2241 # Create the matrix.f file, auto_dsig.f file and all inc files
2242- filename = pjoin(Ppath, 'matrix.f')
2243+ if self.opt['hel_recycling']:
2244+ filename = pjoin(Ppath, 'matrix_orig.f')
2245+ else:
2246+ filename = pjoin(Ppath, 'matrix.f')
2247 calls, ncolor = \
2248 self.write_matrix_element_v4(writers.FortranWriter(filename),
2249 matrix_element, fortran_model, subproc_number = me_number)
2250@@ -4084,7 +4273,8 @@
2251 # The proc prefix is not used for MadEvent output so it can safely be set
2252 # to an empty string.
2253 replace_dict = {'proc_prefix':''}
2254-
2255+
2256+
2257 # Extract helas calls
2258 helas_calls = fortran_model.get_matrix_element_calls(\
2259 matrix_element)
2260@@ -4189,7 +4379,7 @@
2261 replace_dict['wavefunctionsize'] = 6
2262
2263 # Extract amp2 lines
2264- amp2_lines = self.get_amp2_lines(matrix_element, config_map)
2265+ amp2_lines = self.get_amp2_lines(matrix_element, config_map, replace_dict)
2266 replace_dict['amp2_lines'] = '\n'.join(amp2_lines)
2267
2268 # The JAMP definition depends on the splitting order
2269@@ -4198,6 +4388,8 @@
2270 squared_orders, amp_orders = matrix_element.get_split_orders_mapping()
2271 replace_dict['chosen_so_configs']=self.set_chosen_SO_index(
2272 matrix_element.get('processes')[0],squared_orders)
2273+ replace_dict['select_configs_if'] = ' IF (CHOSEN_SO_CONFIGS(SQSOINDEX%(proc_id)s(M,N))) THEN' % replace_dict
2274+ replace_dict['select_configs_endif'] = ' endif'
2275 else:
2276 # Consider the output of a dummy order 'ALL_ORDERS' for which we
2277 # set all amplitude order to weight 1 and only one squared order
2278@@ -4205,6 +4397,9 @@
2279 squared_orders = [(2,),]
2280 amp_orders = [((1,),tuple(range(1,ngraphs+1)))]
2281 replace_dict['chosen_so_configs'] = '.TRUE.'
2282+ # addtionally set the function to NOT be called
2283+ replace_dict['select_configs_if'] = ''
2284+ replace_dict['select_configs_endif'] = ''
2285
2286 replace_dict['nAmpSplitOrders']=len(amp_orders)
2287 replace_dict['nSqAmpSplitOrders']=len(squared_orders)
2288@@ -4219,10 +4414,11 @@
2289
2290 # Extract JAMP lines
2291 # If no split_orders then artificiall add one entry called 'ALL_ORDERS'
2292- jamp_lines = self.get_JAMP_lines_split_order(\
2293+ jamp_lines, nb_temp = self.get_JAMP_lines_split_order(\
2294 matrix_element,amp_orders,split_order_names=
2295 split_orders if len(split_orders)>0 else ['ALL_ORDERS'])
2296 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
2297+ replace_dict['nb_temp_jamp'] = nb_temp
2298
2299 replace_dict['template_file'] = pjoin(_file_path, \
2300 'iolibs/template_files/%s' % self.matrix_file)
2301@@ -4595,7 +4791,7 @@
2302 For s-channels, we need to output one PDG for each subprocess in
2303 the subprocess group, in order to be able to pick the right
2304 one for multiprocesses."""
2305-
2306+
2307 lines = []
2308
2309 s_and_t_channels = []
2310@@ -4635,12 +4831,18 @@
2311 else:
2312 stchannels.append((empty_verts, None))
2313
2314+
2315 # For t-channels, just need the first non-empty one
2316 tchannels = [t for s,t in stchannels if t != None][0]
2317-
2318+
2319+ # pass to ping-pong strategy for t-channel for 3 ore more T-channel
2320+ # this is directly related to change in genps.f
2321+ tstrat = self.opt.get('t_strategy', 0)
2322+ tchannels, tchannels_strategy = ProcessExporterFortranME.reorder_tchannels(tchannels, tstrat, self.model)
2323+
2324 # For s_and_t_channels (to be used later) use only first config
2325 s_and_t_channels.append([[s for s,t in stchannels if t != None][0],
2326- tchannels])
2327+ tchannels, tchannels_strategy])
2328
2329 # Make sure empty_verts is same length as real vertices
2330 if any([s for s,t in stchannels]):
2331@@ -4663,6 +4865,7 @@
2332 # Correspondance between the config and the diagram = amp2
2333 lines.append("data mapconfig(%d)/%d/" % (nconfigs,
2334 mapconfigs[iconfig]))
2335+ lines.append("data tstrategy(%d)/%d/" % (nconfigs, tchannels_strategy))
2336 # Number of QCD couplings in this diagram
2337 nqcd = 0
2338 for h in helas_diags:
2339@@ -4715,7 +4918,321 @@
2340 writer.writelines(lines)
2341
2342 return s_and_t_channels, nqcd_list
2343-
2344+
2345+
2346+
2347+ #===========================================================================
2348+ # reoder t-channels
2349+ #===========================================================================
2350+
2351+ #ordering = 0
2352+ @staticmethod
2353+ def reorder_tchannels(tchannels, tstrat, model):
2354+ # no need to modified anything if 1 or less T-Channel
2355+ #Note that this counts the number of vertex (one more vertex compare to T)
2356+ #ProcessExporterFortranME.ordering +=1
2357+ if len(tchannels) < 3 or tstrat == 2 or not model:
2358+ return tchannels, 2
2359+ elif tstrat == 1:
2360+ return ProcessExporterFortranME.reorder_tchannels_flipside(tchannels), 1
2361+ elif tstrat == -2:
2362+ return ProcessExporterFortranME.reorder_tchannels_pingpong(tchannels), -2
2363+ elif tstrat == -1:
2364+ return ProcessExporterFortranME.reorder_tchannels_pingpong(tchannels, 1), -1
2365+ elif len(tchannels) < 4:
2366+ #
2367+ first = tchannels[0]['legs'][1]['number']
2368+ t1 = tchannels[0]['legs'][-1]['id']
2369+ last = tchannels[-1]['legs'][1]['number']
2370+ t2 = tchannels[-1]['legs'][0]['id']
2371+ m1 = model.get_particle(t1).get('mass') == 'ZERO'
2372+ m2 = model.get_particle(t2).get('mass') == 'ZERO'
2373+ if m2 and not m1:
2374+ return ProcessExporterFortranME.reorder_tchannels_flipside(tchannels), 1
2375+ elif m1 and not m2:
2376+ return tchannels, 2
2377+ elif first < last:
2378+ return ProcessExporterFortranME.reorder_tchannels_flipside(tchannels), 1
2379+ else:
2380+ return tchannels, 2
2381+ else:
2382+ first = tchannels[0]['legs'][1]['number']
2383+ t1 = tchannels[0]['legs'][-1]['id']
2384+ last = tchannels[-1]['legs'][1]['number']
2385+ t2 = tchannels[-1]['legs'][0]['id']
2386+ m1 = model.get_particle(t1).get('mass') == 'ZERO'
2387+ m2 = model.get_particle(t2).get('mass') == 'ZERO'
2388+
2389+ t12 = tchannels[1]['legs'][-1]['id']
2390+ m12 = model.get_particle(t12).get('mass') == 'ZERO'
2391+ t22 = tchannels[-2]['legs'][0]['id']
2392+ m22 = model.get_particle(t22).get('mass') == 'ZERO'
2393+ if m2 and not m1:
2394+ if m22:
2395+ return ProcessExporterFortranME.reorder_tchannels_flipside(tchannels), 1
2396+ else:
2397+ return ProcessExporterFortranME.reorder_tchannels_pingpong(tchannels), -2
2398+ elif m1 and not m2:
2399+ if m12:
2400+ return tchannels, 2
2401+ else:
2402+ return ProcessExporterFortranME.reorder_tchannels_pingpong(tchannels), -2
2403+ elif m1 and m2 and len(tchannels) == 4 and not m12: # 3 T propa
2404+ return ProcessExporterFortranME.reorder_tchannels_pingpong(tchannels), -2
2405+ # this case seems quite sensitive we tested method 2 specifically and this was not helping in general
2406+ elif not m1 and not m2 and len(tchannels) == 4 and m12:
2407+ if first < last:
2408+ return ProcessExporterFortranME.reorder_tchannels_flipside(tchannels), 1
2409+ return tchannels, 2
2410+ else:
2411+ return ProcessExporterFortranME.reorder_tchannels_pingpong(tchannels), -2
2412+
2413+
2414+
2415+
2416+ @staticmethod
2417+ def reorder_tchannels_flipside(tchannels):
2418+ """change the tchannel ordering to pass to a ping-pong strategy.
2419+ assume ninitial == 2
2420+
2421+ We assume that we receive something like this
2422+
2423+ 1 ----- X ------- -2
2424+ |
2425+ | (-X)
2426+ |
2427+ X -------- 4
2428+ |
2429+ | (-X-1)
2430+ |
2431+ X --------- -1
2432+
2433+ X---------- 3
2434+ |
2435+ | (-N+2)
2436+ |
2437+ X --------- L
2438+ |
2439+ | (-N+1)
2440+ |
2441+ -N ----- X ------- P
2442+
2443+ coded as
2444+ (1 -2 > -X) (-X 4 > -X-1) (-X-1 -1 > -X-2) ...
2445+ ((-N+3) 3 > (-N+2)) ((-n+2) L > (-n+1)) ((-n+1) P > -N)
2446+
2447+ we want to convert this as:
2448+ -N ----- X ------- -2
2449+ |
2450+ | (-N+1)
2451+ |
2452+ X -------- 4
2453+ |
2454+ | (-N+2)
2455+ |
2456+ X --------- -1
2457+
2458+ X---------- 3
2459+ |
2460+ | (-X-1)
2461+ |
2462+ X --------- L
2463+ |
2464+ | (-X)
2465+ |
2466+ 2 ----- X ------- P
2467+
2468+ coded as
2469+ ( 2 P > -X) (-X L > -X-1) (-X-1 3 > -X-2)... (-X-L -2 > -N)
2470+ """
2471+
2472+ # no need to modified anything if 1 or less T-Channel
2473+ #Note that this counts the number of vertex (one more vertex compare to T)
2474+ if len(tchannels) < 2:
2475+ return tchannels
2476+
2477+ out = []
2478+ oldid2new = {}
2479+
2480+ # initialisation
2481+ # id of the first T-channel (-X)
2482+ propa_id = tchannels[0]['legs'][-1]['number']
2483+ #
2484+ # Setup the last vertex to refenence the second id beam
2485+ # -N (need to setup it to 2.
2486+ initialid = tchannels[-1]['legs'][-1]['number']
2487+ oldid2new[initialid] = 2
2488+ oldid2new[1] = initialid
2489+
2490+ i = 0
2491+ while tchannels:
2492+ old_vert = tchannels.pop()
2493+
2494+ #copy the vertex /leglist to avoid side effects
2495+ new_vert = base_objects.Vertex(old_vert)
2496+ new_vert['legs'] = base_objects.LegList([base_objects.Leg(l) for l in old_vert['legs']])
2497+ # vertex taken from the bottom we have
2498+ # (-N+1 X > -N) we need to flip to pass to
2499+ # -N X > -N+1 (and then relabel -N and -N+1
2500+ legs = new_vert['legs'] # shorcut
2501+ id1 = legs[0]['number']
2502+ id2 = legs[1]['number']
2503+ id3 = legs[2]['number']
2504+ # to be secure we also support (X -N+1 > -N)
2505+ if id3 == id2 -1 and id1 !=1:
2506+ legs[0], legs[1] = legs[1], legs[0]
2507+ #flipping side
2508+ legs[0], legs[2] = legs[2], legs[0]
2509+
2510+ # the only new relabelling is the last element of the list
2511+ # always thanks to the above flipping
2512+ old_propa_id = new_vert['legs'][-1]['number']
2513+ oldid2new[old_propa_id] = propa_id
2514+
2515+
2516+ #pass to new convention for leg numbering:
2517+ for l in new_vert['legs']:
2518+ if l['number'] in oldid2new:
2519+ l['number'] = oldid2new[l['number']]
2520+
2521+ # new_vert is now ready
2522+ out.append(new_vert)
2523+ # prepare next iteration
2524+ propa_id -=1
2525+ i +=1
2526+
2527+ return out
2528+
2529+ @staticmethod
2530+ def reorder_tchannels_pingpong(tchannels, id=2):
2531+ """change the tchannel ordering to pass to a ping-pong strategy.
2532+ assume ninitial == 2
2533+
2534+ We assume that we receive something like this
2535+
2536+ 1 ----- X ------- -2
2537+ |
2538+ | (-X)
2539+ |
2540+ X -------- 4
2541+ |
2542+ | (-X-1)
2543+ |
2544+ X --------- -1
2545+
2546+ X---------- 3
2547+ |
2548+ | (-N+2)
2549+ |
2550+ X --------- L
2551+ |
2552+ | (-N+1)
2553+ |
2554+ -N ----- X ------- P
2555+
2556+ coded as
2557+ (1 -2 > -X) (-X 4 > -X-1) (-X-1 -1 > -X-2) ...
2558+ ((-N+3) 3 > (-N+2)) ((-n+2) L > (-n+1)) ((-n+1) P > -N)
2559+
2560+ we want to convert this as:
2561+ 1 ----- X ------- -2
2562+ |
2563+ | (-X)
2564+ |
2565+ X -------- 4
2566+ |
2567+ | (-X-2)
2568+ |
2569+ X --------- -1
2570+
2571+ X---------- 3
2572+ |
2573+ | (-X-3)
2574+ |
2575+ X --------- L
2576+ |
2577+ | (-X-1)
2578+ |
2579+ 2 ----- X ------- P
2580+
2581+ coded as
2582+ (1 -2 > -X) (2 P > -X-1) (-X 4 > -X-2) (-X-1 L > -X-3) ...
2583+ """
2584+
2585+ # no need to modified anything if 1 or less T-Channel
2586+ #Note that this counts the number of vertex (one more vertex compare to T)
2587+ if len(tchannels) < 2:
2588+ return tchannels
2589+
2590+ out = []
2591+ oldid2new = {}
2592+
2593+ # initialisation
2594+ # id of the first T-channel (-X)
2595+ propa_id = tchannels[0]['legs'][-1]['number']
2596+ #
2597+ # Setup the last vertex to refenence the second id beam
2598+ # -N (need to setup it to 2.
2599+ initialid = tchannels[-1]['legs'][-1]['number']
2600+ oldid2new[initialid] = id
2601+
2602+
2603+
2604+ i = 0
2605+ while tchannels:
2606+ #ping pong by taking first/last element in aternance
2607+ if id ==2:
2608+ if i % 2 == 0:
2609+ old_vert = tchannels.pop(0)
2610+ else:
2611+ old_vert = tchannels.pop()
2612+ else:
2613+ if i % 2 != 0:
2614+ old_vert = tchannels.pop(0)
2615+ else:
2616+ old_vert = tchannels.pop()
2617+
2618+ #copy the vertex /leglist to avoid side effects
2619+ new_vert = base_objects.Vertex(old_vert)
2620+ new_vert['legs'] = base_objects.LegList([base_objects.Leg(l) for l in old_vert['legs']])
2621+ # if vertex taken from the bottom we have
2622+ # (-N+1 X > -N) we need to flip to pass to
2623+ # -N X > -N+1 (and then relabel -N and -N+1
2624+ # to be secure we also support (X -N+1 > -N)
2625+ if (i % 2 ==1 and id ==2) or (i %2 == 0 and id ==1):
2626+ legs = new_vert['legs'] # shorcut
2627+ id1 = legs[0]['number']
2628+ id2 = legs[1]['number']
2629+ if id1 > id2:
2630+ legs[0], legs[1] = legs[1], legs[0]
2631+ else:
2632+ legs[0], legs[2] = legs[2], legs[0]
2633+
2634+ # the only new relabelling is the last element of the list
2635+ # always thanks to the above flipping
2636+ old_propa_id = new_vert['legs'][-1]['number']
2637+ oldid2new[old_propa_id] = propa_id
2638+
2639+ if i==0 and id==1:
2640+ legs[0]['number'] = 2
2641+
2642+ #pass to new convention for leg numbering:
2643+ for l in new_vert['legs']:
2644+ if l['number'] in oldid2new:
2645+ l['number'] = oldid2new[l['number']]
2646+
2647+ # new_vert is now ready
2648+ out.append(new_vert)
2649+ # prepare next iteration
2650+ propa_id -=1
2651+ i +=1
2652+
2653+ return out
2654+
2655+
2656+
2657+
2658+
2659 #===========================================================================
2660 # write_decayBW_file
2661 #===========================================================================
2662@@ -4828,8 +5345,9 @@
2663 def write_symmetry(self, writer, v5=True):
2664 """Write the SubProcess/driver.f file for ME"""
2665
2666+
2667 path = pjoin(_file_path,'iolibs','template_files','madevent_symmetry.f')
2668-
2669+
2670 if self.model_name == 'mssm' or self.model_name.startswith('mssm-'):
2671 card = 'Source/MODEL/MG5_param.dat'
2672 else:
2673@@ -5036,6 +5554,14 @@
2674
2675 matrix_file = "matrix_madevent_group_v4.inc"
2676 grouped_mode = 'madevent'
2677+ default_opt = {'clean': False, 'complex_mass':False,
2678+ 'export_format':'madevent', 'mp': False,
2679+ 'v5_model': True,
2680+ 'output_options':{},
2681+ 'hel_recycling': True
2682+ }
2683+
2684+
2685 #===========================================================================
2686 # generate_subprocess_directory
2687 #===========================================================================
2688@@ -5096,16 +5622,54 @@
2689 self.write_driver(writers.FortranWriter(filename),ncomb,
2690 n_grouped_proc=len(matrix_elements), v5=self.opt['v5_model'])
2691
2692+ self.proc_characteristic['hel_recycling'] = self.opt['hel_recycling']
2693 for ime, matrix_element in \
2694 enumerate(matrix_elements):
2695- filename = 'matrix%d.f' % (ime+1)
2696- calls, ncolor = \
2697- self.write_matrix_element_v4(writers.FortranWriter(filename),
2698- matrix_element,
2699- fortran_model,
2700- proc_id=str(ime+1),
2701- config_map=subproc_group.get('diagram_maps')[ime],
2702- subproc_number=group_number)
2703+ if self.opt['hel_recycling']:
2704+ filename = 'matrix%d_orig.f' % (ime+1)
2705+ replace_dict = self.write_matrix_element_v4(None,
2706+ matrix_element,
2707+ fortran_model,
2708+ proc_id=str(ime+1),
2709+ config_map=subproc_group.get('diagram_maps')[ime],
2710+ subproc_number=group_number)
2711+ calls,ncolor = replace_dict['return_value']
2712+ tfile = open(replace_dict['template_file']).read()
2713+ file = tfile % replace_dict
2714+ # Add the split orders helper functions.
2715+ file = file + '\n' + open(replace_dict['template_file2'])\
2716+ .read()%replace_dict
2717+ # Write the file
2718+ writer = writers.FortranWriter(filename)
2719+ writer.writelines(file)
2720+
2721+ #
2722+ # write the dedicated template for helicity recycling
2723+ #
2724+ tfile = open(replace_dict['template_file'].replace('.inc',"_hel.inc")).read()
2725+ file = tfile % replace_dict
2726+ # Add the split orders helper functions.
2727+ file = file + '\n' + open(replace_dict['template_file2'])\
2728+ .read()%replace_dict
2729+ # Write the file
2730+ writer = writers.FortranWriter('template_matrix%d.f' % (ime+1))
2731+ writer.uniformcase = False
2732+ writer.writelines(file)
2733+
2734+
2735+
2736+
2737+ else:
2738+ filename = 'matrix%d.f' % (ime+1)
2739+ calls, ncolor = \
2740+ self.write_matrix_element_v4(writers.FortranWriter(filename),
2741+ matrix_element,
2742+ fortran_model,
2743+ proc_id=str(ime+1),
2744+ config_map=subproc_group.get('diagram_maps')[ime],
2745+ subproc_number=group_number)
2746+
2747+
2748
2749 filename = 'auto_dsig%d.f' % (ime+1)
2750 self.write_auto_dsig_file(writers.FortranWriter(filename),
2751@@ -5323,6 +5887,13 @@
2752 replace_dict['nb_spin_state1'] = s1
2753 replace_dict['nb_spin_state2'] = s2
2754
2755+ printzeroamp = []
2756+ for iproc in range(len(matrix_elements)):
2757+ printzeroamp.append(\
2758+ " call print_zero_amp_%i()" % ( iproc + 1))
2759+ replace_dict['print_zero_amp'] = "\n".join(printzeroamp)
2760+
2761+
2762 if writer:
2763 file = open(pjoin(_file_path, \
2764 'iolibs/template_files/super_auto_dsig_group_v4.inc')).read()
2765
2766=== modified file 'madgraph/iolibs/file_writers.py'
2767--- madgraph/iolibs/file_writers.py 2020-11-25 20:43:03 +0000
2768+++ madgraph/iolibs/file_writers.py 2021-01-30 10:13:29 +0000
2769@@ -202,6 +202,7 @@
2770 number_re = re.compile('^(?P<num>\d+)\s+(?P<rest>.*)')
2771 line_cont_char = '$'
2772 comment_char = 'c'
2773+ uniformcase = True #force everyting to be lower/upper case
2774 downcase = False
2775 line_length = 71
2776 max_split = 20
2777@@ -257,23 +258,24 @@
2778 # Replace all double quotes by single quotes
2779 myline = myline.replace('\"', '\'')
2780 # Downcase or upcase Fortran code, except for quotes
2781- splitline = myline.split('\'')
2782- myline = ""
2783- i = 0
2784- while i < len(splitline):
2785- if i % 2 == 1:
2786- # This is a quote - check for escaped \'s
2787- while splitline[i] and splitline[i][-1] == '\\':
2788- splitline[i] = splitline[i] + '\'' + splitline.pop(i + 1)
2789- else:
2790- # Otherwise downcase/upcase
2791- if FortranWriter.downcase:
2792- splitline[i] = splitline[i].lower()
2793+ if self.uniformcase:
2794+ splitline = myline.split('\'')
2795+ myline = ""
2796+ i = 0
2797+ while i < len(splitline):
2798+ if i % 2 == 1:
2799+ # This is a quote - check for escaped \'s
2800+ while splitline[i] and splitline[i][-1] == '\\':
2801+ splitline[i] = splitline[i] + '\'' + splitline.pop(i + 1)
2802 else:
2803- splitline[i] = splitline[i].upper()
2804- i = i + 1
2805-
2806- myline = "\'".join(splitline).rstrip()
2807+ # Otherwise downcase/upcase
2808+ if FortranWriter.downcase:
2809+ splitline[i] = splitline[i].lower()
2810+ else:
2811+ splitline[i] = splitline[i].upper()
2812+ i = i + 1
2813+
2814+ myline = "\'".join(splitline).rstrip()
2815
2816 # Check if line starts with dual keyword and adjust indent
2817 if self.__keyword_list and re.search(self.keyword_pairs[\
2818
2819=== modified file 'madgraph/iolibs/gen_infohtml.py'
2820--- madgraph/iolibs/gen_infohtml.py 2019-04-17 14:39:47 +0000
2821+++ madgraph/iolibs/gen_infohtml.py 2021-01-30 10:13:29 +0000
2822@@ -243,7 +243,8 @@
2823 nb_diag = 0
2824
2825 pat = re.compile(r'''Amplitude\(s\) for diagram number (\d+)''' )
2826-
2827+ if not os.path.exists(path):
2828+ path = os.path.join(self.dir, 'SubProcesses', proc, 'matrix%s_orig.f' % id)
2829 text = open(path).read()
2830 for match in re.finditer(pat, text):
2831 pass
2832
2833=== modified file 'madgraph/iolibs/template_files/auto_dsig_v4.inc'
2834--- madgraph/iolibs/template_files/auto_dsig_v4.inc 2019-06-10 19:05:58 +0000
2835+++ madgraph/iolibs/template_files/auto_dsig_v4.inc 2021-01-30 10:13:29 +0000
2836@@ -156,3 +156,9 @@
2837 %(read_write_good_hel)s
2838
2839 ## }
2840+
2841+
2842+ SUBROUTINE PRINT_ZERO_AMP%(proc_id)s()
2843+
2844+ return
2845+ end
2846\ No newline at end of file
2847
2848=== modified file 'madgraph/iolibs/template_files/b_sf_xxx_fks.inc'
2849--- madgraph/iolibs/template_files/b_sf_xxx_fks.inc 2016-09-08 23:15:34 +0000
2850+++ madgraph/iolibs/template_files/b_sf_xxx_fks.inc 2021-01-30 10:13:29 +0000
2851@@ -99,6 +99,7 @@
2852 INTEGER I,J
2853 REAL*8 DENOM(NCOLOR1), CF(NCOLOR2,NCOLOR1)
2854 COMPLEX*16 ZTEMP, AMP(NGRAPHS), JAMP1(NCOLOR1), JAMP2(NCOLOR2)
2855+ COMPLEX*16 TMP_JAMP(%(nb_temp_jamp)i)
2856 C
2857 C GLOBAL VARIABLES
2858 C
2859
2860=== modified file 'madgraph/iolibs/template_files/born_fks.inc'
2861--- madgraph/iolibs/template_files/born_fks.inc 2020-01-16 13:45:20 +0000
2862+++ madgraph/iolibs/template_files/born_fks.inc 2021-01-30 10:13:29 +0000
2863@@ -166,8 +166,9 @@
2864 INTEGER IC(NEXTERNAL-1),nmo
2865 parameter (nmo=nexternal-1)
2866 data ic /nmo*1/
2867- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
2868+ REAL*8 CF(NCOLOR,NCOLOR)
2869 COMPLEX*16 ZTEMP, AMP(NGRAPHS), JAMP(NCOLOR), W(%(wavefunctionsize)d,NWAVEFUNCS), jamph(2, ncolor)
2870+ COMPLEX*16 TMP_JAMP(%(nb_temp_jamp)i)
2871 C
2872 C GLOBAL VARIABLES
2873 C
2874@@ -249,7 +250,7 @@
2875 DO J = 1, NCOLOR
2876 ZTEMP = ZTEMP + CF(J,I)*JAMP(J)
2877 ENDDO
2878- BORNS(2-(1+back_hel*ihel)/2)=BORNS(2-(1+back_hel*ihel)/2)+ZTEMP*DCONJG(JAMP(I))/DENOM(I)
2879+ BORNS(2-(1+back_hel*ihel)/2)=BORNS(2-(1+back_hel*ihel)/2)+ZTEMP*DCONJG(JAMP(I))
2880 ENDDO
2881 Do I = 1, NGRAPHS
2882 amp2(i)=amp2(i)+amp(i)*dconjg(amp(i))
2883@@ -266,7 +267,7 @@
2884 DO J = 1, NCOLOR
2885 ZTEMP = ZTEMP + CF(J,I)*JAMPH(2,J)
2886 ENDDO
2887- BORNTILDE = BORNTILDE + ZTEMP*DCONJG(JAMPH(1,I))/DENOM(I)
2888+ BORNTILDE = BORNTILDE + ZTEMP*DCONJG(JAMPH(1,I))
2889 ENDDO
2890 if (glu_ij.ne.0) nhel(glu_ij) = back_hel
2891 END
2892
2893=== modified file 'madgraph/iolibs/template_files/born_fks_hel.inc'
2894--- madgraph/iolibs/template_files/born_fks_hel.inc 2016-09-08 23:15:34 +0000
2895+++ madgraph/iolibs/template_files/born_fks_hel.inc 2021-01-30 10:13:29 +0000
2896@@ -104,6 +104,7 @@
2897 INTEGER I,J
2898 REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
2899 COMPLEX*16 ZTEMP, AMP(NGRAPHS), JAMP(NCOLOR)
2900+ COMPLEX*16 TMP_JAMP(%(nb_temp_jamp)i)
2901 C
2902 C GLOBAL VARIABLES
2903 C
2904
2905=== modified file 'madgraph/iolibs/template_files/check_sa.f'
2906--- madgraph/iolibs/template_files/check_sa.f 2015-06-18 08:24:43 +0000
2907+++ madgraph/iolibs/template_files/check_sa.f 2021-01-30 10:13:29 +0000
2908@@ -177,7 +177,7 @@
2909 P(2,2)=0d0
2910 P(3,2)=-mom
2911
2912- call rambo(nexternal-2,energy,pmass(3),prambo,WGT)
2913+ call rambo(nexternal-2,energy,pmass(nincoming+1),prambo,WGT)
2914 DO I=3, NEXTERNAL
2915 P(0,I)=PRAMBO(4,I-2)
2916 P(1,I)=PRAMBO(1,I-2)
2917
2918=== modified file 'madgraph/iolibs/template_files/check_sa_splitOrders.f'
2919--- madgraph/iolibs/template_files/check_sa_splitOrders.f 2015-04-09 22:42:44 +0000
2920+++ madgraph/iolibs/template_files/check_sa_splitOrders.f 2021-01-30 10:13:29 +0000
2921@@ -201,7 +201,7 @@
2922 P(2,2)=0d0
2923 P(3,2)=-mom
2924
2925- call rambo(nexternal-2,energy,pmass(3),prambo,WGT)
2926+ call rambo(nexternal-2,energy,pmass(nincoming+1),prambo,WGT)
2927 DO I=3, NEXTERNAL
2928 P(0,I)=PRAMBO(4,I-2)
2929 P(1,I)=PRAMBO(1,I-2)
2930
2931=== modified file 'madgraph/iolibs/template_files/loop/check_sa.inc'
2932--- madgraph/iolibs/template_files/loop/check_sa.inc 2016-05-22 02:36:25 +0000
2933+++ madgraph/iolibs/template_files/loop/check_sa.inc 2021-01-30 10:13:29 +0000
2934@@ -402,7 +402,7 @@
2935 P(2,2)=0d0
2936 P(3,2)=-mom
2937
2938- call rambo(nexternal-2,energy,pmass(3),prambo,WGT)
2939+ call rambo(nexternal-2,energy,pmass(nexternal+1),prambo,WGT)
2940 DO I=3, NEXTERNAL
2941 P(0,I)=PRAMBO(4,I-2)
2942 P(1,I)=PRAMBO(1,I-2)
2943
2944=== modified file 'madgraph/iolibs/template_files/loop/check_sa_loop_induced.inc'
2945--- madgraph/iolibs/template_files/loop/check_sa_loop_induced.inc 2016-05-22 02:36:25 +0000
2946+++ madgraph/iolibs/template_files/loop/check_sa_loop_induced.inc 2021-01-30 10:13:29 +0000
2947@@ -360,7 +360,7 @@
2948 P(2,2)=0d0
2949 P(3,2)=-mom
2950
2951- call rambo(nexternal-2,energy,pmass(3),prambo,WGT)
2952+ call rambo(nexternal-2,energy,pmass(nexternal+1),prambo,WGT)
2953 DO I=3, NEXTERNAL
2954 P(0,I)=PRAMBO(4,I-2)
2955 P(1,I)=PRAMBO(1,I-2)
2956
2957=== modified file 'madgraph/iolibs/template_files/madevent_driver.f'
2958--- madgraph/iolibs/template_files/madevent_driver.f 2017-06-08 18:43:40 +0000
2959+++ madgraph/iolibs/template_files/madevent_driver.f 2021-01-30 10:13:29 +0000
2960@@ -27,6 +27,7 @@
2961 external NextUnopen
2962 double precision t_before
2963 logical fopened
2964+ integer nb_tchannel
2965 c
2966 c Global
2967 c
2968@@ -159,7 +160,7 @@
2969 maxcfig=mincfig
2970 minvar(1,1) = 0 !This tells it to map things invarients
2971 write(*,*) 'Attempting mappinvarients',nconfigs,nexternal
2972- call map_invarients(minvar,nconfigs,ninvar,mincfig,maxcfig,nexternal,nincoming)
2973+ call map_invarients(minvar,nconfigs,ninvar,mincfig,maxcfig,nexternal,nincoming,nb_tchannel)
2974 write(*,*) "Completed mapping",nexternal
2975 ndim = 3*(nexternal-nincoming)-4
2976 if (nincoming.gt.1.and.abs(lpp(1)) .ge. 1) ndim=ndim+1
2977@@ -173,6 +174,12 @@
2978 minvar(ndim,j) = ninvar
2979 endif
2980 enddo
2981+c ncall = ncall * max(1., min(3., (nb_tchannel+1.)/2.))
2982+ if (nb_tchannel.gt.1) then
2983+c itmin = itmin + 1
2984+ itmax = itmax + 2
2985+ endif
2986+
2987 write(*,*) "about to integrate ", ndim,ncall,itmax,itmin,ninvar,nconfigs
2988 call sample_full(ndim,ncall,itmax,itmin,dsig,ninvar,nconfigs)
2989
2990@@ -233,6 +240,9 @@
2991 common /to_accuracy/accur
2992 integer use_cut
2993 common /to_weight/use_cut
2994+ logical init_mode
2995+ common /to_determine_zero_hel/init_mode
2996+
2997
2998 integer lbw(0:nexternal) !Use of B.W.
2999 common /to_BW/ lbw
3000@@ -270,11 +280,17 @@
3001 write(*,*) 'Using full amplitude.'
3002 endif
3003
3004+ init_mode = .false.
3005 write(*,10) 'Exact helicity sum (0 yes, n = number/event)? '
3006 read(*,*) i
3007 if (i .eq. 0) then
3008 isum_hel = 0
3009 write(*,*) 'Explicitly summing over helicities'
3010+ else if (i.eq.-1) then
3011+ isum_hel = 0
3012+ multi_channel = .false.
3013+ init_mode = .true.
3014+ write(*,*) 'Determining zero helicities'
3015 else
3016 isum_hel= i
3017 write(*,*) 'Monte-Carlo over helicities'
3018
3019=== modified file 'madgraph/iolibs/template_files/madevent_symmetry.f'
3020--- madgraph/iolibs/template_files/madevent_symmetry.f 2020-04-16 19:10:18 +0000
3021+++ madgraph/iolibs/template_files/madevent_symmetry.f 2021-01-30 10:13:29 +0000
3022@@ -47,6 +47,7 @@
3023 c DATA
3024 c
3025 integer iforest(2,-max_branch:-1,lmaxconfigs)
3026+ integer tstrategy(lmaxconfigs)
3027 integer sprop(maxsproc,-max_branch:-1,lmaxconfigs)
3028 integer tprid(-max_branch:-1,lmaxconfigs)
3029 include 'configs.inc'
3030@@ -354,7 +355,8 @@
3031 c chain and could potentially conflict
3032 c
3033 i=1
3034- do while (i .lt. nexternal-2 .and. itree(1,-i) .ne. 1)
3035+ do while (i .lt. nexternal-2 .and. .not. (
3036+ & itree(1,-i) .eq. 1.or.(nincoming.eq.2.and.itree(1,-i).eq.2)))
3037 xmass(-i) = xmass(itree(1,-i))+xmass(itree(2,-i))
3038 mtot=mtot-xmass(-i)
3039 if (prwidth(-i,iconfig) .gt. 0d0) then
3040
3041=== modified file 'madgraph/iolibs/template_files/matrix_madevent_group_v4.inc'
3042--- madgraph/iolibs/template_files/matrix_madevent_group_v4.inc 2020-10-26 15:18:03 +0000
3043+++ madgraph/iolibs/template_files/matrix_madevent_group_v4.inc 2021-01-30 10:13:29 +0000
3044@@ -20,7 +20,7 @@
3045 Include 'nexternal.inc'
3046 Include 'maxamps.inc'
3047 INTEGER NCOMB
3048- PARAMETER ( NCOMB=%(ncomb)d)
3049+ PARAMETER ( NCOMB=%(ncomb)s)
3050 INTEGER NGRAPHS
3051 PARAMETER (NGRAPHS=%(ngraphs)d)
3052 INTEGER NDIAGS
3053@@ -40,7 +40,9 @@
3054
3055 C
3056 C LOCAL VARIABLES
3057-C
3058+C
3059+ INTEGER CONFSUB(MAXSPROC,LMAXCONFIGS)
3060+ INCLUDE 'config_subproc_map.inc'
3061 INTEGER NHEL(NEXTERNAL,NCOMB)
3062 INTEGER ISHEL(2)
3063 REAL*8 T,MATRIX%(proc_id)s
3064@@ -56,6 +58,8 @@
3065 SAVE NB_FAIL
3066 DATA THIS_NTRY /0,0/
3067 DATA NB_FAIL /0/
3068+ double precision get_channel_cut
3069+ external get_channel_cut
3070
3071 c
3072 C This is just to temporarily store the reference grid for helicity of the DiscreteSampler so as to obtain its number of entries with ref_helicity_grid%%n_tot_entries
3073@@ -63,6 +67,8 @@
3074 C
3075 C GLOBAL VARIABLES
3076 C
3077+ logical init_mode
3078+ common /to_determine_zero_hel/init_mode
3079 DOUBLE PRECISION AMP2(MAXAMPS), JAMP2(0:MAXFLOW)
3080 COMMON/TO_AMPS/ AMP2, JAMP2
3081
3082@@ -74,7 +80,12 @@
3083
3084 INTEGER IMIRROR
3085 COMMON/TO_MIRROR/ IMIRROR
3086-
3087+
3088+ double precision tmin_for_channel
3089+ integer sde_strat ! 1 means standard single diagram enhancement strategy,
3090+c 2 means approximation by the denominator of the propagator
3091+ common/TO_CHANNEL_STRAT/tmin_for_channel, sde_strat
3092+
3093 REAL*8 POL(2)
3094 COMMON/TO_POLARIZATION/ POL
3095
3096@@ -125,8 +136,8 @@
3097 ! If HEL_PICKED==-1, this means that calls to other matrix<i> where in initialization mode as well for the helicity.
3098 IF ((ISHEL(IMIRROR).EQ.0.and.ISUM_HEL.eq.0).or.(DS_get_dim_status('Helicity').eq.0).or.(HEL_PICKED.eq.-1)) THEN
3099 DO I=1,NCOMB
3100- IF (GOODHEL(I,IMIRROR) .OR. NTRY(IMIRROR).LE.MAXTRIES.or.(ISUM_HEL.NE.0).or.THIS_NTRY(IMIRROR).le.2) THEN
3101- T=MATRIX%(proc_id)s(P ,NHEL(1,I),JC(1))
3102+ IF (GOODHEL(I,IMIRROR) .OR. NTRY(IMIRROR).LE.MAXTRIES.or.(ISUM_HEL.NE.0).or.THIS_NTRY(IMIRROR).le.10) THEN
3103+ T=MATRIX%(proc_id)s(P ,NHEL(1,I),JC(1),I)
3104 DO JJ=1,nincoming
3105 IF(POL(JJ).NE.1d0.AND.NHEL(JJ,I).EQ.INT(SIGN(1d0,POL(JJ)))) THEN
3106 T=T*ABS(POL(JJ))*NB_SPIN_STATE_IN(JJ)/2d0 ! NB_SPIN_STATE(JJ)/2d0 is added for polarised beam
3107@@ -159,9 +170,13 @@
3108 endif
3109 ELSE
3110 JHEL(IMIRROR) = 1
3111- IF(NTRY(IMIRROR).LE.MAXTRIES.or.THIS_NTRY(IMIRROR).le.2)THEN
3112+ IF(NTRY(IMIRROR).LE.MAXTRIES.or.THIS_NTRY(IMIRROR).le.10)THEN
3113 DO I=1,NCOMB
3114- IF (.NOT.GOODHEL(I,IMIRROR) .AND. (DABS(TS(I)).GT.ANS*LIMHEL/NCOMB)) THEN
3115+ IF(init_mode) THEN
3116+ IF (DABS(TS(I)).GT.ANS*LIMHEL/NCOMB) THEN
3117+ PRINT *, 'Matrix Element/Good Helicity: %(proc_id)s ', i, 'IMIRROR', IMIRROR
3118+ ENDIF
3119+ ELSE IF (.NOT.GOODHEL(I,IMIRROR) .AND. (DABS(TS(I)).GT.ANS*LIMHEL/NCOMB)) THEN
3120 GOODHEL(I,IMIRROR)=.TRUE.
3121 NGOOD(IMIRROR) = NGOOD(IMIRROR) +1
3122 IGOOD(NGOOD(IMIRROR),IMIRROR) = I
3123@@ -173,11 +188,11 @@
3124 ISHEL(IMIRROR)=MIN(ISUM_HEL,NGOOD(IMIRROR))
3125 ENDIF
3126 ENDIF
3127- ELSE ! random helicity
3128+ ELSE IF (.not.init_mode) then ! random helicity
3129 C The helicity configuration was chosen already by genps and put in a common block defined in genps.inc.
3130 I = HEL_PICKED
3131
3132- T=MATRIX%(proc_id)s(P ,NHEL(1,I),JC(1))
3133+ T=MATRIX%(proc_id)s(P ,NHEL(1,I),JC(1),I)
3134
3135 DO JJ=1,nincoming
3136 IF(POL(JJ).NE.1d0.AND.NHEL(JJ,I).EQ.INT(SIGN(1d0,POL(JJ)))) THEN
3137@@ -192,6 +207,9 @@
3138 ANS = ANS * hel_jacobian
3139
3140 WRITE(HEL_BUFF,'(20i5)')(NHEL(II,I),II=1,NEXTERNAL)
3141+ ELSE
3142+ ANS = 1D0
3143+ RETURN
3144 ENDIF
3145 IF (ANS.ne.0d0.and.(ISUM_HEL .NE. 1.or.HEL_PICKED.eq.-1)) THEN
3146 CALL RANMAR(R)
3147@@ -209,8 +227,17 @@
3148 ENDIF
3149 IF (MULTI_CHANNEL) THEN
3150 XTOT=0D0
3151- DO I=1,NDIAGS
3152- XTOT=XTOT+AMP2(I)
3153+ DO I=1,LMAXCONFIGS
3154+ J = CONFSUB(%(proc_id)s, I)
3155+ if (J.ne.0) then
3156+ if(sde_strat.eq.1) then
3157+ AMP2(J) = AMP2(J) * GET_CHANNEL_CUT(P, I)
3158+ XTOT=XTOT+AMP2(J)
3159+ else
3160+ AMP2(J) = GET_CHANNEL_CUT(P, I)
3161+ XTOT=XTOT+AMP2(J)
3162+ endif
3163+ endif
3164 ENDDO
3165 IF (XTOT.NE.0D0) THEN
3166 %(set_amp2_line)s
3167@@ -228,7 +255,7 @@
3168 END
3169
3170
3171-REAL*8 FUNCTION MATRIX%(proc_id)s(P,NHEL,IC)
3172+REAL*8 FUNCTION MATRIX%(proc_id)s(P,NHEL,IC, IHEL)
3173 C
3174 %(info_lines)s
3175 C
3176@@ -242,7 +269,9 @@
3177 C CONSTANTS
3178 C
3179 INTEGER NGRAPHS
3180- PARAMETER (NGRAPHS=%(ngraphs)d)
3181+ PARAMETER (NGRAPHS=%(ngraphs)d)
3182+ INTEGER NCOMB
3183+ PARAMETER ( NCOMB=%(ncomb)s)
3184 include 'genps.inc'
3185 include 'nexternal.inc'
3186 include 'maxamps.inc'
3187@@ -262,12 +291,13 @@
3188 C
3189 REAL*8 P(0:3,NEXTERNAL)
3190 INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL)
3191+ INTEGER IHEL
3192 C
3193 C LOCAL VARIABLES
3194 C
3195 INTEGER I,J,M,N
3196- COMPLEX*16 ZTEMP
3197- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3198+ COMPLEX*16 ZTEMP, TMP_JAMP(%(nb_temp_jamp)i)
3199+ REAL*8 CF(NCOLOR,NCOLOR)
3200 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR,NAMPSO)
3201 COMPLEX*16 W(%(wavefunctionsize)d,NWAVEFUNCS)
3202 C Needed for v4 models
3203@@ -291,6 +321,18 @@
3204
3205 double precision small_width_treatment
3206 common/narrow_width/small_width_treatment
3207+
3208+ logical init_mode
3209+ common/to_determine_zero_hel/init_mode
3210+
3211+ logical zeroamp_%(proc_id)s(NCOMB,NGRAPHS)
3212+ common/to_zeroamp_%(proc_id)s/zeroamp_%(proc_id)s
3213+
3214+ double precision tmin_for_channel
3215+ integer sde_strat ! 1 means standard single diagram enhancement strategy,
3216+c 2 means approximation by the denominator of the propagator
3217+ common/TO_CHANNEL_STRAT/tmin_for_channel, sde_strat
3218+
3219 C
3220 C COLOR DATA
3221 C
3222@@ -301,12 +343,24 @@
3223 if (first) then
3224 first=.false.
3225 %(fake_width_definitions)s
3226+
3227+ if(init_mode) then
3228+ zeroamp_%(proc_id)s(:,:) = .true.
3229+ endif
3230 endif
3231
3232
3233 %(helas_calls)s
3234 %(jamp_lines)s
3235
3236+ if(init_mode)then
3237+ DO I=1, NGRAPHS
3238+ if (AMP(I).ne.0) then
3239+ zeroamp_%(proc_id)s(ihel,i) = .false.
3240+ endif
3241+ ENDDO
3242+ endif
3243+
3244 MATRIX%(proc_id)s = 0.D0
3245 DO M = 1, NAMPSO
3246 DO I = 1, NCOLOR
3247@@ -315,22 +369,62 @@
3248 ZTEMP = ZTEMP + CF(J,I)*JAMP(J,M)
3249 ENDDO
3250 DO N = 1, NAMPSO
3251- IF (CHOSEN_SO_CONFIGS(SQSOINDEX%(proc_id)s(M,N))) THEN
3252- MATRIX%(proc_id)s = MATRIX%(proc_id)s + ZTEMP*DCONJG(JAMP(I,N))/DENOM(I)
3253- ENDIF
3254+ %(select_configs_if)s
3255+ MATRIX%(proc_id)s = MATRIX%(proc_id)s + ZTEMP*DCONJG(JAMP(I,N))
3256+ %(select_configs_endif)s
3257 ENDDO
3258 ENDDO
3259 ENDDO
3260
3261+ if(sde_strat.eq.1)then
3262 %(amp2_lines)s
3263+ endif
3264+
3265 Do I = 1, NCOLOR
3266 DO M = 1, NAMPSO
3267 DO N = 1, NAMPSO
3268- IF (CHOSEN_SO_CONFIGS(SQSOINDEX%(proc_id)s(M,N))) THEN
3269+ %(select_configs_if)s
3270 Jamp2(i)=Jamp2(i)+DABS(DBLE(Jamp(i,m)*dconjg(Jamp(i,n))))
3271- ENDIF
3272+ %(select_configs_endif)s
3273 enddo
3274 enddo
3275 Enddo
3276
3277 END
3278+
3279+ SUBROUTINE PRINT_ZERO_AMP_%(proc_id)s()
3280+
3281+ IMPLICIT NONE
3282+ INTEGER NGRAPHS
3283+ PARAMETER (NGRAPHS=%(ngraphs)d)
3284+
3285+ INTEGER NCOMB
3286+ PARAMETER (NCOMB=%(ncomb)d)
3287+
3288+ logical zeroamp_%(proc_id)s(NCOMB, NGRAPHS)
3289+ common/to_zeroamp_%(proc_id)s/zeroamp_%(proc_id)s
3290+
3291+ integer i,j
3292+ logical all_false
3293+
3294+ do i=1, NGRAPHS
3295+ all_false = .true.
3296+ do j=1,NCOMB
3297+ if (.not.zeroamp_%(proc_id)s(j, i)) then
3298+ all_false = .false.
3299+ exit
3300+ endif
3301+ enddo
3302+ if (all_false) then
3303+ write(*,*) 'Amplitude/ZEROAMP:', %(proc_id)s, i
3304+ else
3305+ do j=1,NCOMB
3306+ if (zeroamp_%(proc_id)s(j, i)) then
3307+ write(*,*) 'HEL/ZEROAMP:', %(proc_id)s, j , i
3308+ endif
3309+ enddo
3310+ endif
3311+ enddo
3312+
3313+ return
3314+ end
3315\ No newline at end of file
3316
3317=== added file 'madgraph/iolibs/template_files/matrix_madevent_group_v4_hel.inc'
3318--- madgraph/iolibs/template_files/matrix_madevent_group_v4_hel.inc 1970-01-01 00:00:00 +0000
3319+++ madgraph/iolibs/template_files/matrix_madevent_group_v4_hel.inc 2021-01-30 10:13:29 +0000
3320@@ -0,0 +1,281 @@
3321+SUBROUTINE SMATRIX%(proc_id)s(P,ANS)
3322+C
3323+%(info_lines)s
3324+C
3325+C MadGraph5_aMC@NLO for Madevent Version
3326+C
3327+C Returns amplitude squared summed/avg over colors
3328+c and helicities
3329+c for the point in phase space P(0:3,NEXTERNAL)
3330+C
3331+%(process_lines)s
3332+C
3333+ IMPLICIT NONE
3334+C
3335+C CONSTANTS
3336+C
3337+ Include 'genps.inc'
3338+ Include 'maxconfigs.inc'
3339+ Include 'nexternal.inc'
3340+ Include 'maxamps.inc'
3341+ INTEGER NCOMB
3342+ PARAMETER ( NCOMB=${ncomb})
3343+ INTEGER NGRAPHS
3344+ PARAMETER (NGRAPHS=%(ngraphs)d)
3345+ INTEGER NDIAGS
3346+ PARAMETER (NDIAGS=%(ndiags)d)
3347+ INTEGER THEL
3348+ PARAMETER (THEL=2*NCOMB)
3349+C
3350+C ARGUMENTS
3351+C
3352+ REAL*8 P(0:3,NEXTERNAL),ANS
3353+C
3354+C LOCAL VARIABLES
3355+C
3356+ INTEGER CONFSUB(MAXSPROC,LMAXCONFIGS)
3357+ INCLUDE 'config_subproc_map.inc'
3358+ INTEGER NHEL(NEXTERNAL,NCOMB)
3359+ REAL*8 T
3360+ REAL*8 R,SUMHEL,TS(NCOMB)
3361+ INTEGER I,IDEN
3362+ INTEGER JC(NEXTERNAL),II
3363+ REAL*8 XTOT
3364+ INTEGER J, JJ
3365+
3366+ double precision get_channel_cut
3367+ external get_channel_cut
3368+
3369+C
3370+C GLOBAL VARIABLES
3371+C
3372+ DOUBLE PRECISION AMP2(MAXAMPS), JAMP2(0:MAXFLOW)
3373+ COMMON/TO_AMPS/ AMP2, JAMP2
3374+
3375+
3376+C
3377+C INFORMATION TO WRITE THE HELICITY IN THE EVENT --not memory efficient--
3378+C
3379+ CHARACTER*101 HEL_BUFF
3380+ COMMON/TO_HELICITY/ HEL_BUFF
3381+
3382+ INTEGER NB_SPIN_STATE_in(2)
3383+ common /nb_hel_state/ nb_spin_state_in
3384+
3385+ REAL*8 POL(2)
3386+
3387+ COMMON/TO_POLARIZATION/ POL
3388+ double precision tmin_for_channel
3389+ integer sde_strat ! 1 means standard single diagram enhancement strategy,
3390+c 2 means approximation by the denominator of the propagator
3391+ common/TO_CHANNEL_STRAT/tmin_for_channel, sde_strat
3392+
3393+ INTEGER ISUM_HEL
3394+ LOGICAL MULTI_CHANNEL
3395+ COMMON/TO_MATRIX/ISUM_HEL, MULTI_CHANNEL
3396+%(define_iconfigs_lines)s
3397+${helicity_lines}
3398+%(den_factor_line)s
3399+
3400+C ----------
3401+C BEGIN CODE
3402+C ----------
3403+
3404+ DO I=1,NEXTERNAL
3405+ JC(I) = +1
3406+ ENDDO
3407+
3408+ IF (multi_channel) THEN
3409+ DO I=1,NDIAGS
3410+ AMP2(I)=0D0
3411+ ENDDO
3412+ JAMP2(0)=%(ncolor)d
3413+ DO I=1,INT(JAMP2(0))
3414+ JAMP2(I)=0D0
3415+ ENDDO
3416+ ENDIF
3417+ ANS = 0D0
3418+ WRITE(HEL_BUFF,'(20I5)') (0,I=1,NEXTERNAL)
3419+c Kiran please check if you need this:
3420+ DO I=1,NCOMB
3421+ TS(I)=0d0
3422+ ENDDO
3423+
3424+ call MATRIX%(proc_id)s(P ,JC(1), TS)
3425+ DO I=1,NCOMB
3426+ T=TS(I)
3427+ DO JJ=1,nincoming
3428+ IF(POL(JJ).NE.1d0.AND.NHEL(JJ,I).EQ.INT(SIGN(1d0,POL(JJ)))) THEN
3429+ T=T*ABS(POL(JJ))*NB_SPIN_STATE_IN(JJ)/2d0 ! NB_SPIN_STATE(JJ)/2d0 is added for polarised beam
3430+ ELSE IF(POL(JJ).NE.1d0)THEN
3431+ T=T*(2d0-ABS(POL(JJ)))*NB_SPIN_STATE_IN(JJ)/2d0
3432+ ENDIF
3433+ ENDDO
3434+ ANS=ANS+DABS(T)
3435+ TS(I)=T
3436+ ENDDO
3437+
3438+ IF (ANS.ne.0d0) THEN
3439+ CALL RANMAR(R)
3440+ SUMHEL=0d0
3441+ DO I=1,NCOMB
3442+ SUMHEL=SUMHEL+DABS(TS(I))/ANS
3443+ IF(R.LT.SUMHEL)THEN
3444+ WRITE(HEL_BUFF,'(20i5)')(NHEL(II,I),II=1,NEXTERNAL)
3445+c Set right sign for ANS, based on sign of chosen helicity
3446+ ANS=DSIGN(ANS,TS(I))
3447+ GOTO 10
3448+ ENDIF
3449+ ENDDO
3450+ 10 CONTINUE
3451+ ENDIF
3452+ IF (MULTI_CHANNEL) THEN
3453+ XTOT=0D0
3454+ DO I=1,LMAXCONFIGS
3455+ J = CONFSUB(%(proc_id)s, I)
3456+ if (J.ne.0)then
3457+ if (sde_strat.eq.1)then
3458+ AMP2(J) = AMP2(J) * GET_CHANNEL_CUT(P, I)
3459+ else
3460+ AMP2(J) = GET_CHANNEL_CUT(P, I)
3461+ endif
3462+ XTOT=XTOT+AMP2(J)
3463+
3464+ endif
3465+ ENDDO
3466+ IF (XTOT.NE.0D0) THEN
3467+%(set_amp2_line)s
3468+ ELSE IF(ANS.ne.0d0) THEN
3469+ write(*,*) "Problem in the multi-channeling. All amp2 are zero but not the total matrix-element"
3470+ stop 1
3471+ ENDIF
3472+ ENDIF
3473+ ANS=ANS/DBLE(IDEN)
3474+ END
3475+
3476+
3477+Subroutine MATRIX%(proc_id)s(P,IC, TS)
3478+C
3479+%(info_lines)s
3480+C
3481+C Returns amplitude squared summed/avg over colors
3482+c for the point with external lines W(0:6,NEXTERNAL)
3483+C
3484+%(process_lines)s
3485+C
3486+ IMPLICIT NONE
3487+C
3488+C CONSTANTS
3489+C
3490+ INTEGER NGRAPHS
3491+ PARAMETER (NGRAPHS=%(ngraphs)d)
3492+ include 'genps.inc'
3493+ include 'nexternal.inc'
3494+ include 'maxamps.inc'
3495+ INTEGER NWAVEFUNCS, NCOLOR
3496+ PARAMETER (NWAVEFUNCS=${nwavefuncs}, NCOLOR=%(ncolor)d)
3497+ REAL*8 ZERO
3498+ PARAMETER (ZERO=0D0)
3499+ COMPLEX*16 IMAG1
3500+ PARAMETER (IMAG1=(0D0,1D0))
3501+ INTEGER NAMPSO, NSQAMPSO
3502+ PARAMETER (NAMPSO=%(nAmpSplitOrders)d, NSQAMPSO=%(nSqAmpSplitOrders)d)
3503+ LOGICAL CHOSEN_SO_CONFIGS(NSQAMPSO)
3504+ DATA CHOSEN_SO_CONFIGS/%(chosen_so_configs)s/
3505+ SAVE CHOSEN_SO_CONFIGS
3506+ INTEGER NCOMB
3507+ PARAMETER ( NCOMB=${ncomb})
3508+C
3509+C ARGUMENTS
3510+C
3511+ REAL*8 P(0:3,NEXTERNAL)
3512+ INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL)
3513+ REAL*8 TS(NCOMB)
3514+C
3515+C LOCAL VARIABLES
3516+C
3517+ INTEGER I,J,M,N,K
3518+ COMPLEX*16 ZTEMP,TMP_JAMP(%(nb_temp_jamp)i)
3519+ COMPLEX*16 TMP(6)
3520+ REAL*8 CF(NCOLOR,NCOLOR)
3521+ COMPLEX*16 AMP(NCOMB,NGRAPHS), JAMP(NCOLOR,NAMPSO)
3522+ COMPLEX*16 W(%(wavefunctionsize)d,NWAVEFUNCS)
3523+C Needed for v4 models
3524+ COMPLEX*16 DUM0,DUM1
3525+ DATA DUM0, DUM1/(0d0, 0d0), (1d0, 0d0)/
3526+
3527+ %(fake_width_declaration)s
3528+ logical first
3529+ data first /.true./
3530+ save first
3531+C
3532+C FUNCTION
3533+C
3534+ INTEGER SQSOINDEX%(proc_id)s
3535+
3536+C
3537+C GLOBAL VARIABLES
3538+C
3539+ Double Precision amp2(maxamps), jamp2(0:maxflow)
3540+ common/to_amps/ amp2, jamp2
3541+ include 'coupl.inc'
3542+
3543+ double precision tmin_for_channel
3544+ integer sde_strat ! 1 means standard single diagram enhancement strategy,
3545+c 2 means approximation by the denominator of the propagator
3546+ common/TO_CHANNEL_STRAT/tmin_for_channel, sde_strat
3547+
3548+ double precision small_width_treatment
3549+ common/narrow_width/small_width_treatment
3550+C
3551+C COLOR DATA
3552+C
3553+%(color_data_lines)s
3554+C ----------
3555+C BEGIN CODE
3556+C ----------
3557+if (first) then
3558+ first=.false.
3559+ %(fake_width_definitions)s
3560+endif
3561+ AMP(:,:) = (0d0,0d0)
3562+${helas_calls}
3563+ DO K = 1, NCOMB
3564+${jamp_lines}
3565+ TS(K) = 0.D0
3566+ DO M = 1, NAMPSO
3567+ DO I = 1, NCOLOR
3568+ ZTEMP = (0.D0,0.D0)
3569+ DO J = 1, NCOLOR
3570+ ZTEMP = ZTEMP + CF(J,I)*JAMP(J,M)
3571+ ENDDO
3572+ DO N = 1, NAMPSO
3573+ %(select_configs_if)s
3574+ TS(K) = TS(K) + ZTEMP*DCONJG(JAMP(I,N))
3575+ %(select_configs_endif)s
3576+ ENDDO
3577+ ENDDO
3578+ ENDDO
3579+ if(sde_strat.eq.1) then
3580+ ${amp2_lines}
3581+ endif
3582+ Do I = 1, NCOLOR
3583+ DO M = 1, NAMPSO
3584+ DO N = 1, NAMPSO
3585+ %(select_configs_if)s
3586+ Jamp2(i)=Jamp2(i)+DABS(DBLE(Jamp(i,m)*dconjg(Jamp(i,n))))
3587+ %(select_configs_endif)s
3588+ enddo
3589+ enddo
3590+ Enddo
3591+ ENDDO
3592+
3593+ END
3594+
3595+
3596+ SUBROUTINE PRINT_ZERO_AMP_%(proc_id)s()
3597+
3598+ integer i
3599+ i =1
3600+ return
3601+ end
3602\ No newline at end of file
3603
3604=== modified file 'madgraph/iolibs/template_files/matrix_madevent_v4.inc'
3605--- madgraph/iolibs/template_files/matrix_madevent_v4.inc 2020-10-26 15:18:03 +0000
3606+++ madgraph/iolibs/template_files/matrix_madevent_v4.inc 2021-01-30 10:13:29 +0000
3607@@ -233,8 +233,8 @@
3608 C LOCAL VARIABLES
3609 C
3610 INTEGER I,J,M,N
3611- COMPLEX*16 ZTEMP
3612- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3613+ COMPLEX*16 ZTEMP, TMP_JAMP(%(nb_temp_jamp)i)
3614+ REAL*8 CF(NCOLOR,NCOLOR)
3615 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR,NAMPSO)
3616 COMPLEX*16 W(18,NWAVEFUNCS)
3617 C Needed for v4 models
3618@@ -282,7 +282,7 @@
3619 ENDDO
3620 DO N = 1, NAMPSO
3621 IF (CHOSEN_SO_CONFIGS(SQSOINDEX%(proc_id)s(M,N))) THEN
3622- MATRIX%(proc_id)s = MATRIX%(proc_id)s + ZTEMP*DCONJG(JAMP(I,N))/DENOM(I)
3623+ MATRIX%(proc_id)s = MATRIX%(proc_id)s + ZTEMP*DCONJG(JAMP(I,N))
3624 ENDIF
3625 ENDDO
3626 ENDDO
3627
3628=== modified file 'madgraph/iolibs/template_files/matrix_madweight_group_v4.inc'
3629--- madgraph/iolibs/template_files/matrix_madweight_group_v4.inc 2018-10-07 20:06:38 +0000
3630+++ madgraph/iolibs/template_files/matrix_madweight_group_v4.inc 2021-01-30 10:13:29 +0000
3631@@ -90,7 +90,7 @@
3632 C
3633 INTEGER I,J
3634 COMPLEX*16 ZTEMP
3635- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3636+ REAL*8 CF(NCOLOR,NCOLOR)
3637 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR)
3638 COMPLEX*16 W(18,NWAVEFUNCS)
3639 COMPLEX*16 DUM0,DUM1
3640@@ -115,6 +115,6 @@
3641 DO J = 1, NCOLOR
3642 ZTEMP = ZTEMP + CF(J,I)*JAMP(J)
3643 ENDDO
3644- MATRIX%(proc_id)s = MATRIX%(proc_id)s+ZTEMP*DCONJG(JAMP(I))/DENOM(I)
3645+ MATRIX%(proc_id)s = MATRIX%(proc_id)s+ZTEMP*DCONJG(JAMP(I))
3646 ENDDO
3647 END
3648
3649=== modified file 'madgraph/iolibs/template_files/matrix_standalone_matchbox.inc'
3650--- madgraph/iolibs/template_files/matrix_standalone_matchbox.inc 2014-11-04 08:17:57 +0000
3651+++ madgraph/iolibs/template_files/matrix_standalone_matchbox.inc 2021-01-30 10:13:29 +0000
3652@@ -89,7 +89,7 @@
3653 C
3654 INTEGER I,J
3655 COMPLEX*16 ZTEMP
3656- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3657+ REAL*8 CF(NCOLOR,NCOLOR)
3658 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR), LNJAMP(NCOLOR)
3659 COMPLEX*16 W(18,NWAVEFUNCS)
3660 COMPLEX*16 DUM0,DUM1
3661@@ -115,7 +115,7 @@
3662 DO J = 1, NCOLOR
3663 ZTEMP = ZTEMP + CF(J,I)*JAMP(J)
3664 ENDDO
3665- %(proc_prefix)sMATRIX = %(proc_prefix)sMATRIX+ZTEMP*DCONJG(JAMP(I))/DENOM(I)
3666+ %(proc_prefix)sMATRIX = %(proc_prefix)sMATRIX+ZTEMP*DCONJG(JAMP(I))
3667 ENDDO
3668 %(amp2_lines)s
3669 END
3670@@ -162,7 +162,7 @@
3671 C
3672 INTEGER I,J
3673 COMPLEX*16 ZTEMP
3674- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3675+ REAL*8 CF(NCOLOR,NCOLOR)
3676 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR), LNJAMP(NCOLOR)
3677 COMMON/%(proc_prefix)sJAMP/JAMP,LNJAMP
3678
3679
3680=== modified file 'madgraph/iolibs/template_files/matrix_standalone_matchbox_splitOrders_v4.inc'
3681--- madgraph/iolibs/template_files/matrix_standalone_matchbox_splitOrders_v4.inc 2014-11-19 10:57:55 +0000
3682+++ madgraph/iolibs/template_files/matrix_standalone_matchbox_splitOrders_v4.inc 2021-01-30 10:13:29 +0000
3683@@ -211,7 +211,7 @@
3684 C
3685 INTEGER I,J,M,N
3686 COMPLEX*16 ZTEMP
3687- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3688+ REAL*8 CF(NCOLOR,NCOLOR)
3689 COMPLEX*16 AMP(NGRAPHS)
3690 COMPLEX*16 JAMP(NCOLOR,NAMPSO), LNJAMP(NCOLOR,NAMPSO)
3691 COMMON/%(proc_prefix)sJAMP/JAMP,LNJAMP
3692@@ -244,7 +244,7 @@
3693 ZTEMP = ZTEMP + CF(J,I)*JAMP(J,M)
3694 ENDDO
3695 DO N = 1, NAMPSO
3696- RES(%(proc_prefix)sSQSOINDEX(M,N)) = RES(%(proc_prefix)sSQSOINDEX(M,N)) + ZTEMP*DCONJG(JAMP(I,N))/DENOM(I)
3697+ RES(%(proc_prefix)sSQSOINDEX(M,N)) = RES(%(proc_prefix)sSQSOINDEX(M,N)) + ZTEMP*DCONJG(JAMP(I,N))
3698 ENDDO
3699 ENDDO
3700 ENDDO
3701@@ -319,7 +319,7 @@
3702 C
3703 INTEGER I,J,M,N
3704 COMPLEX*16 ZTEMP
3705- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3706+ REAL*8 CF(NCOLOR,NCOLOR)
3707 COMPLEX*16 AMP(NGRAPHS)
3708 COMPLEX*16 JAMP(NCOLOR,NAMPSO), LNJAMP(NCOLOR,NAMPSO)
3709 COMMON/%(proc_prefix)sJAMP/JAMP,LNJAMP
3710
3711=== modified file 'madgraph/iolibs/template_files/matrix_standalone_msF_v4.inc'
3712--- madgraph/iolibs/template_files/matrix_standalone_msF_v4.inc 2014-02-18 16:35:27 +0000
3713+++ madgraph/iolibs/template_files/matrix_standalone_msF_v4.inc 2021-01-30 10:13:29 +0000
3714@@ -94,7 +94,7 @@
3715 C
3716 INTEGER I,J
3717 COMPLEX*16 ZTEMP
3718- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3719+ REAL*8 CF(NCOLOR,NCOLOR)
3720 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR)
3721 COMPLEX*16 W(18,NWAVEFUNCS)
3722 COMPLEX*16 DUM0,DUM1
3723@@ -119,7 +119,7 @@
3724 DO J = 1, NCOLOR
3725 ZTEMP = ZTEMP + CF(J,I)*JAMP(J)
3726 ENDDO
3727- MATRIX = MATRIX+ZTEMP*DCONJG(JAMP(I))/DENOM(I)
3728+ MATRIX = MATRIX+ZTEMP*DCONJG(JAMP(I))
3729 ENDDO
3730
3731 END
3732
3733=== modified file 'madgraph/iolibs/template_files/matrix_standalone_msP_v4.inc'
3734--- madgraph/iolibs/template_files/matrix_standalone_msP_v4.inc 2013-12-13 01:58:39 +0000
3735+++ madgraph/iolibs/template_files/matrix_standalone_msP_v4.inc 2021-01-30 10:13:29 +0000
3736@@ -89,7 +89,7 @@
3737 C
3738 INTEGER I,J
3739 COMPLEX*16 ZTEMP
3740- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3741+ REAL*8 CF(NCOLOR,NCOLOR)
3742 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR)
3743 COMPLEX*16 W(18,NWAVEFUNCS)
3744 COMPLEX*16 DUM0,DUM1
3745@@ -116,7 +116,7 @@
3746 DO J = 1, NCOLOR
3747 ZTEMP = ZTEMP + CF(J,I)*JAMP(J)
3748 ENDDO
3749- MATRIX_PROD = MATRIX_PROD+ZTEMP*DCONJG(JAMP(I))/DENOM(I)
3750+ MATRIX_PROD = MATRIX_PROD+ZTEMP*DCONJG(JAMP(I))
3751 ENDDO
3752 %(amp2_lines)s
3753 END
3754
3755=== modified file 'madgraph/iolibs/template_files/matrix_standalone_splitOrders_v4.inc'
3756--- madgraph/iolibs/template_files/matrix_standalone_splitOrders_v4.inc 2018-05-17 12:03:54 +0000
3757+++ madgraph/iolibs/template_files/matrix_standalone_splitOrders_v4.inc 2021-01-30 10:13:29 +0000
3758@@ -254,7 +254,7 @@
3759 C
3760 INTEGER I,J,M,N
3761 COMPLEX*16 ZTEMP
3762- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3763+ REAL*8 CF(NCOLOR,NCOLOR)
3764 COMPLEX*16 AMP(NGRAPHS)
3765 COMPLEX*16 JAMP(NCOLOR,NAMPSO)
3766 COMPLEX*16 W(20,NWAVEFUNCS)
3767@@ -286,7 +286,7 @@
3768 ZTEMP = ZTEMP + CF(J,I)*JAMP(J,M)
3769 ENDDO
3770 DO N = 1, NAMPSO
3771- RES(%(proc_prefix)sSQSOINDEX(M,N)) = RES(%(proc_prefix)sSQSOINDEX(M,N)) + ZTEMP*DCONJG(JAMP(I,N))/DENOM(I)
3772+ RES(%(proc_prefix)sSQSOINDEX(M,N)) = RES(%(proc_prefix)sSQSOINDEX(M,N)) + ZTEMP*DCONJG(JAMP(I,N))
3773 ENDDO
3774 ENDDO
3775 ENDDO
3776
3777=== modified file 'madgraph/iolibs/template_files/matrix_standalone_v4.inc'
3778--- madgraph/iolibs/template_files/matrix_standalone_v4.inc 2020-11-24 16:20:51 +0000
3779+++ madgraph/iolibs/template_files/matrix_standalone_v4.inc 2021-01-30 10:13:29 +0000
3780@@ -194,8 +194,8 @@
3781 C
3782 INTEGER I,J
3783 COMPLEX*16 ZTEMP
3784- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3785- COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR)
3786+ REAL*8 CF(NCOLOR,NCOLOR)
3787+ COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR), TMP_JAMP(%(nb_temp_jamp)i)
3788 COMPLEX*16 W(20,NWAVEFUNCS)
3789 COMPLEX*16 DUM0,DUM1
3790 DATA DUM0, DUM1/(0d0, 0d0), (1d0, 0d0)/
3791@@ -220,8 +220,8 @@
3792 DO J = 1, NCOLOR
3793 ZTEMP = ZTEMP + CF(J,I)*JAMP(J)
3794 ENDDO
3795- %(proc_prefix)sMATRIX = %(proc_prefix)sMATRIX+ZTEMP*DCONJG(JAMP(I))/DENOM(I)
3796- ENDDO
3797+ %(proc_prefix)sMATRIX = %(proc_prefix)sMATRIX+ZTEMP*DCONJG(JAMP(I))
3798+ ENDDO
3799 %(amp2_lines)s
3800 END
3801
3802
3803=== modified file 'madgraph/iolibs/template_files/realmatrix_fks.inc'
3804--- madgraph/iolibs/template_files/realmatrix_fks.inc 2020-01-16 13:45:20 +0000
3805+++ madgraph/iolibs/template_files/realmatrix_fks.inc 2021-01-30 10:13:29 +0000
3806@@ -112,8 +112,9 @@
3807 INTEGER I,J
3808 INTEGER IC(NEXTERNAL)
3809 data ic /nexternal*1/
3810- REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
3811+ REAL*8 CF(NCOLOR,NCOLOR)
3812 COMPLEX*16 ZTEMP, AMP(NGRAPHS), JAMP(NCOLOR), W(%(wavefunctionsize)d,NWAVEFUNCS)
3813+ COMPLEX*16 TMP_JAMP(%(nb_temp_jamp)i)
3814 C
3815 C COLOR DATA
3816 C
3817@@ -129,6 +130,6 @@
3818 DO J = 1, NCOLOR
3819 ZTEMP = ZTEMP + CF(J,I)*JAMP(J)
3820 ENDDO
3821- MATRIX_%(N_me)d = MATRIX_%(N_me)d+ZTEMP*DCONJG(JAMP(I))/DENOM(I)
3822+ MATRIX_%(N_me)d = MATRIX_%(N_me)d+ZTEMP*DCONJG(JAMP(I))
3823 ENDDO
3824 END
3825
3826=== modified file 'madgraph/iolibs/template_files/super_auto_dsig_group_v4.inc'
3827--- madgraph/iolibs/template_files/super_auto_dsig_group_v4.inc 2020-01-16 07:19:30 +0000
3828+++ madgraph/iolibs/template_files/super_auto_dsig_group_v4.inc 2021-01-30 10:13:29 +0000
3829@@ -97,6 +97,8 @@
3830 DATA LAST_ICONF/-1/
3831 COMMON/TO_LAST_ICONF/LAST_ICONF
3832
3833+ logical init_mode
3834+ common /to_determine_zero_hel/init_mode
3835 C ----------
3836 C BEGIN CODE
3837 C ----------
3838@@ -180,7 +182,7 @@
3839 call DS_set_min_points(10,'grouped_processes')
3840 DO J=1,SYMCONF(0)
3841 DO IPROC=1,MAXSPROC
3842- IF(CONFSUB(IPROC,SYMCONF(J)).NE.0) THEN
3843+ IF(init_mode.or.CONFSUB(IPROC,SYMCONF(J)).NE.0) THEN
3844 DO IMIRROR=1,2
3845 IF(IMIRROR.EQ.1.OR.MIRRORPROCS(IPROC))THEN
3846 CALL MAP_3_TO_1(J,IPROC,IMIRROR,MAXSPROC,2,LMAPPED)
3847@@ -201,7 +203,7 @@
3848 LAST_ICONF=0
3849 DO J=1,SYMCONF(0)
3850 DO IPROC=1,MAXSPROC
3851- IF(CONFSUB(IPROC,SYMCONF(J)).NE.0) THEN
3852+ IF(init_mode.or.CONFSUB(IPROC,SYMCONF(J)).NE.0) THEN
3853 DO IMIRROR=1,2
3854 IF(IMIRROR.EQ.1.OR.MIRRORPROCS(IPROC))THEN
3855 C Calculate PDF weight for all subprocesses
3856@@ -245,7 +247,7 @@
3857 LAST_ICONF=0
3858 DO J=1,SYMCONF(0)
3859 DO I=1,MAXSPROC
3860- IF(CONFSUB(I,SYMCONF(J)).NE.0) THEN
3861+ IF(init_mode.or.CONFSUB(I,SYMCONF(J)).NE.0) THEN
3862 DO K=1,2
3863 IF(K.EQ.1.OR.MIRRORPROCS(I))THEN
3864 IPROC=I
3865@@ -264,7 +266,11 @@
3866 XBK(2)=XDUM
3867 CM_RAP=-CM_RAP
3868 ENDIF
3869- SELPROC(K,I,J) = DABS(DSIG*SELPROC(K,I,J))
3870+ if(init_mode) then
3871+ SELPROC(K,I,J) = 1d0
3872+ else
3873+ SELPROC(K,I,J) = DABS(DSIG*SELPROC(K,I,J))
3874+ endif
3875 SUMPROB = SUMPROB + SELPROC(K,I,J)
3876 ENDIF
3877 ENDDO
3878@@ -289,7 +295,7 @@
3879 TOTWGT=0D0
3880 DO J=1,SYMCONF(0)
3881 DO I=1,MAXSPROC
3882- IF(CONFSUB(I,SYMCONF(J)).NE.0) THEN
3883+ IF(init_mode.or.CONFSUB(I,SYMCONF(J)).NE.0) THEN
3884 DO K=1,2
3885 TOTWGT=TOTWGT+SELPROC(K,I,J)
3886 IF(R.LT.TOTWGT)THEN
3887@@ -507,4 +513,8 @@
3888 %(read_write_good_hel)s
3889
3890
3891+ SUBROUTINE PRINT_ZERO_AMP()
3892
3893+ %(print_zero_amp)s
3894+ return
3895+ end
3896
3897=== modified file 'madgraph/madevent/gen_ximprove.py'
3898--- madgraph/madevent/gen_ximprove.py 2020-09-16 07:01:30 +0000
3899+++ madgraph/madevent/gen_ximprove.py 2021-01-30 10:13:29 +0000
3900@@ -29,6 +29,7 @@
3901 import shutil
3902 import stat
3903 import sys
3904+import six
3905 from six.moves import range
3906 from six.moves import zip
3907
3908@@ -44,6 +45,8 @@
3909 import internal.combine_grid as combine_grid
3910 import internal.combine_runs as combine_runs
3911 import internal.lhe_parser as lhe_parser
3912+ if six.PY3:
3913+ import internal.hel_recycle as hel_recycle
3914 else:
3915 MADEVENT= False
3916 import madgraph.madevent.sum_html as sum_html
3917@@ -54,6 +57,8 @@
3918 import madgraph.madevent.combine_grid as combine_grid
3919 import madgraph.madevent.combine_runs as combine_runs
3920 import madgraph.various.lhe_parser as lhe_parser
3921+ if six.PY3:
3922+ import madgraph.madevent.hel_recycle as hel_recycle
3923
3924 logger = logging.getLogger('madgraph.madevent.gen_ximprove')
3925 pjoin = os.path.join
3926@@ -109,22 +114,193 @@
3927 #if the user defines it in the run_card:
3928 if self.run_card['survey_splitting'] != -1:
3929 self.splitted_grid = self.run_card['survey_splitting']
3930- if self.run_card['survey_nchannel_per_job'] != -1:
3931+ if self.run_card['survey_nchannel_per_job'] != 1 and 'survey_nchannel_per_job' in self.run_card.user_set:
3932 self.combining_job = self.run_card['survey_nchannel_per_job']
3933 elif self.run_card['hard_survey'] > 1:
3934 self.combining_job = 1
3935
3936-
3937
3938 self.splitted_Pdir = {}
3939 self.splitted_for_dir = lambda x,y: self.splitted_grid
3940 self.combining_job_for_Pdir = lambda x: self.combining_job
3941 self.lastoffset = {}
3942
3943+ done_warning_zero_coupling = False
3944+ def get_helicity(self, to_submit=True, clean=True):
3945+ """launch a single call to madevent to get the list of non zero helicity"""
3946+
3947+ self.subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
3948+ 'subproc.mg'))]
3949+ subproc = self.subproc
3950+ P_zero_result = []
3951+ nb_tot_proc = len(subproc)
3952+ job_list = {}
3953+
3954+
3955+ for nb_proc,subdir in enumerate(subproc):
3956+ self.cmd.update_status('Compiling for process %s/%s.' % \
3957+ (nb_proc+1,nb_tot_proc), level=None)
3958+
3959+ subdir = subdir.strip()
3960+ Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
3961+ logger.info(' %s ' % subdir)
3962+
3963+ self.cmd.compile(['madevent_forhel'], cwd=Pdir)
3964+ if not os.path.exists(pjoin(Pdir, 'madevent_forhel')):
3965+ raise Exception('Error make madevent_forhel not successful')
3966+
3967+ if not os.path.exists(pjoin(Pdir, 'Hel')):
3968+ os.mkdir(pjoin(Pdir, 'Hel'))
3969+ ff = open(pjoin(Pdir, 'Hel', 'input_app.txt'),'w')
3970+ ff.write('1000 1 1 \n 0.1 \n 2\n 0\n -1\n 1\n')
3971+ ff.close()
3972+ else:
3973+ try:
3974+ os.remove(pjoin(Pdir, 'Hel','results.dat'))
3975+ except Exception:
3976+ pass
3977+ # Launch gensym
3978+ p = misc.Popen(['../madevent_forhel < input_app.txt'], stdout=subprocess.PIPE,
3979+ stderr=subprocess.STDOUT, cwd=pjoin(Pdir,'Hel'), shell=True)
3980+ #sym_input = "%(points)d %(iterations)d %(accuracy)f \n" % self.opts
3981+ (stdout, _) = p.communicate(" ".encode())
3982+ stdout = stdout.decode('ascii')
3983+ if os.path.exists(pjoin(self.me_dir,'error')):
3984+ raise Exception(pjoin(self.me_dir,'error'))
3985+ # note a continue is not enough here, we have in top to link
3986+ # the matrixX_optim.f to matrixX_orig.f to let the code to work
3987+ # after this error.
3988+
3989+ if 'no events passed cuts' in stdout:
3990+ raise Exception
3991+
3992+ all_zamp = set()
3993+ all_hel = set()
3994+ zero_gc = list()
3995+ all_zampperhel = set()
3996+ all_bad_amps_perhel = set()
3997+
3998+ for line in stdout.splitlines():
3999+ if 'GC_' in line:
4000+ lsplit = line.split()
4001+ if float(lsplit[2]) ==0 == float(lsplit[3]):
4002+ zero_gc.append(lsplit[0])
4003+ if 'Matrix Element/Good Helicity:' in line:
4004+ all_hel.add(tuple(line.split()[3:5]))
4005+ if 'Amplitude/ZEROAMP:' in line:
4006+ all_zamp.add(tuple(line.split()[1:3]))
4007+ if 'HEL/ZEROAMP:' in line:
4008+ nb_mat, nb_hel, nb_amp = line.split()[1:4]
4009+ if (nb_mat, nb_hel) not in all_hel:
4010+ continue
4011+ if (nb_mat,nb_amp) in all_zamp:
4012+ continue
4013+ all_zampperhel.add(tuple(line.split()[1:4]))
4014+
4015+ if zero_gc and not gensym.done_warning_zero_coupling:
4016+ gensym.done_warning_zero_coupling = True
4017+ logger.warning("The optimizer detects that you have coupling evaluated to zero: \n"+\
4018+ "%s\n" % (' '.join(zero_gc)) +\
4019+ "This will slow down the computation. Please consider using restricted model:\n" +\
4020+ "https://answers.launchpad.net/mg5amcnlo/+faq/2312")
4021+
4022+
4023+ all_good_hels = collections.defaultdict(list)
4024+ for me_index, hel in all_hel:
4025+ all_good_hels[me_index].append(int(hel))
4026+
4027+ #print(all_hel)
4028+ if self.run_card['hel_zeroamp']:
4029+ all_bad_amps = collections.defaultdict(list)
4030+ for me_index, amp in all_zamp:
4031+ all_bad_amps[me_index].append(int(amp))
4032+
4033+ all_bad_amps_perhel = collections.defaultdict(list)
4034+ for me_index, hel, amp in all_zampperhel:
4035+ all_bad_amps_perhel[me_index].append((int(hel),int(amp)))
4036+
4037+ elif all_zamp:
4038+ nb_zero = sum(int(a[1]) for a in all_zamp)
4039+ if zero_gc:
4040+ logger.warning("Those zero couplings lead to %s Feynman diagram evaluated to zero (on 10 PS point),\n" % nb_zero +\
4041+ "This part can optimize if you set the flag hel_zeroamp to True in the run_card."+\
4042+ "Note that restricted model will be more optimal.")
4043+ else:
4044+ logger.warning("The optimization detected that you have %i zero matrix-element for this SubProcess: %s.\n" % nb_zero +\
4045+ "This part can optimize if you set the flag hel_zeroamp to True in the run_card.")
4046+
4047+ #check if we need to do something and write associate information"
4048+ data = [all_hel, all_zamp, all_bad_amps_perhel]
4049+ if not self.run_card['hel_zeroamp']:
4050+ data[1] = ''
4051+ if not self.run_card['hel_filtering']:
4052+ data[0] = ''
4053+ data = str(data)
4054+ if os.path.exists(pjoin(Pdir,'Hel','selection')):
4055+ old_data = open(pjoin(Pdir,'Hel','selection')).read()
4056+ if old_data == data:
4057+ continue
4058+
4059+
4060+ with open(pjoin(Pdir,'Hel','selection'),'w') as fsock:
4061+ fsock.write(data)
4062+
4063+
4064+ for matrix_file in misc.glob('matrix*orig.f', Pdir):
4065+
4066+ split_file = matrix_file.split('/')
4067+ me_index = split_file[-1][len('matrix'):-len('_orig.f')]
4068+
4069+ basename = split_file[-1].replace('orig', 'optim')
4070+ split_out = split_file[:-1] + [basename]
4071+ out_file = pjoin('/', '/'.join(split_out))
4072+
4073+ basename = 'template_%s' % split_file[-1].replace("_orig", "")
4074+ split_templ = split_file[:-1] + [basename]
4075+ templ_file = pjoin('/', '/'.join(split_templ))
4076+
4077+ # Convert to sorted list for reproducibility
4078+ #good_hels = sorted(list(good_hels))
4079+ good_hels = [str(x) for x in sorted(all_good_hels[me_index])]
4080+ if self.run_card['hel_zeroamp']:
4081+
4082+ bad_amps = [str(x) for x in sorted(all_bad_amps[me_index])]
4083+ bad_amps_perhel = [x for x in sorted(all_bad_amps_perhel[me_index])]
4084+ else:
4085+ bad_amps = []
4086+ bad_amps_perhel = []
4087+ if __debug__:
4088+ mtext = open(matrix_file).read()
4089+ nb_amp = int(re.findall('PARAMETER \(NGRAPHS=(\d+)\)', mtext)[0])
4090+ logger.debug('nb_hel: %s zero amp: %s bad_amps_hel: %s/%s', len(good_hels),len(bad_amps),len(bad_amps_perhel), len(good_hels)*nb_amp )
4091+ if len(good_hels) == 1:
4092+ files.cp(matrix_file, matrix_file.replace('orig','optim'))
4093+ continue # avoid optimization if onlye one helicity
4094+ recycler = hel_recycle.HelicityRecycler(good_hels, bad_amps, bad_amps_perhel)
4095+ # In case of bugs you can play around with these:
4096+ recycler.hel_filt = self.run_card['hel_filtering']
4097+ recycler.amp_splt = self.run_card['hel_splitamp']
4098+ recycler.amp_filt = self.run_card['hel_zeroamp']
4099+
4100+ recycler.set_input(matrix_file)
4101+ recycler.set_output(out_file)
4102+ recycler.set_template(templ_file)
4103+ recycler.generate_output_file()
4104+ del recycler
4105+
4106+ # with misc.chdir():
4107+ # pass
4108+
4109+ #files.ln(pjoin(Pdir, 'madevent_forhel'), Pdir, name='madevent') ##to be removed
4110+
4111+ return {}, P_zero_result
4112+
4113+
4114 def launch(self, to_submit=True, clean=True):
4115 """ """
4116-
4117- self.subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
4118+
4119+ if not hasattr(self, 'subproc'):
4120+ self.subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
4121 'subproc.mg'))]
4122 subproc = self.subproc
4123
4124@@ -916,7 +1092,7 @@
4125 if C.get('axsec') == 0:
4126 continue
4127 if goal_lum/(C.get('luminosity')+1e-99) >= 1 + (self.gen_events_security-1)/2:
4128- logger.debug("channel %s is at lum=%s (need to improve by %s) (xsec=%s pb)", C.name, C.get('luminosity'), goal_lum/(C.get('luminosity')+1e-99), C.get('xsec'))
4129+ logger.debug("channel %s need to improve by %.2f (xsec=%s pb, iter=%s)", C.name, goal_lum/(C.get('luminosity')+1e-99), C.get('xsec'), int(C.get('maxit')))
4130 to_refine.append(C)
4131 elif C.get('xerr') > max(C.get('axsec'),
4132 (1/(100*math.sqrt(self.err_goal)))*all_channels[-1].get('axsec')):
4133
4134=== added file 'madgraph/madevent/hel_recycle.py'
4135--- madgraph/madevent/hel_recycle.py 1970-01-01 00:00:00 +0000
4136+++ madgraph/madevent/hel_recycle.py 2021-01-30 10:13:29 +0000
4137@@ -0,0 +1,924 @@
4138+#!/usr/bin/env python3
4139+
4140+import argparse
4141+import atexit
4142+import re
4143+import collections
4144+from string import Template
4145+from copy import copy
4146+from itertools import product
4147+from functools import reduce
4148+
4149+try:
4150+ import madgraph
4151+except:
4152+ import internal.misc as misc
4153+else:
4154+ import madgraph.various.misc as misc
4155+import mmap
4156+try:
4157+ from tqdm import tqdm
4158+except ImportError:
4159+ tqdm = misc.tqdm
4160+
4161+
4162+def get_num_lines(file_path):
4163+ fp = open(file_path, 'r+')
4164+ buf = mmap.mmap(fp.fileno(),0)
4165+ lines = 0
4166+ while buf.readline():
4167+ lines += 1
4168+ return lines
4169+
4170+class DAG:
4171+
4172+ def __init__(self):
4173+ self.graph = {}
4174+ self.all_wavs = []
4175+ self.external_wavs = []
4176+ self.internal_wavs = []
4177+
4178+ def store_wav(self, wav, ext_deps=[]):
4179+ self.all_wavs.append(wav)
4180+ nature = wav.nature
4181+ if nature == 'external':
4182+ self.external_wavs.append(wav)
4183+ if nature == 'internal':
4184+ self.internal_wavs.append(wav)
4185+ for ext in ext_deps:
4186+ self.add_branch(wav, ext)
4187+
4188+ def add_branch(self, node_i, node_f):
4189+ try:
4190+ self.graph[node_i].append(node_f)
4191+ except KeyError:
4192+ self.graph[node_i] = [node_f]
4193+
4194+ def dependencies(self, old_name):
4195+ deps = [wav for wav in self.all_wavs
4196+ if wav.old_name == old_name and not wav.dead]
4197+ return deps
4198+
4199+ def kill_old(self, old_name):
4200+ for wav in self.all_wavs:
4201+ if wav.old_name == old_name:
4202+ wav.dead = True
4203+
4204+ def old_names(self):
4205+ return {wav.old_name for wav in self.all_wavs}
4206+
4207+ def find_path(self, start, end, path=[]):
4208+ '''Taken from https://www.python.org/doc/essays/graphs/'''
4209+
4210+ path = path + [start]
4211+ if start == end:
4212+ return path
4213+ if start not in self.graph:
4214+ return None
4215+ for node in self.graph[start]:
4216+ if node not in path:
4217+ newpath = self.find_path(node, end, path)
4218+ if newpath:
4219+ return newpath
4220+ return None
4221+
4222+ def __str__(self):
4223+ return self.__repr__()
4224+
4225+ def __repr__(self):
4226+ print_str = 'With new names:\n\t'
4227+ print_str += '\n\t'.join([f'{key} : {item}' for key, item in self.graph.items() ])
4228+ print_str += '\n\nWith old names:\n\t'
4229+ print_str += '\n\t'.join([f'{key.old_name} : {[i.old_name for i in item]}' for key, item in self.graph.items() ])
4230+ return print_str
4231+
4232+
4233+
4234+class MathsObject:
4235+ '''Abstract class for wavefunctions and Amplitudes'''
4236+
4237+ # Store here which externals the last wav/amp depends on.
4238+ # This saves us having to call find_path multiple times.
4239+ ext_deps = None
4240+
4241+ def __init__(self, arguments, old_name, nature):
4242+ self.args = arguments
4243+ self.old_name = old_name
4244+ self.nature = nature
4245+ self.name = None
4246+ self.dead = False
4247+ self.nb_used = 0
4248+ self.linkdag = []
4249+
4250+ def set_name(self, *args):
4251+ self.args[-1] = self.format_name(*args)
4252+ self.name = self.args[-1]
4253+
4254+ def format_name(self, *nums):
4255+ pass
4256+
4257+ @staticmethod
4258+ def get_deps(line, graph):
4259+ old_args = get_arguments(line)
4260+ old_name = old_args[-1].replace(' ','')
4261+ matches = graph.old_names() & set(old_args)
4262+ try:
4263+ matches.remove(old_name)
4264+ except KeyError:
4265+ pass
4266+ old_deps = old_args[0:len(matches)]
4267+
4268+ # If we're overwriting a wav clear it from graph
4269+ graph.kill_old(old_name)
4270+ return [graph.dependencies(dep) for dep in old_deps]
4271+
4272+ @classmethod
4273+ def good_helicity(cls, wavs, graph, diag_number=None, all_hel=[], bad_hel_amp=[]):
4274+ exts = graph.external_wavs
4275+ cls.ext_deps = { i for dep in wavs for i in exts if graph.find_path(dep, i) }
4276+ this_comb_good = False
4277+ for comb in External.good_wav_combs:
4278+ if cls.ext_deps.issubset(set(comb)):
4279+ this_comb_good = True
4280+ break
4281+
4282+ if diag_number and this_comb_good and cls.ext_deps:
4283+ helicity = dict([(a.get_id(), a.hel) for a in cls.ext_deps])
4284+ this_hel = [helicity[i] for i in range(1, len(helicity)+1)]
4285+ hel_number = 1 + all_hel.index(tuple(this_hel))
4286+
4287+ if (hel_number,diag_number) in bad_hel_amp:
4288+ this_comb_good = False
4289+
4290+
4291+
4292+ return this_comb_good and cls.ext_deps
4293+
4294+ @staticmethod
4295+ def get_new_args(line, wavs):
4296+ old_args = get_arguments(line)
4297+ old_name = old_args[-1].replace(' ','')
4298+ # Work out if wavs corresponds to an allowed helicity combination
4299+ this_args = copy(old_args)
4300+ wav_names = [w.name for w in wavs]
4301+ this_args[0:len(wavs)] = wav_names
4302+ # This isnt maximally efficient
4303+ # Could take the num from wavs that've been deleted in graph
4304+ return this_args
4305+
4306+ @staticmethod
4307+ def get_number():
4308+ pass
4309+
4310+ @classmethod
4311+ def get_obj(cls, line, wavs, graph, diag_num = None):
4312+ old_name = get_arguments(line)[-1].replace(' ','')
4313+ new_args = cls.get_new_args(line, wavs)
4314+ num = cls.get_number(wavs, graph)
4315+
4316+ this_obj = cls.call_constructor(new_args, old_name, diag_num)
4317+ this_obj.set_name(num, diag_num)
4318+ if this_obj.nature != 'amplitude':
4319+ graph.store_wav(this_obj, cls.ext_deps)
4320+ return this_obj
4321+
4322+
4323+ def __str__(self):
4324+ return self.name
4325+
4326+ def __repr__(self):
4327+ return self.name
4328+
4329+class External(MathsObject):
4330+ '''Class for storing external wavefunctions'''
4331+
4332+ good_hel = []
4333+ nhel_lines = ''
4334+ num_externals = 0
4335+ # Could get this from dag but I'm worried about preserving order
4336+ wavs_same_leg = {}
4337+ good_wav_combs = []
4338+
4339+ def __init__(self, arguments, old_name):
4340+ super().__init__(arguments, old_name, 'external')
4341+ self.hel = int(self.args[2])
4342+ self.hel_ranges = []
4343+ self.raise_num()
4344+
4345+ @classmethod
4346+ def raise_num(cls):
4347+ cls.num_externals += 1
4348+
4349+ @classmethod
4350+ def generate_wavfuncs(cls, line, graph):
4351+ # If graph is passed in Internal it should be done here to so
4352+ # we can set names
4353+ old_args = get_arguments(line)
4354+ old_name = old_args[-1].replace(' ','')
4355+ graph.kill_old(old_name)
4356+
4357+ if 'NHEL' in old_args[2].upper():
4358+ nhel_index = re.search(r'\(.*?\)', old_args[2]).group()
4359+ ext_num = int(nhel_index[1:-1]) - 1
4360+ new_hels = sorted(list(External.hel_ranges[ext_num]), reverse=True)
4361+ new_hels = [int_to_string(i) for i in new_hels]
4362+ else:
4363+ # Spinor must be a scalar so give it hel = 0
4364+ new_hels = [' 0']
4365+
4366+ new_wavfuncs = []
4367+ for hel in new_hels:
4368+
4369+ this_args = copy(old_args)
4370+ this_args[2] = hel
4371+
4372+ this_wavfunc = External(this_args, old_name)
4373+ this_wavfunc.set_name(len(graph.external_wavs) + len(graph.internal_wavs) +1)
4374+
4375+ graph.store_wav(this_wavfunc)
4376+ new_wavfuncs.append(this_wavfunc)
4377+
4378+ cls.wavs_same_leg[ext_num] = new_wavfuncs
4379+
4380+ return new_wavfuncs
4381+
4382+ @classmethod
4383+ def get_gwc(cls):
4384+ num_combs = len(cls.good_hel)
4385+ gwc = [[] for x in range(num_combs)]
4386+
4387+ for n, comb in enumerate(cls.good_hel):
4388+ for leg, wavs in cls.wavs_same_leg.items():
4389+ for wav in wavs:
4390+ if comb[leg] == wav.hel:
4391+ gwc[n].append(wav)
4392+
4393+ cls.good_wav_combs = gwc
4394+
4395+ @staticmethod
4396+ def format_name(*nums):
4397+ return f'W(1,{nums[0]})'
4398+
4399+ def get_id(self):
4400+ """ return the id of the particle under consideration """
4401+
4402+ try:
4403+ return self.id
4404+ except:
4405+ self.id = int(re.findall(r'P\(0,(\d+)\)', self.args[0])[0])
4406+ return self.id
4407+
4408+
4409+
4410+class Internal(MathsObject):
4411+ '''Class for storing internal wavefunctions'''
4412+
4413+ max_wav_num = 0
4414+ num_internals = 0
4415+
4416+ @classmethod
4417+ def raise_num(cls):
4418+ cls.num_internals += 1
4419+
4420+ @classmethod
4421+ def generate_wavfuncs(cls, line, graph):
4422+ deps = cls.get_deps(line, graph)
4423+ new_wavfuncs = [ cls.get_obj(line, wavs, graph)
4424+ for wavs in product(*deps)
4425+ if cls.good_helicity(wavs, graph) ]
4426+
4427+ return new_wavfuncs
4428+
4429+
4430+ # There must be a better way
4431+ @classmethod
4432+ def call_constructor(cls, new_args, old_name, diag_num):
4433+ return Internal(new_args, old_name)
4434+
4435+ @classmethod
4436+ def get_number(cls, *args):
4437+ num = External.num_externals + Internal.num_internals + 1
4438+ if cls.max_wav_num < num:
4439+ cls.max_wav_num = num
4440+ return num
4441+
4442+ def __init__(self, arguments, old_name):
4443+ super().__init__(arguments, old_name, 'internal')
4444+ self.raise_num()
4445+
4446+
4447+ @staticmethod
4448+ def format_name(*nums):
4449+ return f'W(1,{nums[0]})'
4450+
4451+class Amplitude(MathsObject):
4452+ '''Class for storing Amplitudes'''
4453+
4454+ max_amp_num = 0
4455+
4456+ def __init__(self, arguments, old_name, diag_num):
4457+ self.diag_num = diag_num
4458+ super().__init__(arguments, old_name, 'amplitude')
4459+
4460+
4461+ @staticmethod
4462+ def format_name(*nums):
4463+ return f'AMP({nums[0]},{nums[1]})'
4464+
4465+ @classmethod
4466+ def generate_amps(cls, line, graph, all_hel=None, all_bad_hel=[]):
4467+ old_args = get_arguments(line)
4468+ old_name = old_args[-1].replace(' ','')
4469+
4470+ amp_index = re.search(r'\(.*?\)', old_name).group()
4471+ diag_num = int(amp_index[1:-1])
4472+
4473+ deps = cls.get_deps(line, graph)
4474+
4475+ new_amps = [cls.get_obj(line, wavs, graph, diag_num)
4476+ for wavs in product(*deps)
4477+ if cls.good_helicity(wavs, graph, diag_num, all_hel,all_bad_hel)]
4478+
4479+ return new_amps
4480+
4481+ @classmethod
4482+ def call_constructor(cls, new_args, old_name, diag_num):
4483+ return Amplitude(new_args, old_name, diag_num)
4484+
4485+ @classmethod
4486+ def get_number(cls, *args):
4487+ wavs, graph = args
4488+ amp_num = -1
4489+ exts = graph.external_wavs
4490+ for i, comb in enumerate(External.good_wav_combs):
4491+ if set(comb) == set(cls.ext_deps):
4492+ # Offset because Fortran counts from 1
4493+ amp_num = i + 1
4494+ if amp_num < 1:
4495+ set_trace()
4496+ print('Failed to find amp_num')
4497+ exit(1)
4498+ if cls.max_amp_num < amp_num:
4499+ cls.max_amp_num = amp_num
4500+ return amp_num
4501+
4502+class HelicityRecycler():
4503+ '''Class for recycling helicity'''
4504+
4505+ def __init__(self, good_elements, bad_amps=[], bad_amps_perhel=[]):
4506+
4507+ External.good_hel = []
4508+ External.nhel_lines = ''
4509+ External.num_externals = 0
4510+ External.wavs_same_leg = {}
4511+ External.good_wav_combs = []
4512+
4513+ Internal.max_wav_num = 0
4514+ Internal.num_internals = 0
4515+
4516+ Amplitude.max_amp_num = 0
4517+
4518+ self.good_elements = good_elements
4519+ self.bad_amps = bad_amps
4520+ self.bad_amps_perhel = bad_amps_perhel
4521+
4522+ # Default file names
4523+ self.input_file = 'matrix_orig.f'
4524+ self.output_file = 'matrix_orig.f'
4525+ self.template_file = 'template_matrix.f'
4526+
4527+ self.template_dict = {}
4528+ #initialise everything as for zero matrix element
4529+ self.template_dict['helicity_lines'] = '\n'
4530+ self.template_dict['helas_calls'] = []
4531+ self.template_dict['jamp_lines'] = '\n'
4532+ self.template_dict['amp2_lines'] = '\n'
4533+ self.template_dict['ncomb'] = '0'
4534+ self.template_dict['nwavefuncs'] = '0'
4535+
4536+ self.dag = DAG()
4537+
4538+ self.diag_num = 1
4539+ self.got_gwc = False
4540+
4541+ self.procedure_name = self.input_file.split('.')[0].upper()
4542+ self.procedure_kind = 'FUNCTION'
4543+
4544+ self.old_out_name = ''
4545+ self.loop_var = 'K'
4546+
4547+ self.all_hel = []
4548+ self.hel_filt = True
4549+
4550+ def set_input(self, file):
4551+ if 'born_matrix' in file:
4552+ print('HelicityRecycler is currently '
4553+ f'unable to handle {file}')
4554+ exit(1)
4555+ self.procedure_name = file.split('.')[0].upper()
4556+ self.procedure_kind = 'FUNCTION'
4557+ self.input_file = file
4558+
4559+ def set_output(self, file):
4560+ self.output_file = file
4561+
4562+ def set_template(self, file):
4563+ self.template_file = file
4564+
4565+ def function_call(self, line):
4566+ # Check a function is called at all
4567+ if not 'CALL' in line:
4568+ return None
4569+
4570+ # Now check for external spinor
4571+ ext_calls = ['CALL OXXXXX', 'CALL IXXXXX', 'CALL VXXXXX', 'CALL SXXXXX']
4572+ if any( call in line for call in ext_calls ):
4573+ return 'external'
4574+
4575+ # Now check for internal
4576+ # Wont find a internal when no externals have been found...
4577+ # ... I assume
4578+ if not self.dag.external_wavs:
4579+ return None
4580+
4581+ # Search for internals by looking for calls to the externals
4582+ # Maybe I should just get a list of all internals?
4583+ matches = self.dag.old_names() & set(get_arguments(line))
4584+ try:
4585+ matches.remove(get_arguments(line)[-1])
4586+ except KeyError:
4587+ pass
4588+ try:
4589+ function = (line.split('(', 1)[0]).split()[-1]
4590+ except IndexError:
4591+ return None
4592+ # What if [-1] is garbage? Then I'm relying on needs changing.
4593+ # Is that OK?
4594+ if (function.split('_')[-1] != '0'):
4595+ return 'internal'
4596+ elif (function.split('_')[-1] == '0'):
4597+ return 'amplitude'
4598+ else:
4599+ print(f'Ahhhh what is going on here?\n{line}')
4600+ set_trace()
4601+
4602+ return None
4603+
4604+ # string manipulation
4605+
4606+ def add_amp_index(self, matchobj):
4607+ old_pat = matchobj.group()
4608+ new_pat = old_pat.replace('AMP(', 'AMP( %s,' % self.loop_var)
4609+ #misc.sprint(self.loop_var, old_pat)
4610+
4611+ #new_pat = f'{self.loop_var},{old_pat[:-1]}{old_pat[-1]}'
4612+ return new_pat
4613+
4614+ def add_indices(self, line):
4615+ '''Add loop_var index to amp and output variable.
4616+ Also update name of output variable.'''
4617+ # Doesnt work if the AMP arguments contain brackets
4618+ new_line = re.sub(r'\WAMP\(.*?\)', self.add_amp_index, line)
4619+ new_line = re.sub(r'MATRIX\d+', 'TS(K)', new_line)
4620+ return new_line
4621+
4622+ def jamp_finished(self, line):
4623+ # indent_end = re.compile(fr'{self.jamp_indent}END\W')
4624+ # m = indent_end.match(line)
4625+ # if m:
4626+ # return True
4627+ return 'init_mode' in line.lower()
4628+ #if f'{self.old_out_name}=0.D0' in line.replace(' ', ''):
4629+ # return True
4630+ #return False
4631+
4632+ def get_old_name(self, line):
4633+ if f'{self.procedure_kind} {self.procedure_name}' in line:
4634+ if 'SUBROUTINE' == self.procedure_kind:
4635+ self.old_out_name = get_arguments(line)[-1]
4636+ if 'FUNCTION' == self.procedure_kind:
4637+ self.old_out_name = line.split('(')[0].split()[-1]
4638+
4639+ def get_amp_stuff(self, line_num, line):
4640+
4641+ if 'diagram number' in line:
4642+ self.amp_calc_started = True
4643+ # Check if the calculation of this diagram is finished
4644+ if ('AMP' not in get_arguments(line)[-1]
4645+ and self.amp_calc_started and list(line)[0] != 'C'):
4646+ # Check if the calculation of all diagrams is finished
4647+ if self.function_call(line) not in ['external',
4648+ 'internal',
4649+ 'amplitude']:
4650+ self.jamp_started = True
4651+ self.amp_calc_started = False
4652+ if self.jamp_started:
4653+ self.get_jamp_lines(line)
4654+ if self.in_amp2:
4655+ self.get_amp2_lines(line)
4656+ if self.find_amp2 and line.startswith(' ENDDO'):
4657+ self.in_amp2 = True
4658+ self.find_amp2 = False
4659+
4660+ def get_jamp_lines(self, line):
4661+ if self.jamp_finished(line):
4662+ self.jamp_started = False
4663+ self.find_amp2 = True
4664+ elif not line.isspace():
4665+ self.template_dict['jamp_lines'] += f'{line[0:6]} {self.add_indices(line[6:])}'
4666+
4667+ def get_amp2_lines(self, line):
4668+ if line.startswith(' DO I = 1, NCOLOR'):
4669+ self.in_amp2 = False
4670+ elif not line.isspace():
4671+ self.template_dict['amp2_lines'] += f'{line[0:6]} {self.add_indices(line[6:])}'
4672+
4673+ def prepare_bools(self):
4674+ self.amp_calc_started = False
4675+ self.jamp_started = False
4676+ self.find_amp2 = False
4677+ self.in_amp2 = False
4678+ self.nhel_started = False
4679+
4680+ def unfold_helicities(self, line, nature):
4681+
4682+
4683+
4684+ #print('deps',line, deps)
4685+ if nature not in ['external', 'internal', 'amplitude']:
4686+ raise Exception('wrong unfolding')
4687+
4688+ if nature == 'external':
4689+ new_objs = External.generate_wavfuncs(line, self.dag)
4690+ for obj in new_objs:
4691+ obj.line = apply_args(line, [obj.args])
4692+ else:
4693+ deps = Amplitude.get_deps(line, self.dag)
4694+ name2dep = dict([(d.name,d) for d in sum(deps,[])])
4695+
4696+
4697+ if nature == 'internal':
4698+ new_objs = Internal.generate_wavfuncs(line, self.dag)
4699+ for obj in new_objs:
4700+ obj.line = apply_args(line, [obj.args])
4701+ obj.linkdag = []
4702+ for name in obj.args:
4703+ if name in name2dep:
4704+ name2dep[name].nb_used +=1
4705+ obj.linkdag.append(name2dep[name])
4706+
4707+ if nature == 'amplitude':
4708+ nb_diag = re.findall(r'AMP\((\d+)\)', line)[0]
4709+ if nb_diag not in self.bad_amps:
4710+ new_objs = Amplitude.generate_amps(line, self.dag, self.all_hel, self.bad_amps_perhel)
4711+ out_line = self.apply_amps(line, new_objs)
4712+ for i,obj in enumerate(new_objs):
4713+ if i == 0:
4714+ obj.line = out_line
4715+ obj.nb_used = 1
4716+ else:
4717+ obj.line = ''
4718+ obj.nb_used = 1
4719+ obj.linkdag = []
4720+ for name in obj.args:
4721+ if name in name2dep:
4722+ name2dep[name].nb_used +=1
4723+ obj.linkdag.append(name2dep[name])
4724+ else:
4725+ return ''
4726+
4727+
4728+ return new_objs
4729+ #return f'{line}\n' if nature == 'external' else line
4730+
4731+ def apply_amps(self, line, new_objs):
4732+ if self.amp_splt:
4733+ return split_amps(line, new_objs)
4734+ else:
4735+
4736+ return apply_args(line, [i.args for i in new_objs])
4737+
4738+ def get_gwc(self, line):
4739+ if self.got_gwc:
4740+ return
4741+
4742+ num_found = len({obj.old_name for obj in self.template_dict['helas_calls']
4743+ if isinstance(obj, External)})
4744+
4745+ try:
4746+ num_exts = len(External.good_hel[0])
4747+ except IndexError:
4748+ return
4749+ if num_found <= num_exts:
4750+ External.get_gwc()
4751+ if num_found == num_exts :
4752+ self.got_gwc=True
4753+
4754+ def get_good_hel(self, line):
4755+ if 'DATA (NHEL' in line:
4756+ self.nhel_started = True
4757+ this_hel = [int(hel) for hel in line.split('/')[1].split(',')]
4758+ self.all_hel.append(tuple(this_hel))
4759+ elif self.nhel_started:
4760+ self.nhel_started = False
4761+
4762+ if self.hel_filt:
4763+ External.good_hel = [ self.all_hel[int(i)-1] for i in self.good_elements ]
4764+ else:
4765+ External.good_hel = self.all_hel
4766+
4767+ External.hel_ranges = [set() for hel in External.good_hel[0]]
4768+ for comb in External.good_hel:
4769+ for i, hel in enumerate(comb):
4770+ External.hel_ranges[i].add(hel)
4771+
4772+ self.counter = 0
4773+ nhel_array = [self.nhel_string(hel)
4774+ for hel in External.good_hel]
4775+ nhel_lines = '\n'.join(nhel_array)
4776+ self.template_dict['helicity_lines'] += nhel_lines
4777+
4778+ self.template_dict['ncomb'] = len(External.good_hel)
4779+
4780+ def nhel_string(self, hel_comb):
4781+ self.counter += 1
4782+ formatted_hel = [f'{hel}' if hel < 0 else f' {hel}' for hel in hel_comb]
4783+ nexternal = len(hel_comb)
4784+ return (f' DATA (NHEL(I,{self.counter}),I=1,{nexternal}) /{",".join(formatted_hel)}/')
4785+
4786+ def read_orig(self):
4787+
4788+ with open(self.input_file, 'r') as input_file:
4789+
4790+ self.prepare_bools()
4791+
4792+ for line_num, line in tqdm(enumerate(input_file), total=get_num_lines(self.input_file)):
4793+ if line_num == 0:
4794+ line_cache = line
4795+ continue
4796+
4797+ if '!SKIP' in line:
4798+ continue
4799+
4800+ char_5 = ''
4801+ try:
4802+ char_5 = line[5]
4803+ except IndexError:
4804+ pass
4805+ if char_5 == '$':
4806+ line_cache = undo_multiline(line_cache, line)
4807+ continue
4808+
4809+ line, line_cache = line_cache, line
4810+
4811+ self.get_old_name(line)
4812+ self.get_good_hel(line)
4813+ self.get_amp_stuff(line_num, line)
4814+ self.get_gwc(line)
4815+
4816+ call_type = self.function_call(line)
4817+ if call_type in ['external', 'internal', 'amplitude']:
4818+ self.template_dict['helas_calls'] += self.unfold_helicities(
4819+ line, call_type)
4820+
4821+ self.template_dict['nwavefuncs'] = max(External.num_externals, Internal.max_wav_num)
4822+ # filter out uselless call
4823+ for i in range(len(self.template_dict['helas_calls'])-1,-1,-1):
4824+ obj = self.template_dict['helas_calls'][i]
4825+ if obj.nb_used == 0:
4826+ obj.line = ''
4827+ for dep in obj.linkdag:
4828+ dep.nb_used -= 1
4829+
4830+
4831+
4832+ self.template_dict['helas_calls'] = '\n'.join([f'{obj.line.rstrip()} ! count {obj.nb_used}'
4833+ for obj in self.template_dict['helas_calls']
4834+ if obj.nb_used > 0 and obj.line])
4835+
4836+ def read_template(self):
4837+ out_file = open(self.output_file, 'w+')
4838+ with open(self.template_file, 'r') as file:
4839+ for line in file:
4840+ s = Template(line)
4841+ line = s.safe_substitute(self.template_dict)
4842+ line = '\n'.join([do_multiline(sub_lines) for sub_lines in line.split('\n')])
4843+ out_file.write(line)
4844+ out_file.close()
4845+
4846+ def write_zero_matrix_element(self):
4847+ out_file = open(self.output_file, 'w+')
4848+ self.template_dict['ncomb'] = '0'
4849+ self.template_dict['nwavefuncs'] = '0'
4850+ self.template_dict['helas_calls'] = ''
4851+ with open(self.template_file, 'r') as file:
4852+ for line in file:
4853+ s = Template(line)
4854+ line = s.safe_substitute(self.template_dict)
4855+ line = '\n'.join([do_multiline(sub_lines) for sub_lines in line.split('\n')])
4856+ out_file.write(line)
4857+ out_file.close()
4858+
4859+
4860+ def generate_output_file(self):
4861+ if not self.good_elements:
4862+ misc.sprint("No helicity", self.input_file)
4863+ self.write_zero_matrix_element()
4864+ return
4865+
4866+ atexit.register(self.clean_up)
4867+ self.read_orig()
4868+ self.read_template()
4869+ atexit.unregister(self.clean_up)
4870+
4871+ def clean_up(self):
4872+ pass
4873+
4874+
4875+def get_arguments(line):
4876+ '''Find the substrings separated by commas between the first
4877+ closed set of parentheses in 'line'.
4878+ '''
4879+ bracket_depth = 0
4880+ element = 0
4881+ arguments = ['']
4882+ for char in line:
4883+ if char == '(':
4884+ bracket_depth += 1
4885+ if bracket_depth - 1 == 0:
4886+ # This is the first '('. We don't want to add it to
4887+ # 'arguments'
4888+ continue
4889+ if char == ')':
4890+ bracket_depth -= 1
4891+ if bracket_depth == 0:
4892+ # We've reached the end
4893+ break
4894+ if char == ',' and bracket_depth == 1:
4895+ element += 1
4896+ arguments.append('')
4897+ continue
4898+ if bracket_depth > 0:
4899+ arguments[element] += char
4900+ return arguments
4901+
4902+
4903+def apply_args(old_line, all_the_args):
4904+ function = (old_line.split('(')[0]).split()[-1]
4905+ old_args = old_line.split(function)[-1]
4906+ new_lines = [old_line.replace(old_args, f'({",".join(x)})\n')
4907+ for x in all_the_args]
4908+
4909+ return ''.join(new_lines)
4910+
4911+def split_amps(line, new_amps):
4912+ fct = line.split('(',1)[0].split('_0')[0]
4913+ for i,amp in enumerate(new_amps):
4914+ if i == 0:
4915+ occur = []
4916+ for a in amp.args:
4917+ if "W(1," in a:
4918+ tmp = collections.defaultdict(int)
4919+ tmp[a] += 1
4920+ occur.append(tmp)
4921+ else:
4922+ for i in range(len(occur)):
4923+ a = amp.args[i]
4924+ occur[i][a] +=1
4925+ # Each element in occur is the wavs that appear in a column, with
4926+ # the number of occurences
4927+ nb_wav = [len(o) for o in occur]
4928+ to_remove = nb_wav.index(max(nb_wav))
4929+ # Remove the one that occurs the most
4930+ occur.pop(to_remove)
4931+
4932+ lines = []
4933+ # Get the wavs per column
4934+ wav_name = [o.keys() for o in occur]
4935+ for wfcts in product(*wav_name):
4936+ # Select the amplitudes produced by wfcts
4937+ sub_amps = [amp for amp in new_amps
4938+ if all(w in amp.args for w in wfcts)]
4939+ if not sub_amps:
4940+ continue
4941+ if len(sub_amps) ==1:
4942+ lines.append(apply_args(line, [i.args for i in sub_amps]).replace('\n',''))
4943+
4944+ continue
4945+
4946+ # the next line is to make the code nicer
4947+ sub_amps.sort(key=lambda a: int(a.args[-1][:-1].split(',',1)[1]))
4948+ windices = []
4949+ hel_calculated = []
4950+ iamp = 0
4951+ for i,amp in enumerate(sub_amps):
4952+ args = amp.args[:]
4953+ # Remove wav and get its index
4954+ wcontract = args.pop(to_remove)
4955+ windex = wcontract.split(',')[1].split(')')[0]
4956+ windices.append(windex)
4957+ amp_result, args[-1] = args[-1], 'TMP(1)'
4958+
4959+ if i ==0:
4960+ # Call the original fct with P1N_...
4961+ # Final arg is replaced with TMP(1)
4962+ spin = fct.split(None,1)[1][to_remove]
4963+ lines.append('%sP1N_%s(%s)' % (fct, to_remove+1, ', '.join(args)))
4964+
4965+ hel, iamp = re.findall('AMP\((\d+),(\d+)\)', amp_result)[0]
4966+ hel_calculated.append(hel)
4967+ #lines.append(' %(result)s = TMP(3) * W(3,%(w)s) + TMP(4) * W(4,%(w)s)+'
4968+ # % {'result': amp_result, 'w': windex})
4969+ #lines.append(' & TMP(5) * W(5,%(w)s)+TMP(6) * W(6,%(w)s)'
4970+ # % {'result': amp_result, 'w': windex})
4971+ if spin in "VF":
4972+ lines.append(""" call CombineAmp(%(nb)i,
4973+ & (/%(hel_list)s/),
4974+ & (/%(w_list)s/),
4975+ & TMP, W, AMP(1,%(iamp)s))""" %
4976+ {'nb': len(sub_amps),
4977+ 'hel_list': ','.join(hel_calculated),
4978+ 'w_list': ','.join(windices),
4979+ 'iamp': iamp
4980+ })
4981+ elif spin == "S":
4982+ lines.append(""" call CombineAmpS(%(nb)i,
4983+ &(/%(hel_list)s/),
4984+ & (/%(w_list)s/),
4985+ & TMP, W, AMP(1,%(iamp)s))""" %
4986+ {'nb': len(sub_amps),
4987+ 'hel_list': ','.join(hel_calculated),
4988+ 'w_list': ','.join(windices),
4989+ 'iamp': iamp
4990+ })
4991+ else:
4992+ raise Exception("split amp are not supported for spin2 and 3/2")
4993+
4994+ #lines.append('')
4995+ return '\n'.join(lines)
4996+
4997+def get_num(wav):
4998+ name = wav.name
4999+ between_brackets = re.search(r'\(.*?\)', name).group()
5000+ num = int(between_brackets[1:-1].split(',')[-1])
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: