a real parameter becomes complex when passing to a function defined in function_library.py

Asked by toodles

Dear authors,

I am adding a function in the function_library.py file as:

effv = Function(name = 'effv',
                  arguments = ('flam','s1'),
                  expression = '(1.0 if flam > s1 else 0.0)')

I defined flam to be real in the parameter.py file and s1 = P(-1, x).P(-1,x) which is the invariant mass of the x particle.

When I launch, I got the following error:

 EFFV = (CONDIF(FLAM.GT.S1,DCMPLX(1.000000D+00),DCMPLX(0.000000D
                          1
     Error: COMPLEX quantities cannot be compared at (1)

I tried to use expression = '(1.0 if flam.real > s1.real else 0.0)'), the error turns out to be:

        EFFV = (CONDIF((DBLE(FLAM)).GT.(DBLE(S1)),DCMPLX(1.000000D
                   1
     Error: Function 'condif' at (1) has no IMPLICIT type

I am totally confused. My variable passing to the EFFV function is actually real, why it reminds me they are complex?
When I use .real, it should return double precision real type, why it doesn't work?

Cheers,
YY

Question information

Language:
English Edit question
Status:
Solved
For:
MadGraph5_aMC@NLO Edit question
Assignee:
No assignee Edit question
Solved by:
Olivier Mattelaer
Solved:
Last query:
Last reply:
Revision history for this message
Olivier Mattelaer (olivier-mattelaer) said :
#1

Hi,

All argument of any function defined in function_library,py are expected to apply on complex number.

> I tried to use expression = '(1.0 if flam.real > s1.real else 0.0)'), the error turns out to be:
>
> EFFV = (CONDIF((DBLE(FLAM)).GT.(DBLE(S1)),DCMPLX(1.000000D
> 1
> Error: Function 'condif' at (1) has no IMPLICIT type

Looks like the “if” statement is not detected correctly when we create a function and the associate definition is not written in the file.
I will fix this for the next version.

Cheers,

Olivier

> On 25 Apr 2017, at 22:13, toodles <email address hidden> wrote:
>
> New question #628460 on MadGraph5_aMC@NLO:
> https://answers.launchpad.net/mg5amcnlo/+question/628460
>
> Dear authors,
>
> I am adding a function in the function_library.py file as:
>
> effv = Function(name = 'effv',
> arguments = ('flam','s1'),
> expression = '(1.0 if flam > s1 else 0.0)')
>
> I defined flam to be real in the parameter.py file and s1 = P(-1, x).P(-1,x) which is the invariant mass of the x particle.
>
> When I launch, I got the following error:
>
> EFFV = (CONDIF(FLAM.GT.S1,DCMPLX(1.000000D+00),DCMPLX(0.000000D
> 1
> Error: COMPLEX quantities cannot be compared at (1)
>
> I tried to use expression = '(1.0 if flam.real > s1.real else 0.0)'), the error turns out to be:
>
> EFFV = (CONDIF((DBLE(FLAM)).GT.(DBLE(S1)),DCMPLX(1.000000D
> 1
> Error: Function 'condif' at (1) has no IMPLICIT type
>
> I am totally confused. My variable passing to the EFFV function is actually real, why it reminds me they are complex?
> When I use .real, it should return double precision real type, why it doesn't work?
>
> Cheers,
> YY
>
> --
> You received this question notification because you are an answer
> contact for MadGraph5_aMC@NLO.

Revision history for this message
toodles (liyybnu) said :
#2

Hi Olivier,

Thanks for your reply! So is there a way to fix this with the current version?

Cheers,
YY

Revision history for this message
Olivier Mattelaer (olivier-mattelaer) said :
#3

The solution for the moment is to not use function_library.py and code your if statement directly in the expression.

Cheers,

Olivier
> On 26 Apr 2017, at 04:03, toodles <email address hidden> wrote:
>
> Question #628460 on MadGraph5_aMC@NLO changed:
> https://answers.launchpad.net/mg5amcnlo/+question/628460
>
> Status: Answered => Open
>
> toodles is still having a problem:
> Hi Olivier,
>
> Thanks for your reply! So is there a way to fix this with the current
> version?
>
> Cheers,
> YY
>
> --
> You received this question notification because you are an answer
> contact for MadGraph5_aMC@NLO.

Revision history for this message
toodles (liyybnu) said :
#4

Hi Olivier,

Thanks for your reply! Actually I am following method One here https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FormFactors
to add form factors. I guess adding the if statement in the form_factors.py file doesn't work either, according to your answer here https://answers.launchpad.net/mg5amcnlo/+question/240407.

I could use method two as you recommended. However method two seems incomplete, since it didn't tell me where to include function.f file. Sorry I am really new to fortran.

Revision history for this message
Best Olivier Mattelaer (olivier-mattelaer) said :
#5

Hi,

This is not yet fully validated. But here is a patch which should allow you to have the if statement inside a function:

Cheers,

Olivier

=== modified file 'madgraph/iolibs/export_v4.py'
--- madgraph/iolibs/export_v4.py 2017-03-03 10:07:55 +0000
+++ madgraph/iolibs/export_v4.py 2017-04-26 22:39:06 +0000
@@ -6232,16 +6232,31 @@
           double complex function %(name)s(%(args)s)
           implicit none
           double complex %(args)s
+ %(definitions)s
           %(name)s = %(fct)s

           return
           end
           """
+ str_fct = self.p_to_f.parse(fct.expr)
+ if not self.p_to_f.to_define:
+ definitions = []
+ else:
+ definitions=[]
+ for d in self.p_to_f.to_define:
+ if d == 'pi':
+ definitions.append(' double precision pi')
+ definitions.append(' data pi /3.1415926535897932d0/')
+ else:
+ definitions.append(' double complex %s' % d)
+
                     text = ufo_fct_template % {
                                 'name': fct.name,
                                 'args': ", ".join(fct.arguments),
- 'fct': self.p_to_f.parse(fct.expr)
+ 'fct': str_fct,
+ 'definitions': '\n'.join(definitions)
                                  }
+
                     fsock.writelines(text)
             if self.opt['mp']:
                 fsock.write_comment_line(' START UFO DEFINE FUNCTIONS FOR MP')
@@ -6253,15 +6268,29 @@
           %(complex_mp_format)s function mp__%(name)s(mp__%(args)s)
           implicit none
           %(complex_mp_format)s mp__%(args)s
+ %(definitions)
           mp__%(name)s = %(fct)s

           return
           end
           """
+
+ str_fct = self.mp_p_to_f.parse(fct.expr)
+ if not self.p_to_f.to_define:
+ definitions = []
+ else:
+ definitions=[]
+ for d in self.p_to_f.to_define:
+ if d == 'mp_pi':
+ definitions.append(' %s mp_pi' % self.mp_real_format)
+ definitions.append(' data mp_pi /3.141592653589793238462643383279502884197e+00_16/')
+ else:
+ definitions.append(' %s %s' % (self.mp_complex_format,d))
                         text = ufo_fct_template % {
                                 'name': fct.name,
                                 'args': ", mp__".join(fct.arguments),
- 'fct': self.mp_p_to_f.parse(fct.expr),
+ 'fct': str_fct,
+ 'definitions': '\n'.join(definitions),
                                 'complex_mp_format': self.mp_complex_format
                                  }
                         fsock.writelines(text)

=== modified file 'madgraph/iolibs/ufo_expression_parsers.py'
--- madgraph/iolibs/ufo_expression_parsers.py 2016-04-25 09:54:36 +0000
+++ madgraph/iolibs/ufo_expression_parsers.py 2017-04-26 22:29:22 +0000
@@ -58,6 +58,7 @@

     def parse(self, buf):
         """Parse the string buf"""
+ self.clean()
         self.y.parse(buf)
         return self.parsed_string

@@ -163,6 +164,12 @@
         logger.error("Illegal character '%s'" % t.value[0])
         t.lexer.skip(1)

+ def clean(self):
+ """remove variable related to the latest parsing"""
+ #nothing to do here
+ return
+
+
     # Build the lexer
     def build(self,**kwargs):
         self.lexer = lex.lex(module=self, **kwargs)
@@ -268,6 +275,8 @@
     """A parser for UFO algebraic expressions, outputting
     Fortran-style code."""

+
+
     # The following parser expressions need to be defined for each
     # output language/framework

@@ -280,6 +289,19 @@
                      'or':'.OR.',
                      'and':'.AND.'}

+ def __init__(self, *args, **opts):
+ """ """
+ out = super(UFOExpressionParserFortran,self).__init__(*args, **opts)
+ self.to_define = set()
+
+ def clean(self):
+ """remove information about object parse for previous parsing
+ """
+ self.to_define = set()
+
+
+
+
     def p_expression_number(self, p):
         "expression : NUMBER"
         if p[1].endswith('j'):
@@ -307,19 +329,23 @@
     def p_expression_if(self,p):
         "expression : expression IF boolexpression ELSE expression "
         p[0] = 'CONDIF(%s,DCMPLX(%s),DCMPLX(%s))' % (p[3], p[1], p[5])
+ self.to_define.add('condif')

     def p_expression_ifimplicit(self,p):
         "expression : expression IF expression ELSE expression "
         p[0] = 'CONDIF(DCMPLX(%s).NE.(0d0,0d0),DCMPLX(%s),DCMPLX(%s))'\
                                                              %(p[3], p[1], p[5])
+ self.to_define.add('condif')

     def p_expression_cond(self, p):
         "expression : COND '(' expression ',' expression ',' expression ')'"
         p[0] = 'COND(DCMPLX('+p[3]+'),DCMPLX('+p[5]+'),DCMPLX('+p[7]+'))'
+ self.to_define.add('cond')

     def p_expression_recms(self, p):
         "expression : RECMS '(' boolexpression ',' expression ')'"
         p[0] = 'RECMS('+p[3]+',DCMPLX('+p[5]+'))'
+ self.to_define.add('recms')

     def p_expression_complex(self, p):
         "expression : COMPLEX '(' expression ',' expression ')'"
@@ -356,6 +382,8 @@
         elif p[1] == 'reglogp': p[0] = 'reglogp(DCMPLX' + p[2] + ')'
         elif p[1] == 'reglogm': p[0] = 'reglogm(DCMPLX' + p[2] + ')'

+ if p[1] in ['reglog', 'reglogp', 'reglogm']:
+ self.to_define.add(p[1])

     def p_expression_real(self, p):
         ''' expression : expression RE2 '''
@@ -374,6 +402,7 @@
     def p_expression_pi(self, p):
         '''expression : PI'''
         p[0] = 'pi'
+ self.to_define.add('pi')

 class UFOExpressionParserMPFortran(UFOExpressionParserFortran):
     """A parser for UFO algebraic expressions, outputting
@@ -413,12 +442,14 @@
     def p_expression_if(self,p):
         "expression : expression IF boolexpression ELSE expression "
         p[0] = 'MP_CONDIF(%s,CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))' % (p[3], p[1], p[5])
-
+ self.to_define.add('mp_condif')
+
     def p_expression_ifimplicit(self,p):
         "expression : expression IF expression ELSE expression "
         p[0] = 'MP_CONDIF(CMPLX(%s,KIND=16).NE.(0.0e0_16,0.0e0_16),CMPLX(%s,KIND=16),CMPLX(%s,KIND=16))'\
                                                              %(p[3], p[1], p[5])
-
+ self.to_define.add('mp_condif')
+
     def p_expression_complex(self, p):
         "expression : COMPLEX '(' expression ',' expression ')'"
         p[0] = 'CMPLX(' + p[3] + ',' + p[5] + ',KIND=16)'
@@ -427,10 +458,12 @@
         "expression : COND '(' expression ',' expression ',' expression ')'"
         p[0] = 'MP_COND(CMPLX('+p[3]+',KIND=16),CMPLX('+p[5]+\
                                           ',KIND=16),CMPLX('+p[7]+',KIND=16))'
+ self.to_define.add('mp_cond')

     def p_expression_recms(self, p):
         "expression : RECMS '(' boolexpression ',' expression ')'"
         p[0] = 'MP_RECMS('+p[3]+',CMPLX('+p[5]+',KIND=16))'
+ self.to_define.add('mp_recms')

     def p_expression_func(self, p):
         '''expression : CSC group
@@ -463,6 +496,9 @@
         elif p[1] == 'reglogp': p[0] = 'mp_reglogp(CMPLX(' + p[2] + ',KIND=16))'
         elif p[1] == 'reglogm': p[0] = 'mp_reglogm(CMPLX(' + p[2] + ',KIND=16))'

+ if p[1] in ['reglog', 'reglogp', 'reglogm']:
+ self.to_define.add(p[1])
+
     def p_expression_real(self, p):
         ''' expression : expression RE2 '''

@@ -481,7 +517,8 @@
     def p_expression_pi(self, p):
         '''expression : PI'''
         p[0] = self.mp_prefix+'pi'
-
+ self.to_define.add(self.mp_prefix+'pi')
+
 class UFOExpressionParserCPP(UFOExpressionParser):
     """A parser for UFO algebraic expressions, outputting
     C++-style code."""

> On 26 Apr 2017, at 17:47, toodles <email address hidden> wrote:
>
> Question #628460 on MadGraph5_aMC@NLO changed:
> https://answers.launchpad.net/mg5amcnlo/+question/628460
>
> Status: Answered => Open
>
> toodles is still having a problem:
> Hi Olivier,
>
> Thanks for your reply! Actually I am following method One here https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/FormFactors
> to add form factors. I guess adding the if statement in the form_factors.py file doesn't work either, according to your answer here https://answers.launchpad.net/mg5amcnlo/+question/240407.
>
> I could use method two as you recommended. However method two seems
> incomplete, since it didn't tell me where to include function.f file.
> Sorry I am really new to fortran.
>
> --
> You received this question notification because you are an answer
> contact for MadGraph5_aMC@NLO.

Revision history for this message
toodles (liyybnu) said :
#6

Thanks Olivier Mattelaer, that solved my question.