Пример #1
0
        def sortFunc(term):
            if term.find(Delta) != set():
                return float("inf"), ()

            atoms = []
            for el in [subTerm for subTerm in splitPow(term) if not subTerm.is_number]:
                if isinstance(el, Trace):
                    for ell in splitPow(el.args[0]):
                        atoms.append(list(ell.atoms())[0])
                elif isinstance(el, Symbol):
                    atoms.append(el)
                else:
                    atoms.append(list(el.atoms())[0])
            trace = 'Trace(' in str(term)

            # Remove IdentityMatrices from atoms
            #  + Remove the gauge parameter 'xi' when dealing with vevs
            #  + Remove any symbolic coefficient (e.g. generation numbers)
            atoms = [el for el in atoms if not (hasattr(el, 'is_Identity') and el.is_Identity) and not str(el)=='_xiGauge' and str(el) in Printer.model.allCouplings]

            score = sum([priority[Printer.model.allCouplings[str(el)][0]] for el in atoms])

            if trace:
                score += .5

            sortByCouplingName = []
            for _ in priority:
                sortByCouplingName.append([])

            for el in atoms:
                cType = Printer.model.allCouplings[str(el)][0]
                pos = Printer.model.couplingsPos[cType][str(el)]
                sortByCouplingName[sortedTypes[cType]].append(pos)

            return score, sortByCouplingName
Пример #2
0
    def _print_Mul(self, expr):
        if expr.find(Indexed) != set() and expr.find(Pow) != set():
            if not all([int(el.exp) != el.exp for el in expr.find(Pow)]):
                return ' '.join([self._print(el) for el in splitPow(expr)])

        if isinstance(expr.args[0], Rational) and abs(expr.args[0]) != 1 and not self.baseMul:
            coeff = Mul(*[el for el in flatten(expr.as_coeff_mul()) if el.is_number])
            return self.latex.totex(coeff, baseMul=True) + ' ' + (self._print((expr/coeff).doit()) if expr != coeff else '')

        if self.absReplacements and expr.find(conjugate) != set():
        # Substitution x * conjugate(x) -> |x|^2
            conjArgs = {}
            args = splitPow(expr)
            for el in args:
                if isinstance(el, conjugate) or el.is_commutative == False or el.is_real:
                    continue
                else:
                    count = min(args.count(el), args.count(conjugate(el)))
                    if count != 0:
                        conjArgs[el] = count
            if conjArgs != {}:
                for k,v in conjArgs.items():
                    for _ in range(v):
                        args.remove(k)
                        args.remove(conjugate(k))
                        args.append(Abs(k)**2)
                expr = Mul(*args)

        return super()._print_Mul(expr)
Пример #3
0
    def _print_Mul(self, expr):
        if expr.find(conjugate) != set():
            # Substitution x * conjugate(x) -> abs(x)^2
            conjArgs = {}
            args = splitPow(expr)
            for el in args:
                if isinstance(
                        el,
                        conjugate) or el.is_commutative == False or el.is_real:
                    continue
                else:
                    count = min(args.count(el), args.count(conjugate(el)))
                    if count != 0:
                        conjArgs[el] = count
            if conjArgs != {}:
                for k, v in conjArgs.items():
                    for _ in range(v):
                        args.remove(k)
                        args.remove(conjugate(k))
                        args.append(Abs(k)**2)
                expr = Mul(*args)

        if self.processContent:
            args = splitPow(expr)
            matrixArgs = []
            for el in args:
                if el.is_commutative is False:
                    matrixArgs.append(el)
            matrixArgs = tuple(matrixArgs)

            if len(matrixArgs) >= 2:
                if matrixArgs not in Printer.preDefined['m']:
                    Printer.preDefined['m'][matrixArgs] = 0
                Printer.preDefined['m'][matrixArgs] += 1

        return super()._print_Mul(expr)
Пример #4
0
    def _print_Mul(self, expr):
        if expr.find(conjugate) != set():
            # Substitution x * conjugate(x) -> abs(x)^2
            conjArgs = {}
            args = splitPow(expr)
            for el in args:
                if isinstance(
                        el,
                        conjugate) or el.is_commutative == False or el.is_real:
                    continue
                else:
                    count = min(args.count(el), args.count(conjugate(el)))
                    if count != 0:
                        conjArgs[el] = count
            if conjArgs != {}:
                for k, v in conjArgs.items():
                    for _ in range(v):
                        args.remove(k)
                        args.remove(conjugate(k))
                        args.append(Abs(k)**2)
                expr = Mul(*args)

        return super()._print_Mul(expr)
Пример #5
0
    def fillTensorDic(self, coupling, expTerm, content):
        subTerms = expTerm.as_coeff_add()[1]
        tensorInds = ()
        coeff = 0

        fermions = ()
        scalars = ()

        coupling = Symbol(coupling, complex=True)

        cType = self.model.allCouplings[str(coupling)]
        if type(cType) == tuple:
            cType = cType[0]

        for subTerm in subTerms:
            subTerm = list(subTerm.as_coeff_mul())
            rationalFactors = [el for el in subTerm[1] if el.is_number]
            subTerm[1] = tuple(
                [el for el in subTerm[1] if el not in rationalFactors])
            subTerm[0] *= Mul(*rationalFactors)

            subTerm[1] = splitPow(subTerm[1])

            #For fermions, we have to be careful that the order in which the user wrote the terms
            # is preserved here. Inverting them would transpose the Yukawa / mass matrix

            fermions = [
                self.model.allFermions[str(el)] for el in subTerm[1]
                if str(el) in self.model.allFermions
            ]

            if fermions != []:
                # Sort fermions according to their pos in the potential term
                fermionSortKey = {}
                fermionNames = sorted([str(el[1]) for el in fermions],
                                      key=lambda x: len(x),
                                      reverse=True)
                potStr = self.currentPotentialDic[str(coupling)]
                for el in fermionNames:
                    fermionSortKey[el] = potStr.find(el)
                    potStr = potStr.replace(el, ' ' * len(el))
                fermions = sorted(fermions,
                                  key=lambda x: fermionSortKey[str(x[1])])

            fGen = [f[1].gen for f in fermions]
            fermions = [f[0] for f in fermions]

            scalars = [
                self.model.allScalars[str(el)][0] for el in subTerm[1]
                if str(el) in self.model.allScalars
            ]
            # sGen = [self.model.allScalars[str(el)][1].gen for el in subTerm[1] if str(el) in self.model.allScalars]

            if content == (2, 1):  #Yukawa
                if len(fermions) != 2 or len(scalars) != 1:
                    loggingCritical(
                        f"Error in term {str(coupling)} : \n\tYukawa terms must contain exactly 2 fermions and 1 scalar."
                    )
                    exit()
                tensorInds = tuple(scalars + fermions)
                coeff = subTerm[0] * 2 / len(
                    set(itertools.permutations(fermions, 2)))

                # # Fermion1 = Fermion2 : the matrix is symmetric
                # if self.allFermionsValues[fermions[0]][1] == self.allFermionsValues[fermions[1]][1]:
                #     self.model.assumptions[str(coupling)]['symmetric'] = True
                # # Fermion1 = Fermion2bar : the matrix is hermitian
                # if self.allFermionsValues[fermions[0]][1] == self.allFermionsValues[self.antiFermionPos(fermions[1])][1]:
                #     self.model.assumptions[str(coupling)]['hermitian'] = True

                assumptionDic = self.model.assumptions[str(coupling)]

                coupling = mSymbol(str(coupling), fGen[0], fGen[1],
                                   **assumptionDic)
                if coupling not in self.model.couplingStructure:
                    self.model.couplingStructure[str(coupling)] = (fGen[0],
                                                                   fGen[1])

            if content == (0, 4):  #Quartic
                if len(fermions) != 0 or len(scalars) != 4:
                    loggingCritical(
                        f"\nError in term {str(coupling)} : \n\tQuartic terms must contain exactly 0 fermion and 4 scalars."
                    )
                    exit()
                tensorInds = tuple(sorted(scalars))
                coeff = subTerm[0] * 24 / len(
                    set(itertools.permutations(
                        tensorInds,
                        4)))  #/len(set(itertools.permutations(tensorInds, 4)))

            if content == (0, 3):  #Trilinear
                if len(fermions) != 0 or len(scalars) != 3:
                    loggingCritical(
                        f"\nError in term {str(coupling)} : \n\tTrinilear terms must contain exactly 0 fermion and 3 scalars."
                    )
                    exit()
                tensorInds = tuple(sorted(scalars))
                coeff = subTerm[0] * 6 / len(
                    set(itertools.permutations(tensorInds, 3)))

            if content == (0, 2):  #Scalar Mass
                if len(fermions) != 0 or len(scalars) != 2:
                    loggingCritical(
                        f"\nError in term {str(coupling)} : \n\tScalar mass terms must contain exactly 0 fermion and 2 scalars."
                    )
                    exit()
                tensorInds = tuple(sorted(scalars))
                coeff = subTerm[0] * 2 / len(
                    set(itertools.permutations(tensorInds, 2)))

            if content == (2, 0):  #Fermion Mass
                if len(fermions) != 2 or len(scalars) != 0:
                    loggingCritical(
                        f"\nError in term {str(coupling)} : \n\tFermion mass terms must contain exactly 2 fermions and 0 scalar."
                    )
                    exit()
                tensorInds = tuple(fermions)
                coeff = subTerm[0] * 2 / len(
                    set(itertools.permutations(tensorInds, 2)))

                # # Fermion1 = Fermion2 : the matrix is symmetric
                # if fermions[0] == fermions[1]:
                #     self.model.assumptions[str(coupling)]['symmetric'] = True
                # # Fermion1 = Fermion2bar : the matrix is hermitian
                # if fermions[0] == self.antiFermionPos(fermions[1]):
                #     self.model.assumptions[str(coupling)]['hermitian'] = True

                assumptionDic = self.model.assumptions[str(coupling)]

                coupling = mSymbol(str(coupling), fGen[0], fGen[1],
                                   **assumptionDic)
                if coupling not in self.model.couplingStructure:
                    self.model.couplingStructure[str(coupling)] = (fGen[0],
                                                                   fGen[1])

            if tensorInds not in self.dicToFill:
                self.dicToFill[tensorInds] = coupling * coeff
            else:
                self.dicToFill[tensorInds] += coupling * coeff

            #Update the 'AllCouplings' dictionary
            if type(self.model.allCouplings[str(coupling)]) != tuple:
                tmp = [cType, coupling]

                if isinstance(coupling, mSymbol):
                    orderedFermions = [
                        str(list(self.model.allFermions.values())[f][1])
                        for f in fermions
                    ]
                    tmp.append(tuple(orderedFermions))

                self.model.allCouplings[str(coupling)] = tuple(tmp)

            # If Yukawa / Fermion mass, add the hermitian conjugate to Dic
            if content == (2, 1) or content == (2, 0):
                antiFermions = [self.antiFermionPos(f) for f in fermions]
                antiFermions.reverse()
                tensorInds = tuple(scalars + antiFermions + [True])
                coeff = conjugate(coeff)
                adjCoupling = Adjoint(coupling).doit()

                if tensorInds not in self.dicToFill:
                    self.dicToFill[tensorInds] = adjCoupling * coeff
                else:
                    self.dicToFill[tensorInds] += adjCoupling * coeff
Пример #6
0
    def parseExpression(self, expr, name=None, expandedTerm=None):
        """ This function handles the convertion from str to TensorObject of
        lagrangian expressions written by the user in the model file.
        As much as possible, the user input is validated and error messages
        are printed if needed."""

        originalExpr = expr
        errorExpr = (name +
                     ' : ' if name is not None else '') + str(originalExpr)

        ##########
        # Case 1 : expr is a representation matrix
        ##########

        if expr[:2].lower() == 't(':
            args = expr[2:-1]
            gp = args.split(',')[0]

            if gp + ',' not in args:
                loggingCritical(
                    f"\nError : representation matrix {expr} should have exactly two arguments : group and rep"
                )
                exit()
            rep = eval(args.replace(gp + ',', ''))

            if gp in self.model.gaugeGroups:
                gp = self.model.gaugeGroups[gp]
            else:
                for gName, g in self.model.gaugeGroups.items():
                    if g.type == gp:
                        gp = g
                        break
                if type(gp) == str:
                    loggingCritical(
                        f"\nError in 'Definitions': gauge group '{gp}' is unknown."
                    )
                    exit()

            # DimR -> Dynkin labels
            if isinstance(rep, int):
                rep = self.idb.get(gp.type, 'dynkinLabels', rep)

            repMats = gp.repMat(tuple(rep))

            shape = tuple([len(repMats), *repMats[0].shape])
            dic = {}
            for i, mat in enumerate(repMats):
                for k, v in mat._smat.items():
                    dic[(i, *k)] = v

            # This is for latex output
            expr = Function('t')(Symbol(gp.type), Symbol(str(rep)))

            return TensorObject(copy=(name, shape, dic),
                                fromDef=name,
                                expr=expr)

        ##########
        # Case 2 : expr is a CGC
        ##########

        if expr[:4].lower() == 'cgc(':
            args = expr[4:-1].split(',')

            # Read the gauge group
            gp = args[0]
            args = args[1:]

            # Collect lists together
            i = 0
            while i < len(args):
                o = args[i].count('[') + args[i].count('(') + args[i].count(
                    '{')
                c = args[i].count(']') + args[i].count(')') + args[i].count(
                    '}')
                if o > c:
                    args[i] = args[i] + ', ' + args[i + 1]
                    args.pop(i + 1)
                else:
                    i += 1

            # Read the fields
            fields = []
            for i, el in enumerate(args):
                if el.isnumeric() or ('(' in el and ')' in el):
                    # Stop after encountering an int or a tuple
                    i -= 1
                    break
                fields.append(el)
            args = args[i + 1:]

            # Determine which syntax was used
            if gp in self.model.gaugeGroups and all(
                [el in self.model.Particles for el in fields]):
                fieldNames = fields
            elif gp in [gp.type for gp in self.model.gaugeGroupsList] and all(
                [el not in self.model.Particles for el in fields]):
                fieldNames = []
            else:
                loggingCritical(
                    "\nError : CGC syntax is 'cgc(groupName, field1, field2 [, field3 [, field4, [CGC number]]])' or "
                    +
                    "cgc(group, dynkins1, dynkins2 [, dynkins3 [, dynkins4, [CGC number]]]). The group and particles must be defined above."
                )
                loggingCritical(
                    f"Please rewrite the term '{name}: {expr}' accordingly.")
                exit()

            N = 0
            # The CGC call contains a pos
            if args != []:
                if len(args) == 1:
                    N = int(args[0]) - 1
                else:
                    loggingCritical(
                        f"\nError in {name}: {expr} ; too much arguments to cgc() function."
                    )
                    exit()
                if N < 0:
                    loggingCritical(
                        f"\nError in {name}: {expr} ; the position argument must be a non-zero positive integer."
                    )
                    exit()

            if not isinstance(N, int):
                loggingCritical(
                    f"\nError in CGC '{name}: {expr}' : position argument must be an integer."
                )
                exit()

            if fieldNames != []:
                gpName, gType = gp, self.model.gaugeGroups[gp].type
                reps = [self.model.Particles[p].Qnb[gpName] for p in fields]
            else:
                gType, reps = gp, [eval(labels) for labels in fields]

            cgc = self.idb.get(gType,
                               'invariants',
                               reps,
                               pyrateNormalization=True,
                               realBasis=GaugeGroup.realBasis)

            if len(cgc) == 0:
                loggingCritical(
                    f"Error: no invariant can be formed from the reps provided in '{name}'."
                )
                exit()
            if N > len(cgc) - 1:
                loggingCritical(
                    f"\nError in {name}: {expr} ; the position argument cannot be larger than {len(cgc)} here."
                )
                exit()

            result = cgc[N]

            shape = result.dim[:result.rank]
            dic = {}
            for k, v in result.dic.items():
                dic[k[:result.rank]] = v

            # This is for latex output
            expr = Function('cgc')(Symbol(gType),
                                   *([Symbol(el) for el in fields] + [N]))

            return TensorObject(copy=(name, shape, dic),
                                fromDef=name,
                                expr=expr,
                                fields=fieldNames)

        ##########
        # Case 3 : an expression involving the already defined quantities
        ##########
        localDict = {}

        count = 0
        expr = expr.replace('sqrt', '#').replace('Sqrt', '#')
        for k, v in sorted(self.definitions.items(), key=lambda x: -len(x[0])):
            expr = expr.replace(k, f'@_{count}_')
            localDict[f'symb_{count}_'] = v.symbol
            count += 1
        expr = expr.replace('@', 'symb')
        expr = expr.replace('#', 'sqrt')

        def sympyParse(expr):
            if '^' in expr:
                loggingCritical(
                    f"\nError in expression '{errorExpr}' : powers must be written using the '**' operator"
                )
                exit()
            return parse_expr(expr,
                              local_dict=localDict,
                              transformations=standard_transformations[1:] +
                              (implicit_multiplication, ),
                              evaluate=False)

        # A) Replacements to format the expr string
        expr = expr.replace(']', '] ').strip()
        expr = expr.replace(' +',
                            '+').replace(' -',
                                         '-').replace(' *',
                                                      '*').replace(' /', '/')
        expr = expr.replace(' )', ')')
        expr = expr.replace('] ', ']*')

        for k, v in localDict.items():
            if isinstance(v, Symbol):
                expr = expr.replace(k, k + ' ')

        # B) Parse the string
        try:
            expr = sympyParse(expr)
        except:
            loggingCritical(f"\nError while parsing the term '{errorExpr}'.")
            exit()

        rep = {}
        if expr.find(Pow) != set():
            # Now we want to expand the term, keeping any form (a*b)**2 unexpanded
            a, b, c = [Wild(x, exclude=(1, )) for x in 'abc']
            rep = expr.replace((a * b)**c,
                               lambda a, b, c: (a * b)**Symbol('n_' + str(c)),
                               map=True)

        if rep == {} or rep[1] == {}:
            termList = expand(expr).as_coeff_add()[1]
        else:
            termList = expand(rep[0], power_base=False).as_coeff_add()[1]

        # C) Parse the left hand side of the definition (if given)
        Linds = []
        if name is not None:
            if '[' in name and ']' in name:
                Lbase = name[:name.find('[')]
                Linds = name[name.find('[') + 1:name.find(']')].split(',')
                Linds = [Symbol(el) for el in Linds]

        # D) Validate and compute the expression
        rhsResult = 0
        commonFreeInds = None

        for term in termList:
            split = splitPow(term)

            rationalFactors = [el for el in split if el.is_number]
            terms = tuple([el for el in split if el not in rationalFactors])
            coeff = Mul(*rationalFactors)

            # Handle expr**N now
            newTerms = []
            for subTerm in terms:
                if isinstance(subTerm, Pow):
                    base, exp = subTerm.base, subTerm.exp
                    if isinstance(exp, Symbol):
                        exp = int(exp.name[2:])
                    indexed = base.find(Indexed)

                    if indexed != set():
                        indices = flatten([el.indices for el in indexed])

                        indCopies = {}
                        for i in indices:
                            if i not in indCopies:
                                indCopies[i] = [
                                    Symbol(str(i) + f'_{p}')
                                    for p in range(1, exp)
                                ]

                    else:
                        indCopies = {}
                    newTerms.append(base)
                    for p in range(0, exp - 1):
                        sub = {i: copy[p] for i, copy in indCopies.items()}
                        newTerms.append(base.subs(sub))
                else:
                    newTerms.append(subTerm)

            terms = []
            for subTerm in newTerms:
                if isinstance(subTerm, Mul) or isinstance(subTerm, Pow):
                    tmp = splitPow(subTerm)
                    for el in tmp:
                        if not el.is_number:
                            terms.append(el)
                        else:
                            coeff *= el
                else:
                    if not subTerm.is_number:
                        terms.append(subTerm)
                    else:
                        coeff *= subTerm

            if expandedTerm is not None:
                if expandedTerm == []:
                    expandedTerm.append(Mul(coeff, *terms, evaluate=False))
                else:
                    expandedTerm[0] += Mul(coeff, *terms, evaluate=False)

            inds = []
            indRanges = {}
            for i, field in enumerate(terms):
                if isinstance(field, Symbol):
                    continue
                try:
                    fieldInds = field.indices
                except AttributeError:
                    loggingCritical(
                        f"\nError (in term '{expr}') while reading the quantity '{field}'. It seems that indices are missing."
                    )
                    exit()

                fieldDef = self.definitions[str(field.base)]
                if fieldDef.dim is not None and len(fieldInds) != fieldDef.dim:
                    loggingCritical(
                        f"\nError (in term '{expr}'): the quantity {field.base} should carry exactly {fieldDef.dim} indices"
                    )
                    exit()

                inds += list(fieldInds)
                for p, ind in enumerate(field.indices):
                    indRanges[ind] = (fieldDef, p)

            freeInds = []
            for ind in set(inds):
                count = inds.count(ind)
                if count == 1:
                    freeInds.append(ind)
                if count > 2:
                    loggingCritical(
                        f"\nError: in term '{term}', the index '{ind}' appears more than twice."
                    )
                    exit()

            if commonFreeInds is None:
                commonFreeInds = freeInds
            elif freeInds != commonFreeInds:
                loggingCritical(
                    f"\nError : each term of the sum '{expr}' must contain the same free indices."
                )
                exit()
            if name is not None and set(freeInds) != set(Linds):
                loggingCritical(
                    f"\nError in term {term}: there should be {len(set(Linds))} free indices"
                    + (' -> ' +
                       str(tuple(set(Linds))) if set(Linds) != set() else ''))
                exit()

            # Now that the term is validated, construct the resulting tensor object
            contractArgs = []
            for field in terms:
                if not isinstance(field, Symbol):
                    base, inds = field.base, field.indices
                else:
                    base, inds = field, []

                tens = self.definitions[str(base)]
                tens.update(len(inds))

                inds = [Wild(str(el)) for el in inds]
                contractArgs.append(tens(*inds))

            freeDummies = [Wild(str(el)) for el in Linds]
            tmp = tensorContract(*contractArgs,
                                 value=coeff,
                                 freeDummies=freeDummies,
                                 doit=True)

            if not isinstance(tmp, dict):
                tmp = expand(tmp)

            if rhsResult == 0:
                rhsResult = tmp
            else:
                if not isinstance(rhsResult, dict):
                    rhsResult += tmp
                else:
                    for k, v in tmp.items():
                        v = expand(v)
                        if k in rhsResult:
                            rhsResult[k] += v
                        else:
                            rhsResult = k

                        if rhsResult[k] == 0:
                            del rhsResult[k]

        if not isinstance(rhsResult, dict):
            return TensorObject(copy=('' if name is None else name, (), {
                (): rhsResult
            }),
                                fromDef=name,
                                expr=expr)

        ranges = []

        for freeInd in Linds:
            iRange = indRanges[freeInd]
            iRange = iRange[0].range[iRange[1]]
            ranges.append(iRange)

        try:
            return TensorObject(copy=(Lbase, ranges, rhsResult),
                                fromDef=name,
                                expr=expr)
        except:
            loggingCritical(
                f"\nError while parsing the term '{errorExpr}': please check the consistency of contracted indices."
            )
            exit()
Пример #7
0
    def prepareRGEs(self, model):
        """ Gather all the terms of the RGES by coupling type and by value of the numerical coeff """
        self.indexCount = 0

        def wCoeff(coeff):
            return reg.sub(r'(?<!\*\*)(\d+)', r'\1.', str(coeff),
                           1).replace('pi', 'cmath.pi')

        def wSymb(symb):
            s = str(symb)
            if 'conjugate' in s:
                return 'cc(P.' + s[10:]
            return 'P.' + s

        def listToString(l):
            return '[' + (wSymb(l[0]) if len(l) > 0 else '') + (
                ', ' + ','.join([wSymb(el)
                                 for el in l[1:]]) if len(l) > 1 else '') + ']'

        for cType, loopDic in model.couplingRGEs.items():
            if 'Anomalous' in cType:
                continue

            if cType not in self.RGEsByValue:
                self.RGEsByValue[cType] = {}

            for nLoop, RGEdic in loopDic.items():
                for c, RGE in RGEdic.items():
                    RGE = expand(RGE / self.betaFactor * self.kappa(nLoop + 1))
                    termsAdd = RGE.as_coeff_add()[1]

                    for term in termsAdd:
                        symbs = []
                        mats = []
                        traces = []
                        coeff = 1

                        for el in splitPow(term.args):
                            if not el.is_commutative:
                                mats.append(el)
                            elif isinstance(el, Trace):
                                traces.append(el)
                            elif not el.is_number:
                                symbs.append(el)
                            else:
                                coeff *= el

                        coeff = wCoeff(simplify(coeff))
                        if coeff not in self.RGEsByValue[cType]:
                            self.RGEsByValue[cType][coeff] = []

                        if mats == traces == []:
                            self.RGEsByValue[cType][coeff].append(
                                listToString([c] + symbs))
                        else:
                            (pre, symbs, post
                             ), inds, ranges, cjs = self.buildIndexStructure(
                                 c, coeff, mats, traces, symbs)
                            self.RGEsByValue[cType][coeff].append(
                                '*generateYukTerm([' + listToString(pre) +
                                ', ' + str(symbs) + ', ' + listToString(post) +
                                ']' + ', ' + str(inds) + ', ' + str(ranges) +
                                (', ' + str(cjs) if cjs != () else '') + ')')
Пример #8
0
    def parseLagTerm(self, model, cType, cSymb, expr):
        if isinstance(expr, Add):
            return Mul(cSymb, Add(*[self.parseLagTerm(model, cType, 1, el) for el in expr.args], evaluate=False), evaluate=False)

        def split(term):
            noInds = str(term)[:str(term).find('[')] if str(term).find('[') != -1 else str(term)
            inds = str(term).replace(noInds, '')

            if inds == '':
                inds = []
            else:
                inds = eval(inds.replace('[', "['").replace(',', "','").replace(']',"']"))
            return (noInds, inds)

        def sortKey(x):
            sp = split(x)
            return (sp[0] not in model.lagrangian.cgcs, sp[1], (0 if 'bar' in str(x) else 1), sp[0])


        args = []
        levi = []
        coeff = 1

        for el in splitPow(expr, deep=True):
            if el.is_number:
                coeff *= el
            elif isinstance(el, LeviCivita):
                levi.append(el)
            else:
                args.append(el)

        base1, base2 = None, None

        # Workaround for (x^\dagger)**2 x**2 -> (x^\dagger x)**2
        # + Workaround for  x^\dagger x^\dagger x x -> (x^\dagger x)**2
        if (len(args) == 2 and isinstance(args[0], Pow) and args[0].args[1] == 2
                           and isinstance(args[1], Pow) and args[1].args[1] == 2):
            base1, base2 = sorted([str(args[0].args[0]), str(args[1].args[0])])
        if (lambda a: len(a) == 4 and a[0] == a[1] and a[2] == a[3])(sorted(args, key=lambda x:str(x))):
            sArgs = sorted(args, key=lambda x: str(x))
            base1, base2 = str(sArgs[1]), str(sArgs[2])

        if base1 is not None and base2 is not None:
            if base2 == base1+'bar':
                if cSymb != 1:
                    new = Symbol(str(cSymb), commutative=False)
                if cSymb in self.latex and new not in self.latex:
                    self.latex[new] = self.latex[cSymb]
                    cSymb = new
                else:
                    cSymb = new

                ret = (Symbol(base2, commutative=False)*Symbol(base1, commutative=False))**2

                if Symbol(base1) in self.latex and Symbol(base1, commutative=False) not in self.latex:
                    self.latex[Symbol(base1, commutative=False)] = self.latex[Symbol(base1)]
                if Symbol(base2) in self.latex and Symbol(base2, commutative=False) not in self.latex:
                    self.latex[Symbol(base2, commutative=False)] = self.latex[Symbol(base2)]

                if coeff*cSymb != 1:
                    return coeff*cSymb*ret

                return ret


        if isinstance(cSymb, mSymbol):
            newArgs = [0 for _ in range(len(args))]
            fermions = list(model.allCouplings[str(cSymb)][2])

            # Possibly replace f^2 by [f,f] in the list of args (e.g. majorana fermions)
            args = splitPow(args)
            newArgs = [0,0]
            scalar = 0

            remain = []
            # Add generation indices to fermions and sort as [fermion1, scalar, fermion2]
            for el in args:
                splitEl = split(el)

                if splitEl[0] in fermions:
                    fCount = fermions.index(splitEl[0]) + 1
                    pos = fermions.index(splitEl[0])

                    el = IndexedBase(splitEl[0]).__getitem__(('f'+str(fCount), *splitEl[1]))

                    newArgs[pos] = el
                    fermions[pos] = 0
                else:
                    if isinstance(el, Indexed):
                        base = el.base
                    else:
                        base = el

                    if str(base) in model.Particles:
                        scalar = el
                    else:
                        remain.append(el)

            if scalar != 0:
                newArgs.insert(1, scalar)

            newArgs = remain + newArgs

            if cSymb in self.latex:
                cSymb = Symbol(str(self.latex[cSymb]) + '{}_{f_1,f_2}', commutative=False)
            else:
                cSymb = Symbol(str(cSymb) + '{}_{f_1,f_2}', commutative=False)
        else:
            newArgs = sorted(args, key=sortKey)

            if cSymb != 1:
                new = Symbol(str(cSymb), commutative=False)
                if cSymb in self.latex and new not in self.latex:
                    self.latex[new] = self.latex[cSymb]
                    cSymb = new
                else:
                    cSymb = new

        for el in levi:
            for p, obj in enumerate(newArgs):
                if el.args[1] in obj.args:
                    pos = p
                    break
            newArgs.insert(pos, el)

        if coeff*cSymb != 1:
            return Mul(coeff*cSymb, *newArgs, evaluate=False)
        else:
            return Mul(*newArgs, evaluate=False)