Merge lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel into lp:~mg5core2/mg5amcnlo/2.6.3
- 2.6.3_optimizenlomodel
- Merge into 2.6.3
Status: | Merged |
---|---|
Merged at revision: | 314 |
Proposed branch: | lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel |
Merge into: | lp:~mg5core2/mg5amcnlo/2.6.3 |
Diff against target: |
1284 lines (+672/-101) 16 files modified
UpdateNotes.txt (+11/-1) aloha/aloha_writers.py (+21/-6) aloha/create_aloha.py (+2/-3) madgraph/loop/loop_helas_objects.py (+1/-2) madgraph/various/misc.py (+2/-1) mg5decay/decay_objects.py (+1/-1) models/import_ufo.py (+281/-32) tests/acceptance_tests/test_model_equivalence.py (+5/-2) tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P0_wpwm_wpwm%matrix.f (+8/-8) tests/parallel_tests/test_ML5.py (+1/-1) tests/parallel_tests/test_ML5MSSMQCD.py (+1/-1) tests/parallel_tests/test_aloha.py (+168/-2) tests/unit_tests/iolibs/test_export_v4.py (+1/-1) tests/unit_tests/iolibs/test_helas_call_writers.py (+30/-30) tests/unit_tests/various/test_decay.py (+2/-2) tests/unit_tests/various/test_import_ufo.py (+137/-8) |
To merge this branch: | bzr merge lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Valentin Hirschi (community) | Approve | ||
Review via email: mp+346864@code.launchpad.net |
Commit message
1) include a analyze of the model at (first) loading time to merge multiple lorentz structure in a single one if they have the same coupling (which allows better optimization at ALOHA level and cleaner code)
2) if ALOHA name, use a hash method to keep it short (will be problematic for debugging since the name is machine dependent)
3) improve test suite (and fixed a bug associated to get_custom_propa)
Description of the change
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Valentin Hirschi (valentin-hirschi) wrote : | # |
Ok, I'll wait for your go-ahead then.
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi,
OK this seems quite stable now.
I'm just a bit worried that the parallel test might not be complete enough to detect issue here.
I think that such changes can be really important for complex model (in term of speed/precision).
But such improvement required complex model but this makes the possibility to not detect the introduction of subtle bugs (which will not be detected via unittest/...).
If you have an idea of parallel test (i.e. model/process) this would be great.
Cheers,
Olivier
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi,
I have tested that setting the merged R2 for gggg to zero was leading to the following difference to the g g > g g [virt=QCD]:
Finite = -6.663418777189
to
Finite = -6.671487628945
So we have at least that parralel test which is sensitive to such modification so we should be safe here.
Cheers,
Olivier
- 287. By olivier-mattelaer
-
merge with latest 2.6.3
Valentin Hirschi (valentin-hirschi) wrote : | # |
Hi Olivier,
As I wrote on Skype, I think the coverage of parallel tests of MadLoop5 for
the SM is really exhaustive (complex-mass scheme excluded however).
Cheers,
On Fri, Jun 1, 2018 at 2:52 PM, Olivier Mattelaer <
<email address hidden>> wrote:
> Hi,
>
> I have tested that setting the merged R2 for gggg to zero was leading to
> the following difference to the g g > g g [virt=QCD]:
> Finite = -6.663418777189
> to
> Finite = -6.671487628945
> to 0]
>
> So we have at least that parralel test which is sensitive to such
> modification so we should be safe here.
>
>
> Cheers,
>
> Olivier
> --
> https:/
> optimizenlomode
> You are requested to review the proposed merge of
> lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel into
> lp:~mg5core2/mg5amcnlo/2.6.3.
>
--
Valentin
- 288. By olivier-mattelaer
-
fixing issue with the mssm model
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi,
I plan to release 2.6.3, should I understand that this is not going to be in 2.6.3.
(I do not care you were the one pushing for it)
Cheers,
Olivier
Valentin Hirschi (valentin-hirschi) wrote : | # |
Hi Olivier,
Thanks a lot for this improvement! I checked that the problematic model with long aloha name now goes through fine with identical results as before.
I also tried a complicated 2->4 electroweak loop process which again yielded identical results.
This, together with the existing other parallel tests and the additional ones you've put in place should give us confidence that this can be merged in 2.6.3.
I don't have any smart comment on the code (I also don't know ALOHA well enough), but I was wondering if there would be a benefit in having a special aloha mode which defines a unique different aloha routine for each vertex with definite with a definite colour structure.
This way you could maximise the computational efficiency of the Lorentz part of each vertex in the model. That would of course be inefficient in terms of the size of ALOHA output, but this may sometimes be a trade-of you would be willing to make.
I'm thinking of this now, because I feel that the implementation of the mode described above would have some similarities with what you just implemented.
Anyway, I approve this merge.
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi,
> I don't have any smart comment on the code (I also don't know ALOHA well enough), but I was wondering if there would be a benefit in having a special aloha mode which defines a unique different aloha routine for each vertex with definite with a definite colour structure.
> This way you could maximise the computational efficiency of the Lorentz part of each vertex in the model. That would of course be inefficient in terms of the size of ALOHA output, but this may sometimes be a trade-of you would be willing to make.
> I'm thinking of this now, because I feel that the implementation of the mode described above would have some similarities with what you just implemented.
Can you explain more? I do not see the difference that you propose compare to what is in place now?
Cheers,
Olivier
> On 12 Jun 2018, at 11:11, Valentin Hirschi <email address hidden> wrote:
>
> Review: Approve
>
> Hi Olivier,
>
> Thanks a lot for this improvement! I checked that the problematic model with long aloha name now goes through fine with identical results as before.
> I also tried a complicated 2->4 electroweak loop process which again yielded identical results.
> This, together with the existing other parallel tests and the additional ones you've put in place should give us confidence that this can be merged in 2.6.3.
>
> I don't have any smart comment on the code (I also don't know ALOHA well enough), but I was wondering if there would be a benefit in having a special aloha mode which defines a unique different aloha routine for each vertex with definite with a definite colour structure.
> This way you could maximise the computational efficiency of the Lorentz part of each vertex in the model. That would of course be inefficient in terms of the size of ALOHA output, but this may sometimes be a trade-of you would be willing to make.
> I'm thinking of this now, because I feel that the implementation of the mode described above would have some similarities with what you just implemented.
>
> Anyway, I approve this merge.
> --
> https:/
> Your team MadDevelopers is subscribed to branch lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel.
Valentin Hirschi (valentin-hirschi) wrote : | # |
Nevermind, I worked it out again and realised what you did is basically the best you can get already. In general, if you have this interaction:
particles = [p.A, p.B, p.C]
color = ['C1','C2']
lorentz = [L.LA, L.LB, L.LC]
couplings = {
(0,0): C.G1, (0,1): C.G2, (0,2): C.G3,
(1,0): C.G4, (1,1): C.G5
}
you can generalise your procedure by defining the following two Lorentz structure being basically:
L.LA + (C.G2/C.G1)*L.B + (C.G3/C.G1)*L.C
and
L.LA + (C.G5/C.G4)*L.B
But I now realise that it's pointless/hard to do this if (C.G<i>/C.G<j>)=K , with K having model parametric dependence. You implemented this for K= +/-1, and in principle it could be extended to any integer, but that has very little value in practice indeed.
So I agree, what you did is already basically the best you can get already.
Cheers
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi,
To be complete I detect K=1
only if it is analytically 1 (and trivially so, i.e. if both use the same name
The case K=+/-1 is tackle ONLY for restricted model and the comparison is done numerically.
I would not like to pass to numerical comparison for ALL integer since it is too dangerous to have false positif.
Also doing K=+/-2 differs from the actual description of the restrict_model (but thate
Now it would make sense to look at the K as any integer at the analytical level.
But I'm slightly worried about the time impact (at the same time this is only the first time since it is save in the pkl). I think i will test something with string comparison:
something like:
couplings.
for i in range(len(
for j in range(i+1, len(couplings))
c1, c2 = couplings[i], couplings[j]
c2.expr = c2.expr.
Then a simple regular expression should be able to detect case where
c2.expr=" 2 * GC_1"
What do you think?
Cheers,
Olivier
> On 12 Jun 2018, at 16:31, Valentin Hirschi <email address hidden> wrote:
>
> Nevermind, I worked it out again and realised what you did is basically the best you can get already. In general, if you have this interaction:
>
> particles = [p.A, p.B, p.C]
> color = ['C1','C2']
> lorentz = [L.LA, L.LB, L.LC]
> couplings = {
> (0,0): C.G1, (0,1): C.G2, (0,2): C.G3,
> (1,0): C.G4, (1,1): C.G5
> }
>
> you can generalise your procedure by defining the following two Lorentz structure being basically:
>
> L.LA + (C.G2/C.G1)*L.B + (C.G3/C.G1)*L.C
>
> and
>
> L.LA + (C.G5/C.G4)*L.B
>
> But I now realise that it's pointless/hard to do this if (C.G<i>/C.G<j>)=K , with K having model parametric dependence. You implemented this for K= +/-1, and in principle it could be extended to any integer, but that has very little value in practice indeed.
> So I agree, what you did is already basically the best you can get already.
>
> Cheers
>
> --
> https:/
> Your team MadDevelopers is subscribed to branch lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel.
Valentin Hirschi (valentin-hirschi) wrote : | # |
Hi,
On Tue, Jun 12, 2018 at 10:00 PM, Olivier Mattelaer <
<email address hidden>> wrote:
> Hi,
>
> To be complete I detect K=1
> only if it is analytically 1 (and trivially so, i.e. if both use the same
> name
>
Mhh, It may be nice to cover K=-1 too no?
> The case K=+/-1 is tackle ONLY for restricted model and the comparison is
> done numerically.
> I would not like to pass to numerical comparison for ALL integer since it
> is too dangerous to have false positif.
> Also doing K=+/-2 differs from the actual description of the
> restrict_model (but thate
>
I agree completely here, such false positive would be really hard to track
down.
>
> Now it would make sense to look at the K as any integer at the analytical
> level.
> But I'm slightly worried about the time impact (at the same time this is
> only the first time since it is save in the pkl). I think i will test
> something with string comparison:
>
> something like:
>
> couplings.
> for i in range(len(
> for j in range(i+1, len(couplings))
> c1, c2 = couplings[i], couplings[j]
> c2.expr = c2.expr.
>
> Then a simple regular expression should be able to detect case where
>
> c2.expr=" 2 * GC_1"
>
> What do you think?
>
That could work I suppose, but I think that in practice it makes very
little difference because most of the model will benefit from
simplifications where K is -1 or 1.
So in my opinion, it's not worth the effort:
PS: checkout sympy, it's nice to keep that option in mind for possible
future applications one day (though for anything heavy, it would be better
to wait for the upcoming python bindings of the new version of FORM).
Cheers,
>
> Cheers,
>
> Olivier
>
> > On 12 Jun 2018, at 16:31, Valentin Hirschi <email address hidden>
> wrote:
> >
> > Nevermind, I worked it out again and realised what you did is basically
> the best you can get already. In general, if you have this interaction:
> >
> > particles = [p.A, p.B, p.C]
> > color = ['C1','C2']
> > lorentz = [L.LA, L.LB, L.LC]
> > couplings = {
> > (0,0): C.G1, (0,1): C.G2, (0,2): C.G3,
> > (1,0): C.G4, (1,1): C.G5
> > }
> >
> > you can generalise your procedure by defining the following two Lorentz
> structure being basically:
> >
> > L.LA + (C.G2/C.G1)*L.B + (C.G3/C.G1)*L.C
> >
> > and
> >
> > L.LA + (C.G5/C.G4)*L.B
> >
> > But I now realise that it's pointless/hard to do this if
> (C.G<i>/C.G<j>)=K , with K having model parametric dependence. You
> implemented this for K= +/-1, and in principle it could be extended to any
> integer, but that has very little value in practice indeed.
> > So I agree, what you did is already basically the best you can get
> already.
> >
> > Cheers
> >
> > --
> > https:/
> optimizenlomode
> > Your team MadDevelopers is subscribed to branch
> lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel.
>
>
> --
> https:/
> optimizenlomode
> You are reviewing the proposed merge of lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel
> into lp:~mg5core2/mg5...
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Mhh, It may be nice to cover K=-1 too no?
Nice yes, but quite heavy.
(ALOHA itself will be quite slow for such task,
yacc and lex are a fast enough solution but quite heavy to implement.
regular expression might be easy enough but quite slow.
The best would be that such identification be part of the UFO model and not something that we have to discover...
This is quite hard since you have case like
a/(b+c) + c + (d+ e)/f
and the opposite
-a/(b+c) - c + (d+ e)/(-f)
(ok I'm slightly complexify what we will face but the problem is there)
Cheers,
Olivier
On 12 Jun 2018, at 22:27, Valentin Hirschi <<email address hidden>
Hi,
On Tue, Jun 12, 2018 at 10:00 PM, Olivier Mattelaer <
<email address hidden>
Hi,
To be complete I detect K=1
only if it is analytically 1 (and trivially so, i.e. if both use the same
name
Mhh, It may be nice to cover K=-1 too no?
The case K=+/-1 is tackle ONLY for restricted model and the comparison is
done numerically.
I would not like to pass to numerical comparison for ALL integer since it
is too dangerous to have false positif.
Also doing K=+/-2 differs from the actual description of the
restrict_model (but thate
I agree completely here, such false positive would be really hard to track
down.
Now it would make sense to look at the K as any integer at the analytical
level.
But I'm slightly worried about the time impact (at the same time this is
only the first time since it is save in the pkl). I think i will test
something with string comparison:
something like:
couplings.
for i in range(len(
for j in range(i+1, len(couplings))
c1, c2 = couplings[i], couplings[j]
Then a simple regular expression should be able to detect case where
c2.expr=" 2 * GC_1"
What do you think?
That could work I suppose, but I think that in practice it makes very
little difference because most of the model will benefit from
simplifications where K is -1 or 1.
So in my opinion, it's not worth the effort:
PS: checkout sympy, it's nice to keep that option in mind for possible
future applications one day (though for anything heavy, it would be better
to wait for the upcoming python bindings of the new version of FORM).
Cheers,
Cheers,
Olivier
On 12 Jun 2018, at 16:31, Valentin Hirschi <<email address hidden>
wrote:
Nevermind, I worked it out again and realised what you did is basically
the best you can get already. In general, if you have this interaction:
particles = [p.A, p.B, p.C]
color = ['C1','C2']
lorentz = [L.LA, L.LB, L.LC]
couplings = {
(0,0): C.G1, (0,1): C.G2, (0,2): C.G3,
(1,0): C.G4, (1,1): C.G5
}
you can generalise your procedure by defining the following two Lorentz
structure being basically:
L.LA + (C.G2/C.G1)*L.B + (C.G3/C.G1)*L.C
and
L.LA + (C.G5/C.G4)*L.B
But I now realise that it's pointless/hard to do this if
(C.G<i>/C.G<j>)=K , with K having model parametric dependence. You
implemented this for K= +/-1, and in principle it could be extended t...
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
I have run the following code on the loop_sm model.
It basically strips all the + and - of any expression and identifies equal string.
This is obviously not save but instructive of the issue to handle:
#check opposite couplings
for key in self.couplings:
for C in self.couplings[
I put below the result of the print statement. (and put in bold the false positif expression)
DEBUG: '\n'.join(
[('GC_1009', 'ee__exp_
[('GC_1091', 'ym'), ('GC_1090', '-ym')]
[('GC_1087', 'ye'), ('GC_1086', '-ye')]
[('GC_21', '-(cw*ee*
[('GC_1039', '(ee*complexi)
[('GC_28', '(cw*ee*
[('GC_10', '(ee__exp_
[('GC_3', '-(ee*complexi)'), ('GC_1003', '-(ee*complexi)')]
[('GC_1097', 'ytau'), ('GC_1096', '-ytau')]
[('GC_1067', '(ee__exp_
[('GC_29', 'ee__exp_
[('GC_HHHH', '-6*complexi*lam'), ('GC_1033', '-6*complexi*lam')]
[('GC_1054', '-ee__exp_
[('GC_1074', '-(ee__
[('R2GC_141_50', '-(complexi*
[('R2GC_137_43', '(complexi*
[('R2GC_137_44', '-(complexi*
[('R2GC_141_51', '(-7*complexi*
So we can
1) see how many different way a coupling can be different due to the sign
2) that model can have fully identical expression of coupling but different name (WHY?)
3) that the above method is actually not complete (it miss GC_UV couplings and GC_R2 identification)
4) sone coupling name are weird
Are we still using the hand written model?
Would not make sense to pass to FeynRules model (and to run the above script to manually optimise it?
Olivier
On 12 Jun 2018, at 22:45, Olivier Mattelaer <<email address hidden>
Mhh, It may be nice to cover K=-1 to...
Valentin Hirschi (valentin-hirschi) wrote : | # |
Hi Olivier,
On Wed, Jun 13, 2018 at 10:21 AM, Olivier Mattelaer <
<email address hidden>> wrote:
> I have run the following code on the loop_sm model.
> It basically strips all the + and - of any expression and identifies equal
> string.
> This is obviously not save but instructive of the issue to handle:
>
> #check opposite couplings
> for key in self.couplings:
> iden_list = collections.
> for C in self.couplings[
> #misc.sprint(
> expr = re.sub(
> iden_list[
> to_lookat = [ str([(c.
> for k in iden_list if len(iden_
> misc.sprint(
>
> I put below the result of the print statement. (and put in bold the false
> positif expression)
>
> DEBUG: '\n'.join(
> [('GC_1009', 'ee__exp_
> [('GC_1091', 'ym'), ('GC_1090', '-ym')]
> [('GC_1087', 'ye'), ('GC_1086', '-ye')]
> [('GC_21', '-(cw*ee*
> '(cw*ee*
> [('GC_1039', '(ee*complexi)
> '-(ee*complexi)
> [('GC_28', '(cw*ee*
> ('GC_1061', '-(cw*ee*
> [('GC_10', '(ee__exp_
> '(ee__exp_
> [('GC_3', '-(ee*complexi)'), ('GC_1003', '-(ee*complexi)')]
> [('GC_1097', 'ytau'), ('GC_1096', '-ytau')]
> [('GC_1067', '(ee__exp_
> '-(ee__
> [('GC_29', 'ee__exp_
> + (ee__exp_
> 'ee__exp_
> (ee__exp_
> [('GC_HHHH', '-6*complexi*lam'), ('GC_1033', '-6*complexi*lam')]
> [('GC_1054', '-ee__exp_
> [('GC_1074', '-(ee__
> '(ee__exp_
>
> [('R2GC_141_50', '-(complexi*
> ('R2GC_142_52', '(complexi*
> [('R2GC_137_43', '(complexi*
> ('R2GC_138_45', '-(complexi*
> [('R2GC_137_44', '-(complexi*
> ('R2GC_138_46', '(complexi*
> [('R2GC_141_51', '(-7*complexi*
> ('R2GC_142_53', '(7*complexi*
> [import_ufo.py at line 1643]
>
>
> So we can
> 1) see how many different way a coupling can be different due to the sign
>
As we discussed on Skype, it is probably a bit hard to do this with string
parsing. For example the ratio of this pair:
[('GC_28', '(cw*ee*
('GC_1061', '-(cw*ee*
is actually *not* -1.
I think here the simplest thing to do is t...
Rikkert Frederix (frederix) wrote : | # |
Guys,
Wouldn't it make more sense to check this numerically? I.e., assign some random numbers to all the terms, compute the ratio between all the couplings and repeat this a couple of times. If the ratio between couplings doesn't change up to machine precision for several choices of the random numbers consider them equal with the (numerical) proportionality factor given by the ratio?
Cheers,
Rik
Valentin Hirschi (valentin-hirschi) wrote : | # |
Hi Olivier,
Sure, the numerical approach is one possibility and we discussed it a bit
already in the previous emails of this thread.
We were then worried that we could hit false positive, and you are saying
that we could reduce this risk to an insignificant number by doing it
repeatedly with arbitrary assignment of the external parameters.
I suppose this could work indeed (I think it shouldn't be *too* hard to
implement, but Olivier should confirm).
Of course, when using a restriction file when loading the model, we should
only do this using the specified input parameters, as they may exhibit
extra simplifications that are ok to use, at least for K=1.
But then we could also combine this some other ratios detected with your
method Rik, as those would be safe to use anyway.
I don't think this is too crucial, so we should only go for simple
solutions if there are some, or none if too complicated.
Cheers
On Wed, Jun 13, 2018 at 2:26 PM, Rikkert Frederix <email address hidden>
wrote:
> Guys,
>
> Wouldn't it make more sense to check this numerically? I.e., assign some
> random numbers to all the terms, compute the ratio between all the
> couplings and repeat this a couple of times. If the ratio between couplings
> doesn't change up to machine precision for several choices of the random
> numbers consider them equal with the (numerical) proportionality factor
> given by the ratio?
>
> Cheers,
> Rik
>
> --
> https:/
> optimizenlomode
> You are reviewing the proposed merge of lp:~maddevelopers/mg5amcnlo/2.6.3_optimizenlomodel
> into lp:~mg5core2/mg5amcnlo/2.6.3.
>
--
Valentin
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi,
To merge this to 2.6.3, we have to keep such change minimal for the moment.
So I have had the bare minimum to the current status.
This is
a) detect fully identical expression --same string-- and merge them
b) remove couplings exactly equals to zero (no point to keep them obviously)
This is pretty minimal and quite save.
for loop_sm this does not do anything in the unitary gauge. (but make few simplification in the feynman gauge)
for the loop_qcd_qed_sm, they are 148 coupling equals to zero, so this makes some cool cleaning.
Now we can also not push this in 2.6.3 to be save. They are nothing crucial in such change and can easily wait months to be include.
Cheers,
Olivier
=== modified file 'models/
--- models/
+++ models/
@@ -14,7 +14,7 @@
######
""" How to import a UFO model to the MG5 format """
-
+import collections
import fractions
import logging
import os
@@ -530,8 +530,10 @@
- for interaction in self.interactions:
+ for interaction in list(self.
+ if not interaction[
+ self.interactio
@@ -584,6 +586,32 @@
def optimise_
+
+ # Check if two couplings have exactly the same definition.
+ # If so replace one by the other
+ if not hasattr(self, 'iden_couplings'):
+ coups = collections.
+ coups['
+ for coupling in self.ufomodel.
+ #if isinstance(
+ coups[str(
+
+ self.iden_couplings = {}
+ for idens in [c for c in coups.values() if len(c)>1]:
+ for i in range(1, len(idens)):
+ self.iden_
+
+ # apply the replacement by identical expression
+ for key, coup in list(interactio
+ if coup in self.iden_
+ interaction[
+ if interaction[
+ del interaction[
+
+
+
+
+
# we want to check if the same coupling is used for two lorentz strucutre
# for the same color structure.
to_lor = {}
@@ -1807,9 +1835,9 @@
# modify interaction to avoid to have identical coupling with different lorentz
- for interaction in self.get(
+ for interaction in list(self.
-
+
# deal with parameters
parameters = self.detect_
On 13 Jun 2018...
Valentin Hirschi (valentin-hirschi) wrote : | # |
Hi Olivier
On Wed, Jun 13, 2018 at 5:09 PM, Olivier Mattelaer <
<email address hidden>> wrote:
> Hi,
>
> To merge this to 2.6.3, we have to keep such change minimal for the moment.
>
> So I have had the bare minimum to the current status.
> This is
> a) detect fully identical expression --same string-- and merge them
> b) remove couplings exactly equals to zero (no point to keep them
> obviously)
>
> This is pretty minimal and quite save.
> for loop_sm this does not do anything in the unitary gauge. (but make few
> simplification in the feynman gauge)
> for the loop_qcd_qed_sm, they are 148 coupling equals to zero, so this
> makes some cool cleaning.
>
> Now we can also not push this in 2.6.3 to be save. They are nothing
> crucial in such change and can easily wait months to be include.
>
I would need this to be pushed in 2.6.3 for this model to work:
http://
So could you please put this in the 2.6.3 release ? (the model above in
principle only need the long name fix of course)
Cheers
>
> Cheers,
>
> Olivier
>
>
> === modified file 'models/
> --- models/
> +++ models/
> @@ -14,7 +14,7 @@
> #######
> #######
> """ How to import a UFO model to the MG5 format """
>
> -
> +import collections
> import fractions
> import logging
> import os
> @@ -530,8 +530,10 @@
> self.add_
>
>
> - for interaction in self.interactions:
> + for interaction in list(self.
> self.optimise_
> + if not interaction[
> + self.interactio
>
>
> self.model.
> @@ -584,6 +586,32 @@
>
> def optimise_
>
> +
> + # Check if two couplings have exactly the same definition.
> + # If so replace one by the other
> + if not hasattr(self, 'iden_couplings'):
> + coups = collections.
> + coups['
> + for coupling in self.ufomodel.
> + #if isinstance(
> + coups[str(
> +
> + self.iden_couplings = {}
> + for idens in [c for c in coups.values() if len(c)>1]:
> + for i in range(1, len(idens)):
> + self.iden_
> +
> + # apply the replacement by identical expression
> + for key, coup in list(interactio
> + if coup in self.iden_
> + interaction[
> + if interaction[
> + del interaction[
> +
> +
> +
> +
> +
> # we want to check if the same coupling is used for two lorentz
> strucutre
> # for the same color structure.
> to_lor = {}
> @@...
Olivier Mattelaer (olivier-mattelaer) wrote : | # |
Hi,
I do not understand your mail,
This has nothing to do with 2.6.3
http://
If you want me to add the model to the database this is done automatically for all model in the FR wiki.
So nothing to do here.
Cheers,
Olivier
On 13 Jun 2018, at 17:21, Valentin Hirschi <<email address hidden>
Hi Olivier
On Wed, Jun 13, 2018 at 5:09 PM, Olivier Mattelaer <
<email address hidden>
Hi,
To merge this to 2.6.3, we have to keep such change minimal for the moment.
So I have had the bare minimum to the current status.
This is
a) detect fully identical expression --same string-- and merge them
b) remove couplings exactly equals to zero (no point to keep them
obviously)
This is pretty minimal and quite save.
for loop_sm this does not do anything in the unitary gauge. (but make few
simplification in the feynman gauge)
for the loop_qcd_qed_sm, they are 148 coupling equals to zero, so this
makes some cool cleaning.
Now we can also not push this in 2.6.3 to be save. They are nothing
crucial in such change and can easily wait months to be include.
I would need this to be pushed in 2.6.3 for this model to work:
http://
So could you please put this in the 2.6.3 release ? (the model above in
principle only need the long name fix of course)
Cheers
Cheers,
Olivier
=== modified file 'models/
--- models/
+++ models/
@@ -14,7 +14,7 @@
#######
#######
""" How to import a UFO model to the MG5 format """
-
+import collections
import fractions
import logging
import os
@@ -530,8 +530,10 @@
- for interaction in self.interactions:
+ for interaction in list(self.
+ if not interaction[
+ self.interactio
@@ -584,6 +586,32 @@
def optimise_
+
+ # Check if two couplings have exactly the same definition.
+ # If so replace one by the other
+ if not hasattr(self, 'iden_couplings'):
+ coups = collections.
+ coups['
+ for coupling in self.ufomodel.
+ #if isinstance(
+ coups[str(
+
+ self.iden_couplings = {}
+ for idens in [c for c in coups.values() if len(c)>1]:
+ for i in range(1, len(idens)):
+ self.iden_
+
+ # apply the replacement by identical expression
+ for key, coup in list(interactio
+ if coup in self.iden_
+ interaction[
+ i...
Preview Diff
1 | === modified file 'UpdateNotes.txt' |
2 | --- UpdateNotes.txt 2018-05-08 20:37:57 +0000 |
3 | +++ UpdateNotes.txt 2018-06-02 22:01:27 +0000 |
4 | @@ -1,9 +1,19 @@ |
5 | Update notes for MadGraph5_aMC@NLO (in reverse time order) |
6 | |
7 | 2.6.3 () |
8 | + OM: When importing model, we now run one additional layer of optimisation: |
9 | + - if a vertex as two identical coupling for the same color structure then the associated lorentz |
10 | + structure are merged in a single one and the vertex is modified accordingly |
11 | + OM: When restricting a model, we also run one additional layer of optimisation |
12 | + - Opposite sign coupling are now identified and merged into a single one |
13 | + - if a vertex as two identical coupling (up to the sign) for the same color structure |
14 | + then the associated lorentz structure are merged in a single one and the |
15 | + vertex is modified accordingly |
16 | + VH+OM: changing the ALOHA naming scheme for combine routine when the function name starts to be too long. |
17 | OM: adding a hidden parameter to the run_card (python_seed) to allow to control the randon number |
18 | generated within python and be able to have full reproducibility of the events |
19 | - |
20 | + OM: Adding Qnumbers block for ghost (the latest version of py8 was crashing due to their absence) |
21 | + |
22 | 2.6.2 (29/04/18) |
23 | |
24 | Heavy ion pdf / pdf in general: |
25 | |
26 | === modified file 'aloha/aloha_writers.py' |
27 | --- aloha/aloha_writers.py 2018-04-11 15:28:05 +0000 |
28 | +++ aloha/aloha_writers.py 2018-06-02 22:01:27 +0000 |
29 | @@ -1177,7 +1177,7 @@ |
30 | |
31 | def get_routine_name(name=None, outgoing=None, tag=None, abstract=None): |
32 | """ build the name of the aloha function """ |
33 | - |
34 | + |
35 | assert (name and outgoing is not None) or abstract |
36 | |
37 | if tag is None: |
38 | @@ -1205,6 +1205,14 @@ |
39 | def combine_name(name, other_names, outgoing, tag=None, unknown_propa=False): |
40 | """ build the name for combined aloha function """ |
41 | |
42 | + def myHash(target_string): |
43 | + if len(target_string)<50: |
44 | + return target_string |
45 | + if '%(propa)s' in target_string: |
46 | + return 'ALOHA_'+(str(hash(target_string.lower()))).replace('-','m')+'%(propa)s' |
47 | + else: |
48 | + return 'ALOHA_'+(str(hash(target_string.lower()))).replace('-','m') |
49 | + |
50 | if tag and any(t.startswith('P') for t in tag[:-1]): |
51 | # propagator need to be the last entry for the tag |
52 | for i,t in enumerate(tag): |
53 | @@ -1238,9 +1246,11 @@ |
54 | if unknown_propa and outgoing: |
55 | routine += '%(propa)s' |
56 | if outgoing is not None: |
57 | - return routine +'_%s' % outgoing |
58 | + return myHash(routine)+'_%s' % outgoing |
59 | +# return routine +'_%s' % outgoing |
60 | else: |
61 | - return routine |
62 | + return myHash(routine) |
63 | +# return routine |
64 | |
65 | if tag is not None: |
66 | addon = ''.join(tag) |
67 | @@ -1257,10 +1267,15 @@ |
68 | if unknown_propa: |
69 | addon += '%(propa)s' |
70 | |
71 | +# if outgoing is not None: |
72 | +# return '_'.join((name,) + tuple(other_names)) + addon + '_%s' % outgoing |
73 | +# else: |
74 | +# return '_'.join((name,) + tuple(other_names)) + addon |
75 | + |
76 | if outgoing is not None: |
77 | - return '_'.join((name,) + tuple(other_names)) + addon + '_%s' % outgoing |
78 | + return myHash('_'.join((name,) + tuple(other_names))) + addon + '_%s' % outgoing |
79 | else: |
80 | - return '_'.join((name,) + tuple(other_names)) + addon |
81 | + return myHash('_'.join((name,) + tuple(other_names))) + addon |
82 | |
83 | class ALOHAWriterForCPP(WriteALOHA): |
84 | """Routines for writing out helicity amplitudes as C++ .h and .cc files.""" |
85 | @@ -1736,7 +1751,7 @@ |
86 | # added to another file |
87 | self.mode = 'no_include' |
88 | |
89 | - #name = combine_name(self.name, lor_names, offshell, self.tag) |
90 | + |
91 | |
92 | #h_text = self.write_combined_h(lor_names, offshell, **opt) |
93 | cc_text, h_text = StringIO() , StringIO() |
94 | |
95 | === modified file 'aloha/create_aloha.py' |
96 | --- aloha/create_aloha.py 2018-06-01 15:33:33 +0000 |
97 | +++ aloha/create_aloha.py 2018-06-02 22:01:27 +0000 |
98 | @@ -470,8 +470,8 @@ |
99 | propaR = deltaL('pr1',id) * deltaL('pr2', 'I2') * delta('pr2', spin_id) * delta('pr1', 'I3') |
100 | #numerator += "*deltaL('pr_1',id) * deltaL('pr_2', 'I2') * delta('pr_1', spin_id) * delta('pr_2', 'I3')" |
101 | elif spin == 5 : |
102 | - tag = {'1': _spin2_mult + id, '2': 2 * _spin2_mult + id, |
103 | - '51': 'I2', '52': 'I3', 'id':id} |
104 | + tag = {'1': _spin2_mult + id, '2': 'I2', |
105 | + '51': 2 * _spin2_mult + id, '52': 'I3', 'id':id} |
106 | |
107 | numerator = self.mod_propagator_expression(tag, numerator) |
108 | if denominator: |
109 | @@ -1240,7 +1240,6 @@ |
110 | |
111 | # avoid to add tag in global |
112 | old_tag = set(aloha_lib.KERNEL.use_tag) |
113 | - print 'create lib',tag |
114 | name, i = tag |
115 | if name == "Spin2Prop": |
116 | lib[('Spin2Prop',i)] = create( Spin2Propagator(_spin2_mult + i, \ |
117 | |
118 | === modified file 'madgraph/loop/loop_helas_objects.py' |
119 | --- madgraph/loop/loop_helas_objects.py 2017-07-13 10:33:37 +0000 |
120 | +++ madgraph/loop/loop_helas_objects.py 2018-06-02 22:01:27 +0000 |
121 | @@ -2316,8 +2316,7 @@ |
122 | already created and can be specified here instead of being generated. |
123 | This can make a difference for very complicated models.""" |
124 | |
125 | - |
126 | - if alohaModel is None: |
127 | + if not alohaModel:# is None: |
128 | # Generate it here |
129 | model = self.get('processes')[0].get('model') |
130 | myAlohaModel = create_aloha.AbstractALOHAModel(model.get('name')) |
131 | |
132 | === modified file 'madgraph/various/misc.py' |
133 | --- madgraph/various/misc.py 2018-06-01 12:14:52 +0000 |
134 | +++ madgraph/various/misc.py 2018-06-02 22:01:27 +0000 |
135 | @@ -1082,7 +1082,8 @@ |
136 | return self.path |
137 | |
138 | class TMP_variable(object): |
139 | - """create a temporary directory and ensure this one to be cleaned. |
140 | + """replace an attribute of a class with another value for the time of the |
141 | + context manager |
142 | """ |
143 | |
144 | def __init__(self, cls, attribute, value): |
145 | |
146 | === modified file 'mg5decay/decay_objects.py' |
147 | --- mg5decay/decay_objects.py 2017-07-04 09:24:42 +0000 |
148 | +++ mg5decay/decay_objects.py 2018-06-02 22:01:27 +0000 |
149 | @@ -4091,7 +4091,7 @@ |
150 | model.lorentz_dict = dict([(l.name, l) for l in model['lorentz']]) |
151 | self.init_regular_expression() |
152 | |
153 | - structure = model.lorentz_dict[vertex['lorentz'][key[1]]].structure |
154 | + structure = model.lorentz_dict[vertex['lorentz'][key[1]]].structure |
155 | new_structure = self.lor_pattern.sub(self.simplify_lorentz, |
156 | structure) |
157 | lor_value = eval(new_structure % q_dict_lor) |
158 | |
159 | === modified file 'models/import_ufo.py' |
160 | --- models/import_ufo.py 2018-03-10 22:48:36 +0000 |
161 | +++ models/import_ufo.py 2018-06-02 22:01:27 +0000 |
162 | @@ -497,7 +497,7 @@ |
163 | color_info = self.find_color_anti_color_rep() |
164 | |
165 | # load the lorentz structure. |
166 | - self.model.set('lorentz', self.ufomodel.all_lorentz) |
167 | + self.model.set('lorentz', list(self.ufomodel.all_lorentz)) |
168 | |
169 | # Substitute the expression of CT couplings which include CTparameters |
170 | # in their definition with the corresponding dictionaries, e.g. |
171 | @@ -529,6 +529,11 @@ |
172 | for interaction_info in self.ufomodel.all_CTvertices: |
173 | self.add_CTinteraction(interaction_info, color_info) |
174 | |
175 | + |
176 | + for interaction in self.interactions: |
177 | + self.optimise_interaction(interaction) |
178 | + |
179 | + |
180 | self.model.set('conserved_charge', self.conservecharge) |
181 | |
182 | # If we deal with a Loop model here, the order hierarchy MUST be |
183 | @@ -576,7 +581,102 @@ |
184 | del self.checked_lor |
185 | |
186 | return self.model |
187 | - |
188 | + |
189 | + def optimise_interaction(self, interaction): |
190 | + |
191 | + # we want to check if the same coupling is used for two lorentz strucutre |
192 | + # for the same color structure. |
193 | + to_lor = {} |
194 | + for (color, lor), coup in interaction['couplings'].items(): |
195 | + key = (color, coup) |
196 | + if key in to_lor: |
197 | + to_lor[key].append(lor) |
198 | + else: |
199 | + to_lor[key] = [lor] |
200 | + |
201 | + nb_reduce = [] |
202 | + optimize = False |
203 | + for key in to_lor: |
204 | + if len(to_lor[key]) >1: |
205 | + nb_reduce.append(len(to_lor[key])-1) |
206 | + optimize = True |
207 | + |
208 | + if not optimize: |
209 | + return |
210 | + |
211 | + if not hasattr(self, 'defined_lorentz_expr'): |
212 | + self.defined_lorentz_expr = {} |
213 | + self.lorentz_info = {} |
214 | + self.lorentz_combine = {} |
215 | + for lor in self.model['lorentz']: |
216 | + self.defined_lorentz_expr[lor.get('structure')] = lor.get('name') |
217 | + self.lorentz_info[lor.get('name')] = lor #(lor.get('structure'), lor.get('spins')) |
218 | + |
219 | + for key in to_lor: |
220 | + if len(to_lor[key]) == 1: |
221 | + continue |
222 | + names = [interaction['lorentz'][i] for i in to_lor[key]] |
223 | + names.sort() |
224 | + |
225 | + # get name of the new lorentz |
226 | + if tuple(names) in self.lorentz_combine: |
227 | + # already created new loretnz |
228 | + new_name = self.lorentz_combine[tuple(names)] |
229 | + else: |
230 | + new_name = self.add_merge_lorentz(names) |
231 | + |
232 | + # remove the old couplings |
233 | + color, coup = key |
234 | + to_remove = [(color, lor) for lor in to_lor[key]] |
235 | + for rm in to_remove: |
236 | + del interaction['couplings'][rm] |
237 | + |
238 | + #add the lorentz structure to the interaction |
239 | + if new_name not in [l for l in interaction.get('lorentz')]: |
240 | + interaction.get('lorentz').append(new_name) |
241 | + |
242 | + #find the associate index |
243 | + new_l = interaction.get('lorentz').index(new_name) |
244 | + # adding the new combination (color,lor) associate to this sum of structure |
245 | + interaction['couplings'][(color, new_l)] = coup |
246 | + |
247 | + |
248 | + def add_merge_lorentz(self, names): |
249 | + """add a lorentz structure which is the sume of the list given above""" |
250 | + |
251 | + |
252 | + #create new_name |
253 | + ii = len(names[0]) |
254 | + while ii>0: |
255 | + if not all(n.startswith(names[0][:ii]) for n in names[1:]): |
256 | + ii -=1 |
257 | + else: |
258 | + base_name = names[0][:ii] |
259 | + break |
260 | + else: |
261 | + base_name = 'LMER' |
262 | + |
263 | + i = 1 |
264 | + while '%s%s' %(base_name, i) in self.lorentz_info: |
265 | + i +=1 |
266 | + new_name = '%s%s' %(base_name, i) |
267 | + self.lorentz_combine[tuple(names)] = new_name |
268 | + assert new_name not in self.lorentz_info |
269 | + assert new_name not in [l.name for l in self.model['lorentz']] |
270 | + |
271 | + # load the associate lorentz expression |
272 | + new_struct = ' + '.join([self.lorentz_info[n].get('structure') for n in names]) |
273 | + spins = self.lorentz_info[names[0]].get('spins') |
274 | + new_lor = self.add_lorentz(new_name, spins, new_struct) |
275 | + self.lorentz_info[new_name] = new_lor |
276 | + |
277 | + return new_name |
278 | + |
279 | + # We also have to create the new lorentz |
280 | + |
281 | + |
282 | + |
283 | + |
284 | |
285 | def add_particle(self, particle_info): |
286 | """ convert and add a particle in the particle list """ |
287 | @@ -980,7 +1080,6 @@ |
288 | (intType if poleOrder==0 else (intType+str(poleOrder)+\ |
289 | 'eps')),loop_particles) |
290 | |
291 | - |
292 | def find_color_anti_color_rep(self, output=None): |
293 | """find which color are in the 3/3bar states""" |
294 | # method look at the 3 3bar 8 configuration. |
295 | @@ -1197,6 +1296,7 @@ |
296 | self.conservecharge.discard(charge) |
297 | |
298 | |
299 | + |
300 | def get_sign_flow(self, flow, nb_fermion): |
301 | """ensure that the flow of particles/lorentz are coherent with flow |
302 | and return a correct version if needed""" |
303 | @@ -1241,14 +1341,18 @@ |
304 | |
305 | def add_lorentz(self, name, spins , expr): |
306 | """ Add a Lorentz expression which is not present in the UFO """ |
307 | - |
308 | - new = self.model['lorentz'][0].__class__(name = name, |
309 | - spins = spins, |
310 | - structure = expr) |
311 | - |
312 | - self.model['lorentz'].append(new) |
313 | + |
314 | + assert name not in [l.name for l in self.model['lorentz']] |
315 | + with misc.TMP_variable(self.ufomodel.object_library, 'all_lorentz', |
316 | + self.model['lorentz']): |
317 | + new = self.model['lorentz'][0].__class__(name = name, |
318 | + spins = spins, |
319 | + structure = expr) |
320 | + assert name in [l.name for l in self.model['lorentz']] |
321 | + assert name not in [l.name for l in self.ufomodel.all_lorentz] |
322 | + #self.model['lorentz'].append(new) # already done by above command |
323 | self.model.create_lorentz_dict() |
324 | - return name |
325 | + return new |
326 | |
327 | _pat_T = re.compile(r'T\((?P<first>\d*),(?P<second>\d*)\)') |
328 | _pat_id = re.compile(r'Identity\((?P<first>\d*),(?P<second>\d*)\)') |
329 | @@ -1702,6 +1806,10 @@ |
330 | self.del_coup += zero_couplings |
331 | self.remove_couplings(self.del_coup) |
332 | |
333 | + # modify interaction to avoid to have identical coupling with different lorentz |
334 | + for interaction in self.get('interactions'): |
335 | + self.optimise_interaction(interaction) |
336 | + |
337 | # deal with parameters |
338 | parameters = self.detect_special_parameters() |
339 | self.fix_parameter_values(*parameters, simplify=rm_parameter, |
340 | @@ -1772,14 +1880,23 @@ |
341 | return self.detect_identical_couplings(strict_zero=True) |
342 | |
343 | |
344 | - if value in dict_value_coupling: |
345 | - iden_key.add(value) |
346 | - dict_value_coupling[value].append(name) |
347 | + if value in dict_value_coupling or -1*value in dict_value_coupling: |
348 | + if value in dict_value_coupling: |
349 | + iden_key.add(value) |
350 | + dict_value_coupling[value].append((name,1)) |
351 | + else: |
352 | + iden_key.add(-1*value) |
353 | + dict_value_coupling[-1*value].append((name,-1)) |
354 | else: |
355 | - dict_value_coupling[value] = [name] |
356 | - |
357 | + dict_value_coupling[value] = [(name,1)] |
358 | for key in iden_key: |
359 | - iden_coupling.append(dict_value_coupling[key]) |
360 | + tmp = [] |
361 | + if key in dict_value_coupling: |
362 | + tmp += dict_value_coupling[key] |
363 | + elif -1*key in dict_value_coupling: |
364 | + tmp += dict_value_coupling[-1*key] |
365 | + assert tmp |
366 | + iden_coupling.append(tmp) |
367 | |
368 | return zero_coupling, iden_coupling |
369 | |
370 | @@ -1898,17 +2015,52 @@ |
371 | return output |
372 | |
373 | |
374 | + @staticmethod |
375 | + def get_new_coupling_name(main, coupling, value, coeff): |
376 | + """ We have main == coeff * coupling |
377 | + coeff is only +1 or -1 |
378 | + main can be either GC_X or -GC_X |
379 | + coupling can be either GC_Y or -GC_Y |
380 | + value is either GC_Y or -GC_Y |
381 | + the return is either GC_X or -GC_X |
382 | + such that we have value == OUTPUT |
383 | + """ |
384 | + assert coeff in [-1,1] |
385 | + assert value == coupling or value == '-%s' % coupling or coupling == '-%s' % value |
386 | + assert isinstance(main, str) |
387 | + assert isinstance(coupling, str) |
388 | + assert isinstance(value, str) |
389 | + if coeff ==1: |
390 | + if value == coupling: |
391 | + return main # 4/4 |
392 | + else: |
393 | + if main.startswith('-'): |
394 | + return main[1:] # 2/2 |
395 | + else: |
396 | + return '-%s' % main # 2/2 |
397 | + else: |
398 | + if value == coupling: |
399 | + if main.startswith('-'): |
400 | + return main[1:] # 2/2 |
401 | + else: |
402 | + return '-%s' % main # 2/2 |
403 | + else: |
404 | + return main # 4/4 |
405 | + |
406 | + |
407 | def merge_iden_couplings(self, couplings): |
408 | """merge the identical couplings in the interactions and particle |
409 | counterterms""" |
410 | |
411 | |
412 | logger_mod.debug(' Fuse the Following coupling (they have the same value): %s '% \ |
413 | - ', '.join([obj for obj in couplings])) |
414 | + ', '.join([str(obj) for obj in couplings])) |
415 | + |
416 | + main = couplings[0][0] |
417 | + assert couplings[0][1] == 1 |
418 | + self.del_coup += [c[0] for c in couplings[1:]] # add the other coupl to the suppress list |
419 | |
420 | - main = couplings[0] |
421 | - self.del_coup += couplings[1:] # add the other coupl to the suppress list |
422 | - for coupling in couplings[1:]: |
423 | + for coupling, coeff in couplings[1:]: |
424 | # check if param is linked to an interaction |
425 | if coupling not in self.coupling_pos: |
426 | continue |
427 | @@ -1917,13 +2069,12 @@ |
428 | isinstance(vert, base_objects.Interaction)] |
429 | for vertex in vertices: |
430 | for key, value in vertex['couplings'].items(): |
431 | - if value == coupling: |
432 | - vertex['couplings'][key] = main |
433 | - elif value == '-%s' % coupling: |
434 | - if main.startswith('-'): |
435 | - vertex['couplings'][key] = main[1:] |
436 | - else: |
437 | - vertex['couplings'][key] = '-%s' % main |
438 | + if value == coupling or value == '-%s' % coupling or coupling == '-%s' % value: |
439 | + vertex['couplings'][key] = self.get_new_coupling_name(\ |
440 | + main, coupling, value, coeff) |
441 | + |
442 | + |
443 | + |
444 | |
445 | # replace the coupling appearing in the particle counterterm |
446 | particles_ct = [ pct for pct in self.coupling_pos[coupling] if |
447 | @@ -2183,11 +2334,109 @@ |
448 | data = self['parameters'][param_info[param]['dep']] |
449 | data.remove(param_info[param]['obj']) |
450 | |
451 | - |
452 | - |
453 | - |
454 | - |
455 | - |
456 | + def optimise_interaction(self, interaction): |
457 | + |
458 | + # we want to check if the same coupling (up to the sign) is used for two lorentz structure |
459 | + # for the same color structure. |
460 | + to_lor = {} |
461 | + for (color, lor), coup in interaction['couplings'].items(): |
462 | + abscoup, coeff = (coup[1:],-1) if coup.startswith('-') else (coup, 1) |
463 | + key = (color, abscoup) |
464 | + if key in to_lor: |
465 | + to_lor[key].append((lor,coeff)) |
466 | + else: |
467 | + to_lor[key] = [(lor,coeff)] |
468 | + |
469 | + nb_reduce = [] |
470 | + optimize = False |
471 | + for key in to_lor: |
472 | + if len(to_lor[key]) >1: |
473 | + nb_reduce.append(len(to_lor[key])-1) |
474 | + optimize = True |
475 | + |
476 | + if not optimize: |
477 | + return |
478 | + |
479 | + if not hasattr(self, 'defined_lorentz_expr'): |
480 | + self.defined_lorentz_expr = {} |
481 | + self.lorentz_info = {} |
482 | + self.lorentz_combine = {} |
483 | + for lor in self.get('lorentz'): |
484 | + self.defined_lorentz_expr[lor.get('structure')] = lor.get('name') |
485 | + self.lorentz_info[lor.get('name')] = lor #(lor.get('structure'), lor.get('spins')) |
486 | + |
487 | + for key in to_lor: |
488 | + if len(to_lor[key]) == 1: |
489 | + continue |
490 | + names = ['u%s' % interaction['lorentz'][i[0]] if i[1] ==1 else \ |
491 | + 'd%s' % interaction['lorentz'][i[0]] for i in to_lor[key]] |
492 | + |
493 | + names.sort() |
494 | + |
495 | + # get name of the new lorentz |
496 | + if tuple(names) in self.lorentz_combine: |
497 | + # already created new loretnz |
498 | + new_name = self.lorentz_combine[tuple(names)] |
499 | + else: |
500 | + new_name = self.add_merge_lorentz(names) |
501 | + |
502 | + # remove the old couplings |
503 | + color, coup = key |
504 | + to_remove = [(color, lor[0]) for lor in to_lor[key]] |
505 | + for rm in to_remove: |
506 | + del interaction['couplings'][rm] |
507 | + |
508 | + #add the lorentz structure to the interaction |
509 | + if new_name not in [l for l in interaction.get('lorentz')]: |
510 | + interaction.get('lorentz').append(new_name) |
511 | + |
512 | + #find the associate index |
513 | + new_l = interaction.get('lorentz').index(new_name) |
514 | + # adding the new combination (color,lor) associate to this sum of structure |
515 | + interaction['couplings'][(color, new_l)] = coup |
516 | + |
517 | + |
518 | + |
519 | + def add_merge_lorentz(self, names): |
520 | + """add a lorentz structure which is the sume of the list given above""" |
521 | + |
522 | + #create new_name |
523 | + ii = len(names[0]) |
524 | + while ii>1: |
525 | + #do not count the initial "u/d letter whcih indicates the sign" |
526 | + if not all(n[1:].startswith(names[0][1:ii]) for n in names[1:]): |
527 | + ii -=1 |
528 | + else: |
529 | + base_name = names[0][1:ii] |
530 | + break |
531 | + else: |
532 | + base_name = 'LMER' |
533 | + i = 1 |
534 | + while '%s%s' %(base_name, i) in self.lorentz_info: |
535 | + i +=1 |
536 | + new_name = '%s%s' %(base_name, i) |
537 | + self.lorentz_combine[tuple(names)] = new_name |
538 | + |
539 | + # load the associate lorentz expression |
540 | + new_struct = ' + '.join([self.lorentz_info[n[1:]].get('structure') for n in names if n.startswith('u')]) |
541 | + if any( n.startswith('d') for n in names ): |
542 | + new_struct += '-' + ' - '.join(['1.*(%s)' %self.lorentz_info[n[1:]].get('structure') for n in names if n.startswith('d')]) |
543 | + spins = self.lorentz_info[names[0][1:]].get('spins') |
544 | + new_lor = self.add_lorentz(new_name, spins, new_struct) |
545 | + self.lorentz_info[new_name] = new_lor |
546 | + |
547 | + return new_name |
548 | + |
549 | + def add_lorentz(self, name, spin, struct): |
550 | + """adding lorentz structure to the current model""" |
551 | + new = self['lorentz'][0].__class__(name = name, |
552 | + spins = spin, |
553 | + structure = struct) |
554 | + self['lorentz'].append(new) |
555 | + self.create_lorentz_dict() |
556 | + |
557 | + return None |
558 | + |
559 | |
560 | |
561 | |
562 | |
563 | === modified file 'tests/acceptance_tests/test_model_equivalence.py' |
564 | --- tests/acceptance_tests/test_model_equivalence.py 2016-09-06 15:01:18 +0000 |
565 | +++ tests/acceptance_tests/test_model_equivalence.py 2018-06-02 22:01:27 +0000 |
566 | @@ -347,6 +347,7 @@ |
567 | solutions = {'ymtau ': [1.7769999504089355], 'I4x33 ': [0.024123685681481218, 0.0], 'MTA ': [1.7769999504089355], 'GC_81 ': [0.0, 67.544], 'GC_5 ': [0.0, 0.094836], 'MZ ': [91.18800354003906], 'GC_27 ': [0.94484, 0.0], 'I1x33 ': [0.024123685681481218, 0.0], 'I3x33 ': [0.9448443987662922, 0.0], 'GC_95 ': [0.66811, 0.0], 'GC_60 ': [-0.37035, 0.0], 'ee__exp__2 ': [0.09483552005165403], 'aEWM1 ': [132.5070037841797], 'ytau ': [0.01020661671581679], 'GC_69 ': [-0.0, -190.38], 'GC_35 ': [-0.0, -0.42671], 'cw__exp__2 ': [0.7777535472599892], 'Gf ': [1.16639e-05], 'GC_59 ': [0.0, 0.08231], 'GC_21 ': [-0.94484, -0.0], 'ee ': [0.307953762847045], 'WZ ': [2.441404104232788], 'sw2 ': [0.22224645274001076], 'WT ': [1.5083359479904175], 'GC_80 ': [-0.0, -33.772], 'GC_57 ': [-0.0, -0.35482], 'sqrt__sw2 ': [0.4714302204356555], 'GC_67 ': [13.239, 0.0], 'GC_76 ': [-29.784, 0.0], 'GC_36 ': [0.0, 0.33188], 'GC_68 ': [-0.0, -63.46], 'GC_56 ': [0.10058, 0.0], 'sw__exp__2 ': [0.22224645274001076], 'GC_3 ': [-0.0, -0.30795], 'GC_54 ': [-0.10058, 0.0], 'WW ': [2.047600030899048], 'GC_70 ': [-26.266, 0.0], 'GC_66 ': [-13.239, 0.0], 'GC_38 ': [-0.0, -0.32662], 'GC_83 ': [-0.0, -0.017058], 'GC_77 ': [-16.545, 0.0], 'gw ': [0.653232969584471], 'MH ': [125.0], 'ymb ': [4.199999809265137], 'complexi ': [0.0, 1.0], 'GC_37 ': [-0.32662, 0.0], 'conjg__CKM1x1 ': [1.0], 'GC_2 ': [0.0, 0.2053], 'GC_51 ': [0.0, 0.28804], 'GC_71 ': [-0.0, -26.266], 'GC_39 ': [0.0, 0.32662], 'GC_82 ': [-0.017058, 0.0], 'GC_55 ': [-0.0, -0.10058], 'GC_78 ': [16.545, 0.0], 'GC_98 ': [-0.0072172, 0.0], 'GC_30 ': [-0.024124, -0.0], 'GC_15 ': [0.024124, 0.0], 'cw ': [0.881903366168873], 'yt ': [0.9448443987662922], 'sqrt__aEW ': [0.08687215260631942], 'vev ': [246.2184581018163], 'GC_79 ': [29.784, 0.0], 'GC_72 ': [0.0, 52.532], 'GC_1 ': [-0.0, -0.10265], 'conjg__CKM3x3 ': [1.0], 'GC_52 ': [-0.0, -0.57609], 'GC_100 ': [0.0, 0.46191], 'GC_65 ': [0.0, 0.27432], 'GC_12 ': [0.0, 1.4828], 'I2x33 ': [0.9448443987662922, 0.0], 'GC_94 ': [-0.0, -0.66811], 'sqrt__aS ': [0.3435112817874484], 'GC_31 ': [-0.0, -0.25774], 'aS ': [0.11800000071525575], 'MW__exp__2 ': [6467.21673128622], 'MZ__exp__4 ': [69143415.65084904], 'yb ': [0.024123685681481218], 'GC_99 ': [-0.0, -0.0072172], 'WH ': [0.006382339168339968], 'GC_96 ': [-0.010207, 0.0], 'MH__exp__2 ': [15625.0], 'GC_63 ': [0.0, 0.12671], 'GC_53 ': [0.0, 0.57609], 'GC_73 ': [26.266, 0.0], 'GC_64 ': [0.0, 0.084653], 'sw ': [0.4714302204356555], 'GC_9 ': [0.053768, 0.0], 'GC_32 ': [-0.0, -0.51548], 'muH ': [88.38834764831844], 'GC_7 ': [-0.053768, 0.0], 'aEW ': [0.0075467708984556505], 'vev__exp__2 ': [60623.52911003587], 'MZ__exp__2 ': [8315.251989618177], 'GC_97 ': [0.010207, 0.0], 'GC_62 ': [0.0, 0.37035], 'GC_74 ': [-24.765, 0.0], 'g1 ': [0.34919218438279087], 'GC_10 ': [-1.2177, 0.0], 'GC_8 ': [0.0, 0.053768], 'CKM3x3 ': [1.0], 'MW ': [80.41900727617956], 'MT ': [172.0], 'GC_33 ': [-0.0, -0.77321], 'GC_6 ': [0.0, 0.18967], 'GC_4 ': [0.0, 0.30795], 'MB ': [4.699999809265137], 'GC_61 ': [0.0, -0.20573], 'ymt ': [164.5], 'GC_75 ': [24.765, 0.0], 'G__exp__2 ': [1.4828317414825511], 'lam ': [0.1288691060169027], 'GC_50 ': [-0.0, -0.28804], 'GC_34 ': [0.0, 0.21336], 'GC_11 ': [0.0, 1.2177], 'sqrt__2 ': [1.4142135623730951], 'GC_58 ': [-0.0, -0.027437]} |
568 | #solutions = {'GC_5 ': [0.0, 0.094836], 'mdl_MW ': [80.41900727617956], 'mdl_yb ': [0.024123685681481218], 'mdl_sw__exp__2 ': [0.22224645274001076], 'mdl_conjg__CKM3x3 ': [1.0], 'GC_56 ': [0.10058, 0.0], 'mdl_MH ': [125.0], 'GC_95 ': [0.66811, 0.0], 'mdl_I4x33 ': [0.024123685681481218, 0.0], 'mdl_complexi ': [0.0, 1.0], 'aEWM1 ': [132.5070037841797], 'GC_69 ': [-0.0, -190.38], 'GC_35 ': [-0.0, -0.42671], 'mdl_Gf ': [1.16639e-05], 'mdl_gw ': [0.653232969584471], 'mdl_conjg__CKM1x1 ': [1.0], 'mdl_sqrt__aEW ': [0.08687215260631942], 'GC_59 ': [0.0, 0.08231], 'GC_21 ': [-0.94484, -0.0], 'GC_4 ': [0.0, 0.30795], 'mdl_cw ': [0.881903366168873], 'GC_80 ': [-0.0, -33.772], 'GC_64 ': [0.0, 0.084653], 'GC_57 ': [-0.0, -0.35482], 'GC_76 ': [-29.784, 0.0], 'GC_67 ': [13.239, 0.0], 'mdl_vev__exp__2 ': [60623.52911003587], 'mdl_I3x33 ': [0.9448443987662922, 0.0], 'GC_36 ': [0.0, 0.33188], 'mdl_I1x33 ': [0.024123685681481218, 0.0], 'GC_81 ': [0.0, 67.544], 'mdl_sw2 ': [0.22224645274001076], 'GC_68 ': [-0.0, -63.46], 'mdl_ytau ': [0.01020661671581679], 'GC_100 ': [0.0, 0.46191], 'GC_3 ': [-0.0, -0.30795], 'GC_54 ': [-0.10058, 0.0], 'GC_70 ': [-26.266, 0.0], 'GC_66 ': [-13.239, 0.0], 'GC_38 ': [-0.0, -0.32662], 'GC_83 ': [-0.0, -0.017058], 'GC_77 ': [-16.545, 0.0], 'GC_27 ': [0.94484, 0.0], 'GC_10 ': [-1.2177, 0.0], 'GC_37 ': [-0.32662, 0.0], 'GC_60 ': [-0.37035, 0.0], 'GC_2 ': [0.0, 0.2053], 'mdl_muH ': [88.38834764831844], 'mdl_MT ': [172.0], 'mdl_WH ': [0.006382339168339968], 'GC_51 ': [0.0, 0.28804], 'GC_71 ': [-0.0, -26.266], 'GC_39 ': [0.0, 0.32662], 'GC_82 ': [-0.017058, 0.0], 'mdl_sw ': [0.4714302204356555], 'GC_55 ': [-0.0, -0.10058], 'GC_61 ': [0.0, -0.20573], 'mdl_cw__exp__2 ': [0.7777535472599892], 'mdl_ymt ': [164.5], 'GC_78 ': [16.545, 0.0], 'mdl_CKM3x3 ': [1.0], 'GC_30 ': [-0.024124, -0.0], 'GC_15 ': [0.024124, 0.0], 'mdl_aEW ': [0.0075467708984556505], 'mdl_sqrt__sw2 ': [0.4714302204356555], 'mdl_I2x33 ': [0.9448443987662922, 0.0], 'GC_72 ': [0.0, 52.532], 'GC_1 ': [-0.0, -0.10265], 'GC_52 ': [-0.0, -0.57609], 'GC_65 ': [0.0, 0.27432], 'GC_12 ': [0.0, 1.4828], 'mdl_ymb ': [4.199999809265137], 'mdl_ee ': [0.307953762847045], 'GC_79 ': [29.784, 0.0], 'mdl_sqrt__2 ': [1.4142135623730951], 'GC_31 ': [-0.0, -0.25774], 'aS ': [0.11800000071525575], 'GC_99 ': [-0.0, -0.0072172], 'mdl_vev ': [246.2184581018163], 'GC_96 ': [-0.010207, 0.0], 'GC_63 ': [0.0, 0.12671], 'GC_53 ': [0.0, 0.57609], 'GC_73 ': [26.266, 0.0], 'mdl_MZ__exp__2 ': [8315.251989618177], 'mdl_WZ ': [2.441404104232788], 'GC_9 ': [0.053768, 0.0], 'mdl_g1 ': [0.34919218438279087], 'GC_32 ': [-0.0, -0.51548], 'mdl_G ': [1.2177157884673053], 'mdl_WT ': [1.5083359479904175], 'GC_7 ': [-0.053768, 0.0], 'mdl_G__exp__2 ': [1.4828317414825511], 'GC_97 ': [0.010207, 0.0], 'GC_62 ': [0.0, 0.37035], 'GC_74 ': [-24.765, 0.0], 'mdl_MZ ': [91.18800354003906], 'mdl_MZ__exp__4 ': [69143415.65084904], 'GC_8 ': [0.0, 0.053768], 'mdl_yt ': [0.9448443987662922], 'GC_98 ': [-0.0072172, 0.0], 'mdl_ee__exp__2 ': [0.09483552005165403], 'mdl_MB ': [4.699999809265137], 'GC_33 ': [-0.0, -0.77321], 'mdl_ymtau ': [1.7769999504089355], 'mdl_WW ': [2.047600030899048], 'GC_6 ': [0.0, 0.18967], 'mdl_MTA ': [1.7769999504089355], 'GC_75 ': [24.765, 0.0], 'GC_94 ': [-0.0, -0.66811], 'mdl_MW__exp__2 ': [6467.21673128622], 'mdl_MH__exp__2 ': [15625.0], 'GC_50 ': [-0.0, -0.28804], 'GC_34 ': [0.0, 0.21336], 'GC_11 ': [0.0, 1.2177], 'mdl_sqrt__aS ': [0.3435112817874484], 'GC_58 ': [-0.0, -0.027437], 'mdl_lam ': [0.1288691060169027]} |
569 | nb_value = 0 |
570 | + checked_solutions = solutions.keys() |
571 | for line in testprog.stdout: |
572 | self.assertTrue('Warning' not in line) |
573 | if '=' not in line: |
574 | @@ -356,6 +357,7 @@ |
575 | if variable.startswith('mdl_'): |
576 | variable = variable[4:] |
577 | |
578 | + checked_solutions.remove(variable) |
579 | if ',' in line: |
580 | value = eval(split[1]) |
581 | else: |
582 | @@ -375,8 +377,9 @@ |
583 | # solutions[variable] = [singlevalue] |
584 | # else: |
585 | # solutions[variable].append(singlevalue) |
586 | - |
587 | - self.assertEqual(nb_value, 116) |
588 | + self.assertEqual(nb_value, 116 - len(checked_solutions)) |
589 | + self.assertEqual(set(checked_solutions), set(['GC_%s ' % i for i in [27,67,54,38,78,15,52,79,96,73,9,74,4,50]])) |
590 | + |
591 | |
592 | |
593 | |
594 | |
595 | === modified file 'tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P0_wpwm_wpwm%matrix.f' |
596 | --- tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P0_wpwm_wpwm%matrix.f 2016-02-19 12:28:04 +0000 |
597 | +++ tests/input_files/IOTestsComparison/TestCmdMatchBox/MatchBoxOutput/%TEST%SubProcesses%P0_wpwm_wpwm%matrix.f 2018-06-02 22:01:27 +0000 |
598 | @@ -198,18 +198,18 @@ |
599 | CALL VXXXXX(P(0,4),MDL_MW,NHEL(4),+1*IC(4),W(1,4)) |
600 | C Amplitude(s) for diagram number 1 |
601 | CALL VVVV2_0(W(1,1),W(1,4),W(1,2),W(1,3),GC_35,AMP(1)) |
602 | - CALL VVV1P0_1(W(1,1),W(1,2),GC_4,ZERO,ZERO,W(1,5)) |
603 | + CALL VVV1P0_1(W(1,1),W(1,2),-GC_3,ZERO,ZERO,W(1,5)) |
604 | C Amplitude(s) for diagram number 2 |
605 | - CALL VVV1_0(W(1,5),W(1,4),W(1,3),GC_4,AMP(2)) |
606 | + CALL VVV1_0(W(1,5),W(1,4),W(1,3),-GC_3,AMP(2)) |
607 | CALL VVS1_3(W(1,1),W(1,2),GC_72,MDL_MH,MDL_WH,W(1,5)) |
608 | C Amplitude(s) for diagram number 3 |
609 | CALL VVS1_0(W(1,4),W(1,3),W(1,5),GC_72,AMP(3)) |
610 | CALL VVV1_3(W(1,1),W(1,2),GC_53,MDL_MZ,MDL_WZ,W(1,5)) |
611 | C Amplitude(s) for diagram number 4 |
612 | CALL VVV1_0(W(1,4),W(1,3),W(1,5),GC_53,AMP(4)) |
613 | - CALL VVV1P0_1(W(1,1),W(1,3),GC_4,ZERO,ZERO,W(1,5)) |
614 | + CALL VVV1P0_1(W(1,1),W(1,3),-GC_3,ZERO,ZERO,W(1,5)) |
615 | C Amplitude(s) for diagram number 5 |
616 | - CALL VVV1_0(W(1,5),W(1,4),W(1,2),GC_4,AMP(5)) |
617 | + CALL VVV1_0(W(1,5),W(1,4),W(1,2),-GC_3,AMP(5)) |
618 | CALL VVS1_3(W(1,1),W(1,3),GC_72,MDL_MH,MDL_WH,W(1,5)) |
619 | C Amplitude(s) for diagram number 6 |
620 | CALL VVS1_0(W(1,4),W(1,2),W(1,5),GC_72,AMP(6)) |
621 | @@ -305,18 +305,18 @@ |
622 | CALL VXXXXX(P(0,4),MDL_MW,NHEL(4),+1*IC(4),W(1,4)) |
623 | C Amplitude(s) for diagram number 1 |
624 | CALL VVVV2_0(W(1,1),W(1,4),W(1,2),W(1,3),GC_35,AMP(1)) |
625 | - CALL VVV1P0_1(W(1,1),W(1,2),GC_4,ZERO,ZERO,W(1,5)) |
626 | + CALL VVV1P0_1(W(1,1),W(1,2),-GC_3,ZERO,ZERO,W(1,5)) |
627 | C Amplitude(s) for diagram number 2 |
628 | - CALL VVV1_0(W(1,5),W(1,4),W(1,3),GC_4,AMP(2)) |
629 | + CALL VVV1_0(W(1,5),W(1,4),W(1,3),-GC_3,AMP(2)) |
630 | CALL VVS1_3(W(1,1),W(1,2),GC_72,MDL_MH,MDL_WH,W(1,5)) |
631 | C Amplitude(s) for diagram number 3 |
632 | CALL VVS1_0(W(1,4),W(1,3),W(1,5),GC_72,AMP(3)) |
633 | CALL VVV1_3(W(1,1),W(1,2),GC_53,MDL_MZ,MDL_WZ,W(1,5)) |
634 | C Amplitude(s) for diagram number 4 |
635 | CALL VVV1_0(W(1,4),W(1,3),W(1,5),GC_53,AMP(4)) |
636 | - CALL VVV1P0_1(W(1,1),W(1,3),GC_4,ZERO,ZERO,W(1,5)) |
637 | + CALL VVV1P0_1(W(1,1),W(1,3),-GC_3,ZERO,ZERO,W(1,5)) |
638 | C Amplitude(s) for diagram number 5 |
639 | - CALL VVV1_0(W(1,5),W(1,4),W(1,2),GC_4,AMP(5)) |
640 | + CALL VVV1_0(W(1,5),W(1,4),W(1,2),-GC_3,AMP(5)) |
641 | CALL VVS1_3(W(1,1),W(1,3),GC_72,MDL_MH,MDL_WH,W(1,5)) |
642 | C Amplitude(s) for diagram number 6 |
643 | CALL VVS1_0(W(1,4),W(1,2),W(1,5),GC_72,AMP(6)) |
644 | |
645 | === modified file 'tests/parallel_tests/test_ML5.py' |
646 | --- tests/parallel_tests/test_ML5.py 2016-05-25 22:03:40 +0000 |
647 | +++ tests/parallel_tests/test_ML5.py 2018-06-02 22:01:27 +0000 |
648 | @@ -463,7 +463,7 @@ |
649 | # MadLoop goes to quadruple precision. The agreement is then fine (10e-14!) |
650 | # but it takes several hours for the non-optimized evaluation. So better skip |
651 | # it unless you explicitly want to try out quad prec behaviors. |
652 | - def notest_long_sm_vs_stored_ML5_gg_ggg(self): |
653 | + def test_long_sm_vs_stored_ML5_gg_ggg(self): |
654 | proc = "gg_ggg" |
655 | self.compare_processes([ML5_processes_long_dic[proc]], |
656 | model = self.test_model_name, pickle_file = 'ml5_sm_%s.pkl'%proc, |
657 | |
658 | === modified file 'tests/parallel_tests/test_ML5MSSMQCD.py' |
659 | --- tests/parallel_tests/test_ML5MSSMQCD.py 2016-07-02 20:34:59 +0000 |
660 | +++ tests/parallel_tests/test_ML5MSSMQCD.py 2018-06-02 22:01:27 +0000 |
661 | @@ -108,7 +108,7 @@ |
662 | filename = 'ptest_long_mssm_vs_HCR_%s'%proc, chosen_runner = 'HCR') |
663 | |
664 | # ('g g > go go',{'QCD':2,'QED':0},['QCD'],{'QCD':6,'QED':0}) |
665 | - def test_long_mssm_vs_stored_HCR_gg_gogo_QCD(self): |
666 | + def test_short_mssm_vs_stored_HCR_gg_gogo_QCD(self): |
667 | proc = 'gg_gogo_mssm_QCD' |
668 | compare_processes(self,[HCR_processes_long_dic[proc]], |
669 | model = "loop_MSSM-parallel_test_gogo", |
670 | |
671 | === modified file 'tests/parallel_tests/test_aloha.py' |
672 | --- tests/parallel_tests/test_aloha.py 2017-12-09 21:34:23 +0000 |
673 | +++ tests/parallel_tests/test_aloha.py 2018-06-02 22:01:27 +0000 |
674 | @@ -21,6 +21,7 @@ |
675 | import time |
676 | import tempfile as tempfile |
677 | from functools import wraps |
678 | +from collections import namedtuple |
679 | |
680 | import aloha |
681 | import aloha.aloha_object as aloha_obj |
682 | @@ -3121,7 +3122,7 @@ |
683 | helas_suite.look_for_multiple_lorentz_interactions() |
684 | solution = {'FFV2': [('FFV3',), ('FFV4',), ('FFV5',)], 'FFS1': [('FFS3',)]} |
685 | self.assertEqual(solution, helas_suite.multiple_lor) |
686 | - |
687 | + |
688 | |
689 | def test_short_aloha_multiple_lorentz_and_symmetry(self): |
690 | """ check if the detection of multiple lorentz work """ |
691 | @@ -3466,6 +3467,7 @@ |
692 | self.assertEqual(amp.name, conjg_amp.name) |
693 | self.assertEqual(amp.tag + ['C1'], conjg_amp.tag) |
694 | |
695 | + |
696 | def test_short_aloha_expr_FFFF3(self): |
697 | """Test analytical expression for four fermion (provide by Tim M). |
698 | it's particularity is about to have contraction A and 4*A """ |
699 | @@ -3498,6 +3500,7 @@ |
700 | solution = [(-518016-1383424j), (317568-1604608j), (162600-4898488j), (-31800-8538056j)] |
701 | for out,sol in zip(ufo_value,solution): |
702 | self.assertAlmostEqual(out, sol) |
703 | + |
704 | |
705 | def test_short_aloha_expr_VVS1(self): |
706 | """Test analytical expression for VVS from SILH. |
707 | @@ -3668,7 +3671,170 @@ |
708 | class TestAlohaWriter(unittest.TestCase): |
709 | """ simple unittest of the writer more test are in test_export_v4 |
710 | and test_export_pythia""" |
711 | - |
712 | + |
713 | + @set_global() |
714 | + def test_get_custom_propa(self): |
715 | + |
716 | + FFVV = UFOLorentz(name = 'FFVV', |
717 | + spins = [ 2, 2, 3, 3]) |
718 | + |
719 | + abstract = AbstractRoutineBuilder(FFVV) |
720 | + Propagator = namedtuple('Propagator', ('name', 'numerator', 'denominator')) |
721 | + modelclass = namedtuple('modelclass', ('propagators')) |
722 | + propa = namedtuple('propa', ('mypropa')) |
723 | + |
724 | + #start by the scalar case |
725 | + S = Propagator(name = "S", |
726 | + numerator = "complex(0,1)", |
727 | + denominator = "P('mu', id) * P('mu', id) - Mass(id) * Mass(id) + complex(0,1) * Mass(id) * Width(id)" |
728 | + ) |
729 | + |
730 | + abstract.model= modelclass(propagators=propa(mypropa=S)) |
731 | + out = abstract.get_custom_propa('mypropa', 1, 1) |
732 | + # check numerator/denominator |
733 | + self.assertEqual(str(out), '1j') |
734 | + self.assertEqual(str(abstract.denominator), '( (TMP0) + (-1 * M1 * M1) + (1j * M1 * W1) )') |
735 | + |
736 | + # check simple modification of the propagators |
737 | + S = Propagator(name = "S", |
738 | + numerator = "P('mu',id) **2", |
739 | + denominator = "Mass(id) * Mass(id)" |
740 | + ) |
741 | + |
742 | + abstract = AbstractRoutineBuilder(FFVV) |
743 | + abstract.model= modelclass(propagators=propa(mypropa=S)) |
744 | + out = abstract.get_custom_propa('mypropa', 1, 2) |
745 | + # check numerator/denominator |
746 | + self.assertEqual(str(out), '(_P^2_mu * _P^2_mu)') |
747 | + self.assertEqual(str(abstract.denominator), '(M2 * M2)') |
748 | + |
749 | + # check simple modification of the propagators |
750 | + F = Propagator(name = "F", |
751 | + numerator = "P('mu', id)* Gamma('mu',1,2)", |
752 | + denominator = "Mass(id) * Mass(id)" |
753 | + ) |
754 | + |
755 | + abstract = AbstractRoutineBuilder(FFVV) |
756 | + abstract.model= modelclass(propagators=propa(mypropa=F)) |
757 | + out = abstract.get_custom_propa('mypropa', 2, 2) |
758 | + # check numerator/denominator |
759 | + self.assertEqual(str(out), '(_P^2_mu * Gamma^mu_I2_2)') |
760 | + self.assertEqual(type(out), aloha.aloha_lib.MultLorentz ) |
761 | + out = out.expand() |
762 | + self.assertEqual(type(out), aloha.aloha_lib.LorentzObjectRepresentation ) |
763 | + self.assertEqual(out.nb_lor, 0) |
764 | + self.assertEqual(out.nb_spin, 2) |
765 | + self.assertEqual(str(abstract.denominator), '(M2 * M2)') |
766 | + |
767 | + # check propa with conjugate routine |
768 | + F = Propagator(name = "F", |
769 | + numerator = "P('mu', id)* Gamma('mu',1,2)", |
770 | + denominator = "Mass(id) * Mass(id)" |
771 | + ) |
772 | + |
773 | + abstract = AbstractRoutineBuilder(FFVV) |
774 | + abstract = abstract.define_conjugate_builder(1) |
775 | + abstract.model= modelclass(propagators=propa(mypropa=F)) |
776 | + out = abstract.get_custom_propa('mypropa', 2, 2) |
777 | + # check numerator/denominator |
778 | + self.assertEqual(str(out), '(-1 * _P^2_mu * Gamma^mu_51_I2)') |
779 | + # the next line does not check the propagator in itself but show the consistency |
780 | + # of the 51 index. |
781 | + self.assertEqual(str(abstract.lorentz_expr), '(1) * C(51,2) * C(52,1)') |
782 | + self.assertEqual(type(out), aloha.aloha_lib.MultLorentz ) |
783 | + out = out.expand() |
784 | + self.assertEqual(type(out), aloha.aloha_lib.LorentzObjectRepresentation ) |
785 | + self.assertEqual(out.nb_lor, 0) |
786 | + self.assertEqual(out.nb_spin, 2) |
787 | + self.assertEqual(out.spin_ind, [51, 'I2']) |
788 | + |
789 | + |
790 | + # check simple modification of the propagators for Vector |
791 | + V = Propagator(name = "V", |
792 | + numerator = "P(1, id)* P(2, id) * FCT(P('mu', id)* P('mu', id))", |
793 | + denominator = "Mass(id) * Mass(id)" |
794 | + ) |
795 | + |
796 | + abstract = AbstractRoutineBuilder(FFVV) |
797 | + abstract.model= modelclass(propagators=propa(mypropa=V)) |
798 | + out = abstract.get_custom_propa('mypropa', 3, 3) |
799 | + # check numerator/denominator |
800 | + self.assertEqual(str(out), '(_P^3_3 * _P^3_I2 * _FCT0)') |
801 | + self.assertEqual(type(out), aloha.aloha_lib.MultLorentz ) |
802 | + out = out.expand() |
803 | + self.assertEqual(type(out), aloha.aloha_lib.LorentzObjectRepresentation ) |
804 | + self.assertEqual(out.nb_lor, 2) |
805 | + self.assertEqual(out.nb_spin, 0) |
806 | + self.assertEqual(out.lorentz_ind, ['I2',3]) |
807 | + self.assertEqual(str(abstract.denominator), '(M3 * M3)') |
808 | + |
809 | + # check simple modification of the spin3/2 propagators |
810 | + R = Propagator(name = "R", |
811 | + numerator = "P(1, id)* Gamma(2,1,2)", |
812 | + denominator = "Mass(id) * Mass(id)" |
813 | + ) |
814 | + |
815 | + abstract = AbstractRoutineBuilder(FFVV) |
816 | + abstract.model= modelclass(propagators=propa(mypropa=R)) |
817 | + out = abstract.get_custom_propa('mypropa', 4, 1) |
818 | + # check numerator/denominator |
819 | + self.assertEqual(str(out), '(-1 * _P^1_pr1 * Gamma^pr2_pr1_pr2 * IdL_pr1_1 * IdL_pr2_I2 * Id_pr1_1 * Id_pr2_I3)') |
820 | + self.assertEqual(type(out), aloha.aloha_lib.MultLorentz ) |
821 | + out = out.expand() |
822 | + self.assertEqual(type(out), aloha.aloha_lib.LorentzObjectRepresentation ) |
823 | + self.assertEqual(out.nb_lor, 2) |
824 | + self.assertEqual(out.nb_spin, 2) |
825 | + self.assertEqual(out.lorentz_ind, [1, 'I2']) |
826 | + self.assertEqual(out.spin_ind, ['I3', 1]) |
827 | + self.assertEqual(str(abstract.denominator), '(M1 * M1)') |
828 | + |
829 | + |
830 | + |
831 | + # check simple modification of the spin3/2 propagators |
832 | + R = Propagator(name = "R", |
833 | + numerator = "P(1, id)* Gamma(2,1,2)", |
834 | + denominator = "Mass(id) * Mass(id)" |
835 | + ) |
836 | + |
837 | + abstract = AbstractRoutineBuilder(FFVV) |
838 | + abstract.model= modelclass(propagators=propa(mypropa=R)) |
839 | + abstract = abstract.define_conjugate_builder(1) |
840 | + out = abstract.get_custom_propa('mypropa', 4, 1) |
841 | + # check numerator/denominator |
842 | + self.assertEqual(str(out), '(_P^1_pr1 * Gamma^pr2_pr1_pr2 * IdL_pr1_1 * IdL_pr2_I2 * Id_pr2_52 * Id_pr1_I3)') |
843 | + |
844 | + self.assertEqual(type(out), aloha.aloha_lib.MultLorentz ) |
845 | + out = out.expand() |
846 | + self.assertEqual(type(out), aloha.aloha_lib.LorentzObjectRepresentation ) |
847 | + self.assertEqual(out.nb_lor, 2) |
848 | + self.assertEqual(out.nb_spin, 2) |
849 | + self.assertEqual(out.lorentz_ind, [1, 'I2']) |
850 | + self.assertEqual(out.spin_ind, ['I3', 52]) |
851 | + self.assertEqual(str(abstract.denominator), '(M1 * M1)') |
852 | + |
853 | + |
854 | + # check simple modification of the propagators for Vector |
855 | + S2 = Propagator(name = "S2", |
856 | + numerator = "P(1, id)* P(2, id) * FCT(P('mu', id)* P('mu', id)) * Metric(51,52)", |
857 | + denominator = "Mass(id) * Mass(id)" |
858 | + ) |
859 | + |
860 | + abstract = AbstractRoutineBuilder(FFVV) |
861 | + abstract.model= modelclass(propagators=propa(mypropa=S2)) |
862 | + out = abstract.get_custom_propa('mypropa', 5, 3) |
863 | + # check numerator/denominator |
864 | + self.assertEqual(str(out), '(_P^3_1003 * _P^3_I2 * _FCT0 * _ETA_2003_I3)') |
865 | + self.assertEqual(type(out), aloha.aloha_lib.MultLorentz ) |
866 | + out = out.expand() |
867 | + self.assertEqual(type(out), aloha.aloha_lib.LorentzObjectRepresentation ) |
868 | + self.assertEqual(out.nb_lor, 4) |
869 | + self.assertEqual(out.nb_spin, 0) |
870 | + self.assertEqual(out.lorentz_ind, ['I2', 1003, 2003, 'I3']) |
871 | + self.assertEqual(str(abstract.denominator), '(M3 * M3)') |
872 | + |
873 | + |
874 | + |
875 | + |
876 | def old_test_reorder_call_listFFVV(self): |
877 | |
878 | FFVV = UFOLorentz(name = 'FFVV', |
879 | |
880 | === modified file 'tests/unit_tests/iolibs/test_export_v4.py' |
881 | --- tests/unit_tests/iolibs/test_export_v4.py 2018-04-23 20:23:22 +0000 |
882 | +++ tests/unit_tests/iolibs/test_export_v4.py 2018-06-02 22:01:27 +0000 |
883 | @@ -9832,7 +9832,7 @@ |
884 | |
885 | # couplings |
886 | self.assertEqual(len(mg4_model.coups_dep), 3) |
887 | - sol = ['GC_1', 'GC_2', 'GC_3', 'GC_4', 'GC_5', 'GC_6', 'GC_7', 'GC_8', 'GC_9', 'GC_15', 'GC_21', 'GC_27', 'GC_30', 'GC_31', 'GC_32', 'GC_33', 'GC_34', 'GC_35', 'GC_36', 'GC_37', 'GC_38', 'GC_39', 'GC_50', 'GC_51', 'GC_52', 'GC_53', 'GC_54', 'GC_55', 'GC_56', 'GC_57', 'GC_58', 'GC_59', 'GC_60', 'GC_61', 'GC_62', 'GC_63', 'GC_64', 'GC_65', 'GC_66', 'GC_67', 'GC_68', 'GC_69', 'GC_70', 'GC_71', 'GC_72', 'GC_73', 'GC_74', 'GC_75', 'GC_76', 'GC_77', 'GC_78', 'GC_79', 'GC_80', 'GC_81', 'GC_82', 'GC_83', 'GC_94', 'GC_95', 'GC_96', 'GC_97', 'GC_98', 'GC_99', 'GC_100'] |
888 | + sol = ['GC_1', 'GC_2', 'GC_3', 'GC_5', 'GC_6', 'GC_7', 'GC_8', 'GC_21', 'GC_30', 'GC_31', 'GC_32', 'GC_33', 'GC_34', 'GC_35', 'GC_36', 'GC_37', 'GC_39', 'GC_51', 'GC_53', 'GC_55', 'GC_56', 'GC_57', 'GC_58', 'GC_59', 'GC_60', 'GC_61', 'GC_62', 'GC_63', 'GC_64', 'GC_65', 'GC_66', 'GC_68', 'GC_69', 'GC_70', 'GC_71', 'GC_72', 'GC_75', 'GC_76', 'GC_77', 'GC_80', 'GC_81', 'GC_82', 'GC_83', 'GC_94', 'GC_95', 'GC_97', 'GC_98', 'GC_99', 'GC_100'] |
889 | |
890 | self.assertEqual(sol, [ p.name for p in mg4_model.coups_indep]) |
891 | |
892 | |
893 | === modified file 'tests/unit_tests/iolibs/test_helas_call_writers.py' |
894 | --- tests/unit_tests/iolibs/test_helas_call_writers.py 2015-10-01 16:00:08 +0000 |
895 | +++ tests/unit_tests/iolibs/test_helas_call_writers.py 2018-06-02 22:01:27 +0000 |
896 | @@ -996,40 +996,40 @@ |
897 | CALL VXXXXX(P(0,3),ZERO,NHEL(3),+1*IC(3),W(1,3)) |
898 | CALL VXXXXX(P(0,4),mdl_MW,NHEL(4),+1*IC(4),W(1,4)) |
899 | CALL VXXXXX(P(0,5),mdl_MZ,NHEL(5),+1*IC(5),W(1,5)) |
900 | -CALL VVV1_3(W(1,1),W(1,2),GC_4,DCMPLX(CMASS_mdl_MW),W(1,6)) |
901 | -CALL VVV1_2(W(1,3),W(1,4),GC_4,DCMPLX(CMASS_mdl_MW),W(1,7)) |
902 | +CALL VVV1_3(W(1,1),W(1,2),-GC_3,DCMPLX(CMASS_mdl_MW),W(1,6)) |
903 | +CALL VVV1_2(W(1,3),W(1,4),-GC_3,DCMPLX(CMASS_mdl_MW),W(1,7)) |
904 | # Amplitude(s) for diagram number 1 |
905 | CALL VVV1_0(W(1,6),W(1,7),W(1,5),GC_53,AMP(1)) |
906 | CALL VVV1_1(W(1,4),W(1,5),GC_53,DCMPLX(CMASS_mdl_MW),W(1,8)) |
907 | # Amplitude(s) for diagram number 2 |
908 | -CALL VVV1_0(W(1,3),W(1,6),W(1,8),GC_4,AMP(2)) |
909 | +CALL VVV1_0(W(1,3),W(1,6),W(1,8),-GC_3,AMP(2)) |
910 | # Amplitude(s) for diagram number 3 |
911 | CALL VVVV5_0(W(1,3),W(1,6),W(1,4),W(1,5),GC_57,AMP(3)) |
912 | -CALL VVV1_2(W(1,1),W(1,4),GC_4,DCMPLX(CMASS_mdl_MW),W(1,6)) |
913 | -CALL VVV1_3(W(1,3),W(1,2),GC_4,DCMPLX(CMASS_mdl_MW),W(1,9)) |
914 | +CALL VVV1_2(W(1,1),W(1,4),-GC_3,DCMPLX(CMASS_mdl_MW),W(1,6)) |
915 | +CALL VVV1_3(W(1,3),W(1,2),-GC_3,DCMPLX(CMASS_mdl_MW),W(1,9)) |
916 | # Amplitude(s) for diagram number 4 |
917 | CALL VVV1_0(W(1,9),W(1,6),W(1,5),GC_53,AMP(4)) |
918 | CALL VVV1_2(W(1,2),W(1,5),GC_53,DCMPLX(CMASS_mdl_MW),W(1,10)) |
919 | # Amplitude(s) for diagram number 5 |
920 | -CALL VVV1_0(W(1,3),W(1,10),W(1,6),GC_4,AMP(5)) |
921 | +CALL VVV1_0(W(1,3),W(1,10),W(1,6),-GC_3,AMP(5)) |
922 | # Amplitude(s) for diagram number 6 |
923 | CALL VVVV5_0(W(1,3),W(1,2),W(1,6),W(1,5),GC_57,AMP(6)) |
924 | # Amplitude(s) for diagram number 7 |
925 | -CALL VVV1_0(W(1,1),W(1,9),W(1,8),GC_4,AMP(7)) |
926 | +CALL VVV1_0(W(1,1),W(1,9),W(1,8),-GC_3,AMP(7)) |
927 | # Amplitude(s) for diagram number 8 |
928 | -CALL VVV1_0(W(1,1),W(1,10),W(1,7),GC_4,AMP(8)) |
929 | +CALL VVV1_0(W(1,1),W(1,10),W(1,7),-GC_3,AMP(8)) |
930 | CALL VVVV2_4(W(1,1),W(1,3),W(1,2),GC_5,DCMPLX(CMASS_mdl_MW),W(1,10)) |
931 | # Amplitude(s) for diagram number 9 |
932 | CALL VVV1_0(W(1,10),W(1,4),W(1,5),GC_53,AMP(9)) |
933 | CALL VVVV5_3(W(1,1),W(1,2),W(1,5),GC_57,DCMPLX(CMASS_mdl_MW),W(1,10)) |
934 | # Amplitude(s) for diagram number 10 |
935 | -CALL VVV1_0(W(1,3),W(1,10),W(1,4),GC_4,AMP(10)) |
936 | +CALL VVV1_0(W(1,3),W(1,10),W(1,4),-GC_3,AMP(10)) |
937 | CALL VVVV2_3(W(1,1),W(1,3),W(1,4),GC_5,DCMPLX(CMASS_mdl_MW),W(1,10)) |
938 | # Amplitude(s) for diagram number 11 |
939 | CALL VVV1_0(W(1,2),W(1,10),W(1,5),GC_53,AMP(11)) |
940 | CALL VVVV5_2(W(1,1),W(1,4),W(1,5),GC_57,DCMPLX(CMASS_mdl_MW),W(1,10)) |
941 | # Amplitude(s) for diagram number 12 |
942 | -CALL VVV1_0(W(1,3),W(1,2),W(1,10),GC_4,AMP(12))""" |
943 | +CALL VVV1_0(W(1,3),W(1,2),W(1,10),-GC_3,AMP(12))""" |
944 | |
945 | self.assertEqual(solution.split('\n'), result) |
946 | |
947 | @@ -1047,40 +1047,40 @@ |
948 | vxxxxx(p[perm[2]],mME[2],hel[2],+1,w[2]); |
949 | vxxxxx(p[perm[3]],mME[3],hel[3],+1,w[3]); |
950 | vxxxxx(p[perm[4]],mME[4],hel[4],+1,w[4]); |
951 | -VVV1_3(w[0],w[1],pars->GC_4,pars->CMASS_mdl_MW,w[5]); |
952 | -VVV1_2(w[2],w[3],pars->GC_4,pars->CMASS_mdl_MW,w[6]); |
953 | +VVV1_3(w[0],w[1],-pars->GC_3,pars->CMASS_mdl_MW,w[5]); |
954 | +VVV1_2(w[2],w[3],-pars->GC_3,pars->CMASS_mdl_MW,w[6]); |
955 | # Amplitude(s) for diagram number 1 |
956 | VVV1_0(w[5],w[6],w[4],pars->GC_53,amp[0]); |
957 | VVV1_1(w[3],w[4],pars->GC_53,pars->CMASS_mdl_MW,w[7]); |
958 | # Amplitude(s) for diagram number 2 |
959 | -VVV1_0(w[2],w[5],w[7],pars->GC_4,amp[1]); |
960 | +VVV1_0(w[2],w[5],w[7],-pars->GC_3,amp[1]); |
961 | # Amplitude(s) for diagram number 3 |
962 | VVVV5_0(w[2],w[5],w[3],w[4],pars->GC_57,amp[2]); |
963 | -VVV1_2(w[0],w[3],pars->GC_4,pars->CMASS_mdl_MW,w[5]); |
964 | -VVV1_3(w[2],w[1],pars->GC_4,pars->CMASS_mdl_MW,w[8]); |
965 | +VVV1_2(w[0],w[3],-pars->GC_3,pars->CMASS_mdl_MW,w[5]); |
966 | +VVV1_3(w[2],w[1],-pars->GC_3,pars->CMASS_mdl_MW,w[8]); |
967 | # Amplitude(s) for diagram number 4 |
968 | VVV1_0(w[8],w[5],w[4],pars->GC_53,amp[3]); |
969 | VVV1_2(w[1],w[4],pars->GC_53,pars->CMASS_mdl_MW,w[9]); |
970 | # Amplitude(s) for diagram number 5 |
971 | -VVV1_0(w[2],w[9],w[5],pars->GC_4,amp[4]); |
972 | +VVV1_0(w[2],w[9],w[5],-pars->GC_3,amp[4]); |
973 | # Amplitude(s) for diagram number 6 |
974 | VVVV5_0(w[2],w[1],w[5],w[4],pars->GC_57,amp[5]); |
975 | # Amplitude(s) for diagram number 7 |
976 | -VVV1_0(w[0],w[8],w[7],pars->GC_4,amp[6]); |
977 | +VVV1_0(w[0],w[8],w[7],-pars->GC_3,amp[6]); |
978 | # Amplitude(s) for diagram number 8 |
979 | -VVV1_0(w[0],w[9],w[6],pars->GC_4,amp[7]); |
980 | +VVV1_0(w[0],w[9],w[6],-pars->GC_3,amp[7]); |
981 | VVVV2_4(w[0],w[2],w[1],pars->GC_5,pars->CMASS_mdl_MW,w[9]); |
982 | # Amplitude(s) for diagram number 9 |
983 | VVV1_0(w[9],w[3],w[4],pars->GC_53,amp[8]); |
984 | VVVV5_3(w[0],w[1],w[4],pars->GC_57,pars->CMASS_mdl_MW,w[9]); |
985 | # Amplitude(s) for diagram number 10 |
986 | -VVV1_0(w[2],w[9],w[3],pars->GC_4,amp[9]); |
987 | +VVV1_0(w[2],w[9],w[3],-pars->GC_3,amp[9]); |
988 | VVVV2_3(w[0],w[2],w[3],pars->GC_5,pars->CMASS_mdl_MW,w[9]); |
989 | # Amplitude(s) for diagram number 11 |
990 | VVV1_0(w[1],w[9],w[4],pars->GC_53,amp[10]); |
991 | VVVV5_2(w[0],w[3],w[4],pars->GC_57,pars->CMASS_mdl_MW,w[9]); |
992 | # Amplitude(s) for diagram number 12 |
993 | -VVV1_0(w[2],w[1],w[9],pars->GC_4,amp[11]);""" |
994 | +VVV1_0(w[2],w[1],w[9],-pars->GC_3,amp[11]);""" |
995 | |
996 | self.assertEqual(solution.split('\n'), result) |
997 | |
998 | @@ -1097,40 +1097,40 @@ |
999 | w[2] = vxxxxx(p[2],ZERO,hel[2],+1) |
1000 | w[3] = vxxxxx(p[3],mdl_MW,hel[3],+1) |
1001 | w[4] = vxxxxx(p[4],mdl_MZ,hel[4],+1) |
1002 | -w[5]= VVV1_3(w[0],w[1],GC_4,CMASS_mdl_MW) |
1003 | -w[6]= VVV1_2(w[2],w[3],GC_4,CMASS_mdl_MW) |
1004 | +w[5]= VVV1_3(w[0],w[1],-GC_3,CMASS_mdl_MW) |
1005 | +w[6]= VVV1_2(w[2],w[3],-GC_3,CMASS_mdl_MW) |
1006 | # Amplitude(s) for diagram number 1 |
1007 | amp[0]= VVV1_0(w[5],w[6],w[4],GC_53) |
1008 | w[7]= VVV1_1(w[3],w[4],GC_53,CMASS_mdl_MW) |
1009 | # Amplitude(s) for diagram number 2 |
1010 | -amp[1]= VVV1_0(w[2],w[5],w[7],GC_4) |
1011 | +amp[1]= VVV1_0(w[2],w[5],w[7],-GC_3) |
1012 | # Amplitude(s) for diagram number 3 |
1013 | amp[2]= VVVV5_0(w[2],w[5],w[3],w[4],GC_57) |
1014 | -w[5]= VVV1_2(w[0],w[3],GC_4,CMASS_mdl_MW) |
1015 | -w[8]= VVV1_3(w[2],w[1],GC_4,CMASS_mdl_MW) |
1016 | +w[5]= VVV1_2(w[0],w[3],-GC_3,CMASS_mdl_MW) |
1017 | +w[8]= VVV1_3(w[2],w[1],-GC_3,CMASS_mdl_MW) |
1018 | # Amplitude(s) for diagram number 4 |
1019 | amp[3]= VVV1_0(w[8],w[5],w[4],GC_53) |
1020 | w[9]= VVV1_2(w[1],w[4],GC_53,CMASS_mdl_MW) |
1021 | # Amplitude(s) for diagram number 5 |
1022 | -amp[4]= VVV1_0(w[2],w[9],w[5],GC_4) |
1023 | +amp[4]= VVV1_0(w[2],w[9],w[5],-GC_3) |
1024 | # Amplitude(s) for diagram number 6 |
1025 | amp[5]= VVVV5_0(w[2],w[1],w[5],w[4],GC_57) |
1026 | # Amplitude(s) for diagram number 7 |
1027 | -amp[6]= VVV1_0(w[0],w[8],w[7],GC_4) |
1028 | +amp[6]= VVV1_0(w[0],w[8],w[7],-GC_3) |
1029 | # Amplitude(s) for diagram number 8 |
1030 | -amp[7]= VVV1_0(w[0],w[9],w[6],GC_4) |
1031 | +amp[7]= VVV1_0(w[0],w[9],w[6],-GC_3) |
1032 | w[9]= VVVV2_4(w[0],w[2],w[1],GC_5,CMASS_mdl_MW) |
1033 | # Amplitude(s) for diagram number 9 |
1034 | amp[8]= VVV1_0(w[9],w[3],w[4],GC_53) |
1035 | w[9]= VVVV5_3(w[0],w[1],w[4],GC_57,CMASS_mdl_MW) |
1036 | # Amplitude(s) for diagram number 10 |
1037 | -amp[9]= VVV1_0(w[2],w[9],w[3],GC_4) |
1038 | +amp[9]= VVV1_0(w[2],w[9],w[3],-GC_3) |
1039 | w[9]= VVVV2_3(w[0],w[2],w[3],GC_5,CMASS_mdl_MW) |
1040 | # Amplitude(s) for diagram number 11 |
1041 | amp[10]= VVV1_0(w[1],w[9],w[4],GC_53) |
1042 | w[9]= VVVV5_2(w[0],w[3],w[4],GC_57,CMASS_mdl_MW) |
1043 | # Amplitude(s) for diagram number 12 |
1044 | -amp[11]= VVV1_0(w[2],w[1],w[9],GC_4)""" |
1045 | +amp[11]= VVV1_0(w[2],w[1],w[9],-GC_3)""" |
1046 | |
1047 | self.assertEqual(solution.split('\n'), result) |
1048 | |
1049 | |
1050 | === modified file 'tests/unit_tests/various/test_decay.py' |
1051 | --- tests/unit_tests/various/test_decay.py 2016-09-06 15:01:18 +0000 |
1052 | +++ tests/unit_tests/various/test_decay.py 2018-06-02 22:01:27 +0000 |
1053 | @@ -1397,7 +1397,7 @@ |
1054 | except KeyError: |
1055 | coup0 = model['couplings'][()][0] |
1056 | # coupling depend on aS |
1057 | - coup_aS = model['couplings'][('aS',)][0] |
1058 | + coup_aS = model['couplings'][('aS',)][1] |
1059 | # coupling depend on both aS and aEWM1 |
1060 | try: |
1061 | coup_both = model['couplings'][('aS', 'aEWM1')][0] |
1062 | @@ -1427,7 +1427,7 @@ |
1063 | |
1064 | # Both of GC_114 ('aS',) and GC_15 ('aEWSM1', 'aS') should change |
1065 | self.assertAlmostEqual(eval('decay_objects.'+coup_aS.name), \ |
1066 | - -decay_objects.G) |
1067 | + 1j*decay_objects.G**2) |
1068 | |
1069 | # copying the expr of |
1070 | self.assertAlmostEqual(eval('decay_objects.'+coup_both.name), \ |
1071 | |
1072 | === modified file 'tests/unit_tests/various/test_import_ufo.py' |
1073 | --- tests/unit_tests/various/test_import_ufo.py 2015-11-23 05:39:08 +0000 |
1074 | +++ tests/unit_tests/various/test_import_ufo.py 2018-06-02 22:01:27 +0000 |
1075 | @@ -26,6 +26,7 @@ |
1076 | import models.model_reader as model_reader |
1077 | import madgraph.iolibs.export_v4 as export_v4 |
1078 | import models as ufomodels |
1079 | +import madgraph.various.misc as misc |
1080 | |
1081 | _file_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] |
1082 | |
1083 | @@ -144,7 +145,7 @@ |
1084 | |
1085 | self.assertEqual(original_all_particles,ufo_model.all_particles) |
1086 | self.assertEqual(original_all_vertices,ufo_model.all_vertices) |
1087 | -# self.assertEqual(original_all_couplings,ufo_model.all_couplings) |
1088 | + self.assertEqual(original_all_couplings,ufo_model.all_couplings) |
1089 | self.assertEqual(original_all_lorentz,ufo_model.all_lorentz) |
1090 | self.assertEqual(original_all_parameters,ufo_model.all_parameters) |
1091 | self.assertEqual(original_all_orders,ufo_model.all_orders) |
1092 | @@ -152,6 +153,34 @@ |
1093 | self.assertEqual(original_all_CTvertices,ufo_model.all_CTvertices) |
1094 | self.assertEqual(original_all_CTparameters,ufo_model.all_CTparameters) |
1095 | |
1096 | + # Also test that one new lorentz struture has been added within the model |
1097 | + # and that the associate optimization is working as expected. |
1098 | + self.assertEqual(len(original_all_lorentz) + 1, len(model['lorentz'])) |
1099 | + new_l = [l for l in model['lorentz'] if l not in original_all_lorentz][0] |
1100 | + new_name = new_l.name |
1101 | + self.assertEqual(new_l.name, 'R2RGA_VVVV1') |
1102 | + # find interactions with that lorentz structure |
1103 | + int_with_it = [] |
1104 | + for id, vertices in model.get('interaction_dict').items(): |
1105 | + if new_name in vertices['lorentz']: |
1106 | + int_with_it.append(vertices) |
1107 | + self.assertEqual(len(int_with_it), 2) |
1108 | + # check the first one |
1109 | + vert = int_with_it[0] |
1110 | + pdg = [p['pdg_code'] for p in vert['particles']] |
1111 | + self.assertEqual(pdg, [21,21,21,21]) |
1112 | + # check the equivalent vertex in the original model |
1113 | + old_vert = [ v for v in ufo_model.all_CTvertices if pdg == [p.pdg_code for p in v.particles]] |
1114 | + #pick one |
1115 | + old_vert = old_vert[0] |
1116 | + |
1117 | + # find the number of coupling associate to this lorentz structure |
1118 | + ind = vert['lorentz'].index(new_name) |
1119 | + coup_name = [ c for ((l,col),c) in vert['couplings'].items() if l ==ind] |
1120 | + nb_old = len([ c for ((l,col),c) in vert['couplings'].items() if c == coup_name[0]]) |
1121 | + nb_new = len([ c for ((l,col,k),c) in old_vert.couplings.items() if c.name == coup_name[0]]) |
1122 | + self.assertEqual(3*nb_old, nb_new) |
1123 | + |
1124 | #=============================================================================== |
1125 | # TestRestrictModel |
1126 | #=============================================================================== |
1127 | @@ -241,7 +270,20 @@ |
1128 | self.assertEqual(expected, result) |
1129 | |
1130 | # check what are the identical coupling |
1131 | - expected = [['GC_100', 'GC_108', 'GC_49', 'GC_45', 'GC_40', 'GC_41', 'GC_104']] |
1132 | + expected = [[('GC_100',1), ('GC_108',1), ('GC_49',1), ('GC_45',1), ('GC_40',1), ('GC_41',1), ('GC_104',1)], |
1133 | + [('GC_21', 1), ('GC_27', -1)], |
1134 | + [('GC_3', 1), ('GC_4', -1)], |
1135 | + [('GC_39', 1), ('GC_38', -1)], |
1136 | + [('GC_51', 1), ('GC_50', -1)], |
1137 | + [('GC_53', 1), ('GC_52', -1)], |
1138 | + [('GC_56', 1), ('GC_54', -1)], |
1139 | + [('GC_66', 1), ('GC_67', -1)], |
1140 | + [('GC_7', 1), ('GC_9', -1)], |
1141 | + [('GC_70', 1), ('GC_73', -1)], |
1142 | + [('GC_75', 1), ('GC_74', -1)], |
1143 | + [('GC_76', 1), ('GC_79', -1)], |
1144 | + [('GC_77', 1), ('GC_78', -1)], |
1145 | + [('GC_97', 1), ('GC_96', -1)]] |
1146 | expected.sort() |
1147 | iden.sort() |
1148 | self.assertEqual(expected, iden) |
1149 | @@ -286,28 +328,29 @@ |
1150 | |
1151 | # Check that All the code/model is the one intended for this test |
1152 | target = [i for i in iden if len(i)==7][0] |
1153 | - GC = target[0] |
1154 | + target2 = [i[0] for i in target] |
1155 | + GC = target2[0] |
1156 | |
1157 | check_content = [['d', 'u', 'w+'], ['s', 'c', 'w+'], ['b', 't', 'w+'], ['u', 'd', 'w+'], ['c', 's', 'w+'], ['t', 'b', 'w+'], ['e-', 've', 'w+'], ['m-', 'vm', 'w+'], ['tt-', 'vt', 'w+'], ['ve', 'e-', 'w+'], ['vm', 'm-', 'w+'], ['vt', 'tt-', 'w+']] |
1158 | content = [[p.get('name') for p in v.get('particles')] \ |
1159 | for v in self.model.get('interactions') \ |
1160 | - if any([c in target for c in v['couplings'].values()])] |
1161 | + if any([c in target2 for c in v['couplings'].values()])] |
1162 | |
1163 | self.assertEqual(len(check_content),len(content))#, 'test not up-to-date' |
1164 | |
1165 | vertex_id = [v.get('id') \ |
1166 | for v in self.model.get('interactions') \ |
1167 | - if any([c in target for c in v['couplings'].values()])] |
1168 | + if any([c in target2 for c in v['couplings'].values()])] |
1169 | |
1170 | |
1171 | for id in vertex_id: |
1172 | is_in_target = False |
1173 | for coup in self.model.get_interaction(id)['couplings'].values(): |
1174 | - if coup in target: |
1175 | + if coup in target2: |
1176 | is_in_target = True |
1177 | assert is_in_target == True, 'test not up-to-date' |
1178 | |
1179 | - # check now that everything is fine |
1180 | + # check now that everything is fine |
1181 | self.model.merge_iden_couplings(target) |
1182 | for id in vertex_id: |
1183 | has_GC = False |
1184 | @@ -316,6 +359,41 @@ |
1185 | if coup == GC: |
1186 | has_GC = True |
1187 | self.assertTrue(has_GC, True) |
1188 | + |
1189 | + # check that the same occur with opposite sign coupling |
1190 | + target = [i for i in iden if len(i)==2][1] |
1191 | + target2 = [i[0] for i in target] |
1192 | + GC = target2[0] |
1193 | + |
1194 | + check_content = [['a', 'w+', 'w+'], ['e-', 'e-', 'a'], ['mu-', 'mu-', 'a'], ['ta-', 'ta-', 'a']] |
1195 | + content = [[p.get('name') for p in v.get('particles')] \ |
1196 | + for v in self.model.get('interactions') \ |
1197 | + if any([c in target2 for c in v['couplings'].values()])] |
1198 | + #content = [[v.get('couplings').values() for p in v.get('particles')] \ |
1199 | + # for v in self.model.get('interactions')] |
1200 | + self.assertEqual(len(check_content),len(content))#, 'test not up-to-date' |
1201 | + |
1202 | + vertex_id = [v.get('id') \ |
1203 | + for v in self.model.get('interactions') \ |
1204 | + if any([c in target2[1:] for c in v['couplings'].values()])] |
1205 | + |
1206 | + for id in vertex_id: |
1207 | + is_in_target = False |
1208 | + for coup in self.model.get_interaction(id)['couplings'].values(): |
1209 | + if coup in target2: |
1210 | + is_in_target = True |
1211 | + assert is_in_target == True, 'test not up-to-date' |
1212 | + |
1213 | + self.model.merge_iden_couplings(target) |
1214 | + for id in vertex_id: |
1215 | + has_GC = False |
1216 | + for coup in self.model.get_interaction(id)['couplings'].values(): |
1217 | + self.assertFalse(coup in target[1:]) |
1218 | + if coup == '-%s' % GC: |
1219 | + has_GC = True |
1220 | + self.assertTrue(has_GC, True) |
1221 | + |
1222 | + |
1223 | |
1224 | def test_remove_couplings(self): |
1225 | """ check that the detection of irrelevant interactions works """ |
1226 | @@ -428,7 +506,58 @@ |
1227 | self.assertFalse(param.name in ['ymb']) |
1228 | if param.name == 'yb': |
1229 | param.expr == 'ZERO' |
1230 | - |
1231 | + |
1232 | + def test_get_new_coupling_name(self): |
1233 | + """ test that the static function get_new_coupling_name |
1234 | + behaves as expected |
1235 | + """ |
1236 | + |
1237 | + # reject wrong input |
1238 | + self.assertRaises(AssertionError, import_ufo.RestrictModel.get_new_coupling_name, |
1239 | + '','','',0) |
1240 | + self.assertRaises(AssertionError, import_ufo.RestrictModel.get_new_coupling_name, |
1241 | + '','','',2.) |
1242 | + self.assertRaises(AssertionError, import_ufo.RestrictModel.get_new_coupling_name, |
1243 | + '','1','2',1) |
1244 | + self.assertRaises(AssertionError, import_ufo.RestrictModel.get_new_coupling_name, |
1245 | + '',1,1,1) |
1246 | + self.assertRaises(AssertionError, import_ufo.RestrictModel.get_new_coupling_name, |
1247 | + 1,'1','1',1) |
1248 | + |
1249 | + # real test |
1250 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1251 | + 'GC1', 'GC2', 'GC2', 1), 'GC1') |
1252 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1253 | + 'GC1', 'GC2', '-GC2', 1), '-GC1') |
1254 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1255 | + 'GC1', '-GC2', 'GC2', 1), '-GC1') |
1256 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1257 | + 'GC1', '-GC2', '-GC2', 1), 'GC1') |
1258 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1259 | + '-GC1', 'GC2', 'GC2', 1), '-GC1') |
1260 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1261 | + '-GC1', 'GC2', '-GC2', 1), 'GC1') |
1262 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1263 | + '-GC1', '-GC2', 'GC2', 1), 'GC1') |
1264 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1265 | + '-GC1', '-GC2', '-GC2', 1), '-GC1') |
1266 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1267 | + 'GC1', 'GC2', 'GC2', -1), '-GC1') |
1268 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1269 | + 'GC1', 'GC2', '-GC2', -1), 'GC1') |
1270 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1271 | + 'GC1', '-GC2', 'GC2', -1), 'GC1') |
1272 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1273 | + 'GC1', '-GC2', '-GC2', -1), '-GC1') |
1274 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1275 | + '-GC1', 'GC2', 'GC2', -1), 'GC1') |
1276 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1277 | + '-GC1', 'GC2', '-GC2', -1), '-GC1') |
1278 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1279 | + '-GC1', '-GC2', 'GC2', -1), '-GC1') |
1280 | + self.assertEqual(import_ufo.RestrictModel.get_new_coupling_name(\ |
1281 | + '-GC1', '-GC2', '-GC2', -1), 'GC1') |
1282 | + |
1283 | def test_restrict_from_a_param_card(self): |
1284 | """ check the full restriction chain in one case b b~ h """ |
1285 |
I've continued the work in model optimization in the context of restricted model
1) redo the above work of creating new lorentz structure for identified coupling.
2) Identify opposite sign coupling and keep only one of the two.
3) Doing the same as 1 but also for opposite sign coupling. This is very helpfull to avoid numerical inaccuracy in some complex model (complex spin 3/2 for example)
I'm running all the tests (I obviously add some at the same time) and then I will push this.
So please do not start this review right now.
Cheers,
Olivier