Exemplo n.º 1
0
    def __init__(self, wd):
        self.wd = wd

        # Load the default settings from 'default.settings' file
        settings = self.loadDefaultSettings()

        # Load the settings from user command
        runSettings = self.initParser(settings)

        # Combine the two dicts
        for k,v in runSettings.items():
            settings[k] = v

        if os.path.abspath(settings['Results']) != settings['Results']:
            settings['Results'] = os.path.abspath(os.path.join(wd, settings['Results']))
        if not (os.path.exists(settings['Results'])):
            os.makedirs(settings['Results'])

        if settings['ForceLog']:
            settings['LogFolder'] = 'log/'

        if os.path.abspath(settings['LogFolder']) != settings['LogFolder']:
            settings['LogFolder'] = os.path.abspath(os.path.join(wd, settings['LogFolder']))
        if not (os.path.exists(settings['LogFolder'])):
            os.makedirs(settings['LogFolder'])

        self.initLogging(settings)

        # A useful check before going on : no export was selected
        if not any((settings['LatexOutput'], settings['MathematicaOutput'], settings['PythonOutput'], settings['UFOfolder'])):
            loggingCritical("Error : No ouput would be produced after the computation. Please choose at least one export option (Latex, Mathematica, Python, UFO).")
            exit()

        if settings['UFOfolder'] is not None:
            if os.path.abspath(settings['UFOfolder']) != settings['UFOfolder']:
                settings['UFOfolder'] = os.path.abspath(os.path.join(wd, settings['UFOfolder']))
            if not (os.path.exists(settings['UFOfolder'])):
                os.makedirs(settings['UFOfolder'])

        if 'RealBasis' in settings and type(settings['RealBasis']) == str:
            settings['RealBasis'] = settings['RealBasis'].lower()
            if settings['RealBasis'] in ('none', 'true', 'false'):
                settings['RealBasis'] = eval(settings['RealBasis'].capitalize())
            elif settings['RealBasis'] not in ('adjoint', 'all'):
                loggingInfo("Warning : RealBasis argument not understood. Setting it to 'adjoint'.")
                settings['RealBasis'] = 'adjoint'

        if 'MoreGroupTheoryInfo' in settings:
            if settings['MoreGroupTheoryInfo'] is True:
                settings['MoreGroupTheoryInfo'] = 10
            elif settings['MoreGroupTheoryInfo'] is False:
                settings['MoreGroupTheoryInfo'] = 0
            elif type(settings['MoreGroupTheoryInfo']) != int:
                loggingInfo("Warning : 'MoreGroupTheoryInfo' setting must be a boolean or a positive integer. Setting it to False.")
                settings['MoreGroupTheoryInfo'] = 0
        else:
            settings['MoreGroupTheoryInfo'] = 0

        self.yamlSettings = self.readModelFile(settings)
        self.settings = settings
Exemplo n.º 2
0
    def Beta(self, *args, nLoops=1):

        # Possibly store the result of the computation. This is useful to
        # speed up the computation in presence of kinetic mixing
        storeAfter = False
        if self.store:
            key = tuple([*args, nLoops])
            if key in self.storeDic:
                return self.storeDic[key]
            storeAfter = True

        ret = 0
        for j, coeff in enumerate(self.coefficients[nLoops]):
            if coeff != 0:
                try:
                    tmp = self.functions[nLoops][j](*args)
                    if tmp != 0:
                        if ret == 0:
                            ret = coeff * tmp
                        else:
                            ret += coeff * tmp
                except BaseException as e:
                    loggingCritical(
                        f"## Error while computing {self.functions[nLoops][j].__name__}. ##"
                    )
                    loggingCritical('>> ' + str(e))
                    exit()

        if storeAfter:
            self.storeDic[key] = ret

        return ret
Exemplo n.º 3
0
    def couplingsDefinition(self, model):
        s = ""

        substitutedCouplings = [
            str(k) for subDic in model.substitutions.values() for k in subDic
        ]

        for cType in model.toCalculate:
            if 'Anomalous' in cType:
                continue

            self.cDic[cType] = {}
            for k, v in model.allCouplings.items():
                if v[0] == cType and k not in substitutedCouplings:
                    # The conjugated couplings are removed, and must be replaced by Conjugate[ ... ]
                    if not k[-2:] == '^*' and not k[-4:] == '^{*}' and not k[
                            -4:] == 'star':
                        self.cDic[cType][v[1]] = pycode(v[1]).replace(
                            '{', '').replace('}', '')
                        self.allCouplings[k] = pycode(v[1]).replace(
                            '{', '').replace('}', '')
                    else:
                        candidates = [
                            el for el in model.allCouplings
                            if el in k and el != k
                        ]
                        if len(candidates) == 1:
                            self.conjugatedCouplings[k] = candidates[0]
                        else:
                            lengths = [len(el) for el in candidates]
                            i, maxLen = lengths.index(
                                max(lengths)), max(lengths)
                            lengths.remove(maxLen)

                            if maxLen not in lengths:
                                self.conjugatedCouplings[k] = candidates[i]
                            else:
                                loggingCritical(
                                    f"Warning in Python export: could not determine the conjugate quantity of {k} automatically."
                                    +
                                    "\n -> The user will have to modify the output Python file manually."
                                )

            s += f"\n\n        # {self.translation[cType]}"

            if cType == 'Vevs' and model.gaugeFixing is None:
                s += "\n        #   For vevs the gauge must be fixed. Let's use for instance the Landau gauge :\n"
                s += "        self.xiGauge = 0\n"
                self.gaugeFixing = True

            for c, cName in self.cDic[cType].items():
                s += f"\n        self.{cName} = Coupling('{cName}', '{cType}'"
                if cName in self.latex:
                    s += ", latex='" + self.latex[cName].replace(
                        '\\', '\\\\').replace("'", "\\'") + "'"
                if isinstance(c, mSymbol):
                    s += ', shape=' + str(c.shape).replace(' ', '')
                s += ')'

        return s
Exemplo n.º 4
0
    def UFOsubstitutions(self, model, inconsistentRGEerror=True):
        """ Transform the UFO mapping dict into substitutions, and apply them to the RGEs """

        subsDic = {}
        yukMats = {}

        for k, v in self.mapping.items():
            if not '[' in k and not ']' in k:
                subsDic[k] = v
            else:
                # Handle Yukawa-matrix assumptions
                base = k[:k.find('[')]
                inds = eval(k.replace(base, ''))

                if base not in yukMats:
                    if base not in self.couplingStructure:
                        loggingCritical(
                            f"Error : coupling matrix '{base}' is unknown.")
                        continue
                    yukMats[base] = (self.couplingStructure[base], {})

                if v != '0':
                    yukMats[base][1][tuple(inds)] = v

        for k, (shape, dic) in yukMats.items():
            matList = [[
                dic[(i, j)] if (i, j) in dic else 0 for j in range(shape[1])
            ] for i in range(shape[0])]
            subsDic[k] = str(matList).replace("\\'", "'")

        subsDic = getSubstitutions(model, subsDic)
        doSubstitutions(model,
                        subsDic,
                        inconsistentRGEerror=inconsistentRGEerror)
Exemplo n.º 5
0
    def __new__(cls,
                *args,
                symmetric=False,
                hermitian=False,
                real=False,
                unitary=False):
        if args[1] != args[2]:
            if symmetric or hermitian or unitary:
                loggingCritical(
                    "Matrix <" + args[0] +
                    "> cannot be symmetric, hermitian or unitary since it is not a square matrix."
                )
                exit()

        if not args[1] == args[2] == 1:
            obj = Symbol.__new__(cls,
                                 args[0],
                                 commutative=False,
                                 hermitian=hermitian)
            obj.is_symmetric = symmetric
            obj.is_realMatrix = real
            obj.is_unitary = unitary
        else:
            obj = Symbol.__new__(cls, args[0], real=real)
        obj.shape = (args[1], args[2])
        return obj
Exemplo n.º 6
0
    def pseudoScalarHandling(self, allScalars, scalarPos):
        gNabelList = [
            gName for gName, g in self.groups.items()
            if self.Qnb[gName] != 0 and g.dimR(self.Qnb[gName]) > 1
        ]

        self.pseudoRanges = [el[3] for el in self.pseudoRealReps]
        self.pseudoRepsPos = [
            gNabelList.index(el[0]) for el in self.pseudoRealReps
        ]
        self.pseudoRealReps = [(el[0], el[2]) for el in self.pseudoRealReps]

        # First, check that a solution to X = pseudoRealConjugate(X) = C.X exists
        C = sMat([[1, 0], [0, -1]])

        for gName in gNabelList:
            g = self.groups[gName]
            rep = self.Qnb[gName]

            if (gName, rep) in self.pseudoRealReps:
                m = self.idb.get(g.type, '_pseudoMetric', rep)
            else:
                m = eye(g.dimR(rep))

            C = C.kroneckerProduct(m)

        N = C.shape[0]
        ns = (eye(N) - C).nullSpace()

        if ns == {}:
            loggingCritical(
                f"Error: real scalar '{self._name}' cannot be self-conjugate.")
            exit()

        nsMat = sMat(N, N // 2)
        for r, rowDic in ns.items():
            for c, v in rowDic.items():
                nsMat[c, r] = v * self.pseudoNorm

        self.pseudoNS = nsMat
        self.pseudoNSadj = 1 / (self.pseudoNorm**2 * 2) * nsMat.adjoint()
        pseudoTransfo = eye(N // 2).append(I * eye(N // 2), axis=1) * nsMat

        self.pseudoTransfo = {}
        for k, v in pseudoTransfo.todok().items():
            if k[0] not in self.pseudoTransfo:
                self.pseudoTransfo[k[0]] = {}
            self.pseudoTransfo[k[0]][k[1]] = v

        def computeExpr(inds, symb):
            res = 0

            for k, v in self.pseudoTransfo[flattenedTensorPos(
                    self.indexStructure, inds)].items():
                res += v * symb[flattenedTensorInds(self.indexStructure, k)]

            return res

        self.computeComponents = computeExpr
Exemplo n.º 7
0
    def expandLagrangian(self, RGmodule):
        self.lagrangian = Lagrangian(self.saveSettings, self, RGmodule)
        loggingInfo("Done.")

        loggingInfo("Expanding the Lagrangian ...")
        self.lagrangian.expand()

        self.expandedPotential = self.lagrangian.expandedPotential

        # Read the substitutions now
        self.substitutions = {}
        self.gutNorm = {}
        if 'Substitutions' in self.saveSettings and self.saveSettings[
                'Substitutions'] != {}:
            self.substitutions = getSubstitutions(
                self, self.saveSettings['Substitutions']
                if 'Substitutions' in self.saveSettings else {})

        # If any matrix substitution is provided, check now that the shapes correspond.
        # This is to prevent the computation from starting if not.
        # Also, if the matrix satisfies Y = Diag(y), replace it by y*Identity(nG)

        if 'yukMat' in self.substitutions:
            for k, v in self.substitutions['yukMat'].items():
                shape = tuple([
                    el for el in self.couplingStructure[k] if type(el) != bool
                ])

                if not isinstance(v[1], DiagonalMatrix):
                    if v[1].shape != shape:
                        loggingCritical("Error : The shape of the matrix " +
                                        k + " given in Substitutions" +
                                        " should be " + str(shape))
                        exit()
                else:
                    if shape[0] != shape[1]:
                        loggingCritical(
                            "Error in Substitutions : the 'diag' keyword cannot be used for"
                            + " the rectangular matrix '" + k + "'")
                        exit()

                    cType, diagMat = self.substitutions['yukMat'][k]
                    self.substitutions['yukMat'][k] = (cType, diagMat.arg *
                                                       Identity(shape[0]))

        # VeVs
        if self.vevs != {}:
            for k, v in self.vevs.items():
                RGmodule.Vdic[(v[0], )] = v[1]

        # Anomalous dimensions
        if self.fermionAnomalous != {}:
            for k, v in self.fermionAnomalous.items():
                RGmodule.gammaFdic[v] = k

        if self.scalarAnomalous != {}:
            for k, v in self.scalarAnomalous.items():
                RGmodule.gammaSdic[v] = k
Exemplo n.º 8
0
 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)
Exemplo n.º 9
0
    def expand(self):
        """ Performs a first level of expansion of the Lagrangian. More precisely, replaces
        all the occurences of user-defined quantities with their expression."""
        def isComplex(cType, c, expTerm):
            return (cType in ('QuarticTerms', 'TrilinearTerms', 'ScalarMasses')
                    and c + 'star' not in self.potential[cType] and
                    not (c[-4:] == 'star' and c[:-4] in self.potential[cType])
                    and expTerm.find(I) != set())

        count = 0
        content = ()
        for couplingType, terms in self.potential.items():
            if couplingType in self.translateContent:
                self.dicToFill = self.translateDic(self.RGmodule)[couplingType]
                content = self.translateContent[couplingType]
                self.currentPotentialDic = self.potential[couplingType]
            else:
                continue

            for coupling, term in list(terms.items()):
                TensorObject.globalTensorCount = 1
                parsedTerm = []

                try:
                    expTerm = self.parseExpression(
                        term, expandedTerm=parsedTerm).dic[()]
                except BaseException as e:
                    loggingCritical(
                        f"\nError while expanding the term '{coupling}':")
                    loggingCritical(f" -> {str(e)}")
                    exit()

                self.expandedPotential[couplingType][coupling] = parsedTerm[0]
                self.fullyExpandedPotential[couplingType][coupling] = expTerm

                self.fillTensorDic(coupling, expTerm, content)

                if isComplex(couplingType, coupling, expTerm):
                    self.conjugateScalarTerm(couplingType, coupling, content)
                    count += 1

                count += 1
                print_progress(count,
                               self.model.nCouplings,
                               prefix=' ' * 4,
                               bar_length=20,
                               printTime=self.model.times,
                               logProgress=True)

            # Finally, remove all vanishing elements from dict
            for k, v in list(self.dicToFill.items()):
                if v == 0:
                    self.dicToFill.pop(k)
Exemplo n.º 10
0
    def getDefinitions(self, settings):
        #######################
        # Pre-Defined objects #
        #######################

        preDefinedObjects = {}

        # #Kronecker delta
        preDefinedObjects['kd'] = TensorObject("kd")

        # #Eps tensors
        preDefinedObjects['Eps'] = TensorObject("Eps")

        self.definitions.update(preDefinedObjects)

        #############
        # Particles #
        #############

        particleTensors = {}
        for name, p in self.model.Particles.items():
            particleTensors[name] = TensorObject(p)

            # Self-conjugate scalars have a complex conjugate counterpart
            if p.pseudoRealReps != []:
                particleTensors[name + 'bar'] = TensorObject(p).getConjugate()

        self.definitions.update(particleTensors)

        ########################
        # User-defined objects #
        ########################

        if 'Definitions' in settings[
                'Potential'] and settings['Potential']['Definitions'] != {}:
            for k, v in settings['Potential']['Definitions'].items():
                obj = self.parseExpression(v, name=k)

                if obj is not None:
                    self.definitions[str(obj.symbol)] = obj

                    if str(type(obj.expr)) == 'cgc':
                        self.cgcs[str(obj.symbol)] = obj

                    if str(type(obj.expr)) == 't':
                        self.definitions[str(obj.symbol) +
                                         'bar'] = obj.getConjugate()
                else:
                    loggingCritical(
                        f"Warning : unable to read the definition '{k}: {v}'. Skipping."
                    )
Exemplo n.º 11
0
    def getQnb(self, dic, gaugeGroups):
        """Get the Qnbs of the particle from the dic. The only thing to do is to transform the DimR notation into DynkinLabels"""

        for k,v in dic.items():
            g = gaugeGroups[k]

            if isinstance(v, str):
                if not g.abelian:
                    loggingCritical(f"Error while reading particle {self.name} : for non-abelian " +
                                    "gauge factors, quantum number must be integers or dynkin labels.")
                    exit()

                v = parse_expr(v.replace('i','I').replace('Sqrt','sqrt'))

            if isinstance(v, list):
                v = tuple(v)
            if not isinstance(v, tuple) and not g.abelian:
                dynk = tuple(self.idb.get(g.type, 'dynkinLabels', v, realBasis=GaugeGroup.realBasis))
                if type(dynk[0]) == list:
                    loggingCritical(f"Error : more than one representation of the group {g.type} have dimension {dynk} :")
                    loggingCritical(' -> ' + ', '.join([str(el) for el in dynk[:-1]]) + ' and ' + str(dynk[-1]))
                    loggingCritical("Please use the Dynkin-labels notation instead to remove the ambihuity.")
                    exit()

                v = dynk

            dic[k] = v

        return dic
Exemplo n.º 12
0
    def as_explicit(self, applyFunc=None):
        if self.shape == (1, 1):
            return self

        if isinstance(self.shape[0], Symbol) or isinstance(
                self.shape[1], Symbol):
            loggingCritical(
                "Error : a Matrix with symbolic number of generations as rows and/or columns cannot be given as an explicit matrix."
            )
            exit()

        mat = SparseMatrix(*self.shape, {})

        for i in range(self.shape[0]):
            for j in range(self.shape[1]):
                assump = {}
                if self.is_realMatrix or (self.is_hermitian and i == j):
                    assump['real'] = True
                else:
                    assump['complex'] = True

                if i == j and self.is_antisymmetric:
                    mat[i, j] = 0
                elif i <= j:
                    mat[i, j] = Symbol(
                        '{' + str(self) + '}_{' + str(i + 1) + str(j + 1) +
                        '}', **assump)
                else:
                    if self.is_symmetric:
                        mat[i, j] = mat[j, i]
                    elif self.is_antisymmetric:
                        mat[i, j] = -1 * mat[j, i]
                    elif self.is_hermitian:
                        mat[i, j] = conjugate(mat[j, i])
                    else:
                        mat[i, j] = Symbol(
                            '{' + str(self) + '}_{' + str(i + 1) + str(j + 1) +
                            '}', **assump)

        if applyFunc is None:
            return Matrix(mat)

        # The following case is needed in Python export
        retList = mat.tolist()
        for i, row in enumerate(retList):
            for j, el in enumerate(row):
                retList[i][j] = applyFunc(el)

        return retList
Exemplo n.º 13
0
    def getAssumptions(self):
        for cType, terms in self.potential.items():
            if cType == 'Definitions':
                continue

            newKeys = []
            for k, v in terms.items():
                assumptions = {}
                invalidAssumptions = []

                if cType == 'ScalarMasses':
                    assumptions = {'squared': False}
                    if type(v) != tuple:
                        v = (v, )

                if type(v) == tuple:
                    if 'real' in v:
                        assumptions['real'] = True
                    if 'symmetric' in v:
                        assumptions['symmetric'] = True
                    if 'hermitian' in v:
                        assumptions['hermitian'] = True
                    if 'unitary' in v:
                        assumptions['unitary'] = True

                    if cType == 'ScalarMasses':
                        if 'squared' in v:
                            assumptions['squared'] = True

                    invalidAssumptions = [
                        el for el in v[1:] if el not in assumptions
                    ]

                if assumptions != {} or invalidAssumptions != []:
                    self.potential[cType][k] = v[0]

                    for el in invalidAssumptions:
                        loggingCritical("Warning : assumption '" + el +
                                        "' is not understood. Ignoring it.")

                self.assumptions[k] = assumptions
                newKeys.append(k)
            self.potential[cType] = {
                k: v
                for k, v in zip(newKeys, terms.values())
            }
Exemplo n.º 14
0
 def initFromString(self, s):
     if s.lower() == 'kd':
         # Kronecker delta
         self.symbol = IndexedBase('KD')
         self.dic = None
         self.range = None
         self.dim = None
         self.sym = False
     elif s.lower() == 'eps':
         # Kronecker delta
         self.symbol = IndexedBase('Eps')
         self.dic = None
         self.range = None
         self.dim = None
         self.sym = False
     else:
         loggingCritical("Error : Unkown tensor object '{s}'.")
         return
Exemplo n.º 15
0
def checkDependencies():
    from Logging import loggingCritical, loggingInfo

    dep = checkDependenciesAux(requirements)

    if dep[0] is False:
        ex = False
        if dep[1] != []:
            mess = 'Error: some dependencies are missing/outdated.\n' + '\n'.join(
                dep[1])
            loggingCritical(mess)
            ex = True

        if dep[2] != []:
            mess = 'Warning: some optional dependencies are missing/outdated.\n' + '\n'.join(
                dep[2])
            loggingInfo(mess)

        if ex:
            exit()
Exemplo n.º 16
0
    def mapBetaFunctions(self):
        loggingInfo("Re-combining the RGES ...")

        #This is for progress bar
        nTot = 0
        count = 0
        for couplingType, RGlist in self.allRGEs.items():
            nTot += len(
                self.potential[couplingType]) * self.loopDic[couplingType]

        for couplingType, RGloops in self.allRGEs.items():
            mat = self.lagrangianMapping[couplingType]
            for n, RGlist in RGloops.items():
                couplingRGEs = mat * Matrix(RGlist)

                # Take into account the beta-exponent
                expFactor = 1
                if 'Anomalous' not in couplingType:
                    exponent = self.betaExponent(n + 1) - 2 * (n + 1)
                    if exponent != 0:
                        expFactor = Pow(4 * pi, exponent)

                for pos, coupling in enumerate(
                        list(self.potential[couplingType])):
                    try:
                        self.couplingRGEs[couplingType][n][coupling] = expand(
                            couplingRGEs[pos] * expFactor)
                    except BaseException as e:
                        loggingCritical(
                            f"Error expanding term at : {couplingType}, {n}, {pos}"
                        )
                        loggingCritical(e)
                        exit()
                    count += 1
                    print_progress(count,
                                   nTot,
                                   prefix='    ',
                                   bar_length=20,
                                   printTime=self.times)
Exemplo n.º 17
0
    def getVevs(self, settings):
        if 'Vevs' in settings and settings['Vevs'] != {}:
            for k, v in settings['Vevs'].items():
                if '[' in v and ']' in v:
                    try:
                        field = v[:v.find('[')]
                        inds = eval('(' + v[v.find('[') + 1:v.find(']')] +
                                    ',)')
                    except:
                        loggingCritical("Error while reading the vev '" + k +
                                        "'. Skipping.")
                        continue
                else:
                    field = v
                    inds = tuple()

                if field not in self.Scalars:
                    loggingCritical("Error while reading the vev '" + k +
                                    "' : scalar '" + field +
                                    "' is unkown. Skipping")
                    continue

                field = self.Scalars[field]
                ni = len(field.indexStructure)

                if len(inds) != ni or any([
                        i < 1 or i > field.indexStructure[pos]
                        for pos, i in enumerate(inds)
                ]):
                    loggingCritical("Error while reading the vev '" + k +
                                    "' : " + "scalar '" + str(field) +
                                    "' should have exactly " + str(ni) +
                                    (" indices with ranges "
                                     if ni > 1 else " index with range ") +
                                    str(field.indexStructure) + ". Skipping")
                    continue

                vSymb = Symbol(k, real=True)
                inds = tuple([i - 1 for i in inds])

                scalarStr = str(field)
                if inds != tuple():
                    scalarStr += str(inds).replace('(', '[').replace(
                        ')', ']').replace(',]', ']')

                # Now determine whether the scalar is a real/imaginary part of a cplx field
                fromCplx = field.fromCplx

                if fromCplx != False:
                    part = fromCplx.realFields.index(field)
                    self.vevs[k] = (self.allScalars[scalarStr][0], vSymb,
                                    scalarStr, fromCplx, part)
                else:
                    self.vevs[k] = (self.allScalars[scalarStr][0], vSymb,
                                    scalarStr)
Exemplo n.º 18
0
    def write(self, path):
        tmpDir = os.getcwd()

        if not os.path.exists(os.path.join(path, 'PythonOuput')):
            os.makedirs(os.path.join(path, 'PythonOuput'))

        # First : write the Python solver module
        fileName = os.path.join(path, 'PythonOuput', self._Name + '.py')
        try:
            self.file = open(fileName, 'w')
        except:
            loggingCritical(
                'ERROR while creating the Python output file. Skipping.')
            return

        self.file.write(self.string)
        self.file.close()

        # Then, create the file containing the expression of the beta-functions
        fileName = os.path.join(path, 'PythonOuput', 'RGEs.py')
        try:
            self.file = open(fileName, 'w')
            self.file.write(self.RGEfileString())
        except:
            loggingCritical(
                'ERROR while creating the Python RGE file. Skipping.')
            return
        self.file.close()

        # Finally create and write the run.py file
        os.chdir(os.path.join(path, 'PythonOuput'))
        self.runString(self.model, os.path.join(path, 'PythonOuput'))
        os.chdir(tmpDir)

        fileName = os.path.join(path, 'PythonOuput', 'run.py')
        try:
            self.file = open(fileName, 'w')
            self.file.write(self.stringRun)
        except:
            loggingCritical(
                'ERROR while creating the Python run file. Skipping.')
            return

        self.file.close()
Exemplo n.º 19
0
    def write(self, path):
        self.storePath = path

        if not os.path.exists(os.path.join(path, 'PythonOutput')):
            os.makedirs(os.path.join(path, 'PythonOutput'))

        # First : write the C++ solver file
        fileName = os.path.join(path, 'PythonOutput', self._Name + '.cpp')
        try:
            self.file = open(fileName, 'w')
        except:
            loggingCritical(
                'ERROR while creating the C++ output file. Skipping.')
            return

        self.file.write(self.allStr)
        self.file.close()

        # Then, create the makefile
        fileName = os.path.join(path, 'PythonOutput', 'Makefile')
        try:
            self.file = open(fileName, 'w')
            self.file.write(self.makeFileString())
        except:
            loggingCritical('ERROR while creating the Makefile. Skipping.')
            return
        self.file.close()

        # Optional: write the light Cpp output
        if self.lightSolver:
            fileName = os.path.join(self.lightSolver, 'RGEsolver.cpp')
            try:
                self.file = open(fileName, 'w')
            except:
                loggingCritical(
                    'ERROR while creating the light C++ output file. Skipping.'
                )
                return

            self.file.write(self.lallStr)
            self.file.close()
Exemplo n.º 20
0
    def RGEs(self, model, anomalous):
        sec = '1.' if not anomalous else '1.A)'
        s = f"(* ::Subsection:: *)\n(*{sec} RGEs*)\n\n"

        if self.inconsistentRGset:
            s += """(* ::Text:: *)
(*< WARNING : > The RGE set  is inconsistent. Please refer to the .tex output to solve this.*)\n\n"""

        exponent = mathematica(model.betaExponent(Symbol('i')))
        s += f"""(* \\[Beta]-function definition *)

\\[Beta][x_] := {mathematica(1/self.betaFactor)}*Sum[If[With[{{j=i}}, ValueQ[\\[Beta][x, j]]] && (!ValueQ[loops[x]] || i <= loops[x]),  1/(4 Pi)^({exponent})*\[Beta][x,i], 0], {{i,{max(model.loopDic.values())}}}]*Log[10];\n"""

        substitutedCouplings = [str(k) for subDic in model.substitutions.values() for k in subDic]

        for cType in model.toCalculate:
            if 'Anomalous' in cType:
                continue

            cDic = {}
            for k,v in model.allCouplings.items():
                if v[0] == cType and k not in substitutedCouplings:
                    # The conjugated couplings are removed, and must be replaced by Conjugate[ ... ]
                    if not k[-2:] == '^*' and not k[-4:] == '^{*}' and not k[-4:] == 'star':
                        cDic[k] = mathematica(v[1])
                    else:
                        candidates = [el for el in model.allCouplings if el in k and el != k]
                        if len(candidates) == 1:
                            self.conjugatedCouplings[k] = candidates[0]
                        else:
                            lengths = [len(el) for el in candidates]
                            i, maxLen = lengths.index(max(lengths)), max(lengths)
                            lengths.remove(maxLen)

                            if maxLen not in lengths:
                                self.conjugatedCouplings[k] = candidates[i]
                            else:
                                loggingCritical(f"Warning in Mathematica export: could not determine the conjugate quantity of {k} automatically." +
                                                "\n -> The user will have to modify the output Mathematica file manually.")

            s += f"\n\n(* {self.translation[cType]} *)\n\n{self.cListNames[cType]} = "
            s += '{' + ', '.join([c for c in cDic.values()]) + '};\n'

            if model.allRGEs[cType] == {}:
                continue

            if cType == 'Vevs':
                if model.gaugeFixing is None:
                    s += "\n(* For vevs the gauge must be fixed. Let's use for instance the Landau gauge : *)\n"
                    s += "xiGauge = 0;\n"
                else:
                    s += "\n(* Gauge fixing *)\n"
                    s += f"xiGauge = {mathematica(model.gaugeFixing)};\n"


            self.allCouplings[cType] = []
            for nLoop, RGEdic in model.couplingRGEs[cType].items():

                RGEdic = {v:RGEdic[k] for k,v in cDic.items() if k in RGEdic}
                for k, RGE in RGEdic.items():
                    s += '\n\\[Beta][' + k + f', {nLoop+1}] = '
                    betaFunc = mathematica(RGE, k in self.couplingStructure)

                    # Yukawa singlet workaround : take the trace of the beta-function if needed
                    if k in self.couplingStructure and self.couplingStructure[k] == (1,1) and 'Dot[' in betaFunc:
                        s += 'Tr[' + betaFunc + '];'
                    else:
                        s += betaFunc + ';'

                    if k not in self.allCouplings[cType]:
                        self.allCouplings[cType].append(k)

                s += '\n'

        self.string += s
Exemplo n.º 21
0
    def readModelFile(self, RunSettings):
        if RunSettings['Model'] == '':
            loggingCritical(
                "Error : Please, specify a .model file (using '-m' argument).")
            exit()
        else:
            if os.path.abspath(RunSettings['Model']) != RunSettings['Model']:
                RunSettings['Model'] = os.path.abspath(
                    os.path.join(self.wd, RunSettings['Model']))
            try:
                # Open the Yaml file and load the settings
                f = open(RunSettings['Model'], 'r')
                RunSettings['StoreModelFile'] = f.read()
                f.close()

                fString = self.parseFile(RunSettings['StoreModelFile'])
                if yaml.__version__ > '5.1':
                    yamlSettings = yaml.load(fString, Loader=yaml.FullLoader)
                else:
                    yamlSettings = yaml.load(fString)
            except yaml.scanner.ScannerError as err:
                loggingCritical(
                    f"Check the YAML file {RunSettings['Model']}, impossible to load the settings:\n\n-> {err}."
                )
                exit()
            except yaml.parser.ParserError as err:
                loggingCritical(
                    f"Check the YAML file {RunSettings['Model']}, impossible to parse the settings:\n\n->{err}."
                )
                exit()
            except IOError as errstr:
                loggingCritical(
                    f"Did not find the YAML file {RunSettings['Model']}, specify the path if not in the current directory.\n\n-> {errstr}."
                )
                exit()

            loggingInfo(f"Loading the YAML file: {RunSettings['Model']} ...",
                        end=' ')

            # Now we want to process the settings before creating the model class
            # Let's first construct the dictionaries if the input is given as a list

            if 'Fermions' in yamlSettings and yamlSettings['Fermions'] != {}:
                for k, v in yamlSettings['Fermions'].items():
                    if type(v) == dict:
                        continue
                    elif type(v) == list:
                        if len(v) == len(yamlSettings['Groups']) + 1:
                            qnb = {
                                grp: Q
                                for (grp,
                                     Q) in zip(yamlSettings['Groups'], v[1:])
                            }
                            yamlSettings['Fermions'][k] = {
                                'Gen': v[0],
                                'Qnb': qnb
                            }
                        else:
                            loggingCritical(
                                f"Error : The length of the lists describing fermions should be 1 + {len(yamlSettings['Groups'])}, "
                                +
                                f"corresponding to generation + various quantum numbers. ('{k} : {v}')"
                            )
                            exit()
                    else:
                        loggingCritical(
                            f"Error : Fermions should either be described by a dictionary or a list. ('{k} : {v}')"
                        )
                        exit()

            if 'RealScalars' in yamlSettings and yamlSettings[
                    'RealScalars'] != {}:
                for k, v in yamlSettings['RealScalars'].items():
                    if type(v) == dict:
                        if len(v) == 1 and 'Qnb' in v:
                            yamlSettings['RealScalars'][k] = v['Qnb']
                    elif type(v) == list:
                        if len(v) == len(yamlSettings['Groups']):
                            qnb = {
                                grp: Q
                                for (grp, Q) in zip(yamlSettings['Groups'], v)
                            }
                            yamlSettings['RealScalars'][k] = qnb
                        else:
                            loggingCritical(
                                f"Error : The length of the lists describing real scalars should be {len(yamlSettings['Groups'])}, "
                                +
                                f"corresponding to the various quantum numbers. ('{k} : {v}')"
                            )
                            exit()
                    else:
                        loggingCritical(
                            f"Error : Real scalars should either be described by a dictionary or a list. ('{k} : {v}')"
                        )
                        exit()

            # For complex scalars, also check that the pairs [Pi, Sigma] are only used once
            if 'CplxScalars' in yamlSettings and 'ComplexScalars' not in yamlSettings:
                yamlSettings['ComplexScalars'] = yamlSettings['CplxScalars']
            if 'ComplexScalars' in yamlSettings and yamlSettings[
                    'ComplexScalars'] != {}:
                realFieldsDic = {}
                for k, v in yamlSettings['ComplexScalars'].items():
                    if type(v) == dict:
                        pass
                    elif type(v) == list:
                        if len(v) == len(yamlSettings['Groups']) + 3:
                            qnb = {
                                grp: Q
                                for (grp,
                                     Q) in zip(yamlSettings['Groups'], v[3:])
                            }
                            yamlSettings['ComplexScalars'][k] = {
                                'RealFields': [v[0], v[1]],
                                'Norm': v[2],
                                'Qnb': qnb
                            }
                        else:
                            loggingCritical(
                                f"Error : The length of the lists describing complex scalars should be 3 + {len(yamlSettings['Groups'])}, "
                                +
                                f"corresponding to Re + Im + norm + various quantum numbers. ('{k} : {v}')"
                            )
                            exit()
                    else:
                        loggingCritical(
                            f"Error : Complex scalars should either be described by a dictionary or a list. ('{k} : {v}')"
                        )
                        exit()

                    rf = tuple(yamlSettings['ComplexScalars'][k]['RealFields'])
                    if rf not in realFieldsDic:
                        realFieldsDic[rf] = k
                    else:
                        loggingCritical(
                            f"Error in complex scalar '{k}' : the real fields couple {rf} is already used in '{realFieldsDic[rf]}'"
                        )
                        exit()

            if 'Potential' in yamlSettings and yamlSettings['Potential'] != {}:
                labels = ('QuarticTerms', 'Yukawas', 'TrilinearTerms',
                          'ScalarMasses', 'FermionMasses')
                for cType in labels:
                    if cType in yamlSettings['Potential'] and yamlSettings[
                            'Potential'][cType] != {}:
                        for coupling, term in yamlSettings['Potential'][
                                cType].items():
                            if type(term) == str:
                                # This is an explicit math expression
                                pass
                            elif type(term) == dict:
                                # This is a dict with no values, containing :
                                #    { 'mathExpression', assumption1, assumption2, ... }
                                tup = list(term.keys())
                                if len(tup) > 1:
                                    tup = tuple([tup[0]] +
                                                [el.lower() for el in tup[1:]])
                                else:
                                    tup = tup[0]
                                yamlSettings['Potential'][cType][
                                    coupling] = tup
                            else:
                                loggingCritical(
                                    f"Could not understand the term : {term}")
                                exit()

        loggingInfo("Done.")
        return yamlSettings
Exemplo n.º 22
0
    def validateSettings(self, settings, runSettings):
        """Implements the different checks carried out on the input provided by the user"""

        ########################################
        # Check the gauge groups and particles #
        ########################################

        if not 'Groups' in settings:
            loggingCritical("Error : No gauge groups specified. Exiting.")
            exit()
        else:
            groups = settings['Groups'].keys()

        allParticles = {}

        if 'Fermions' in settings and settings['Fermions'] != {}:
            for k, v in settings['Fermions'].items():
                if k not in allParticles:
                    allParticles[k] = v
                else:
                    loggingCritical(
                        f"Error : Particle '{k}' cannot be defined twice. Please check the model file."
                    )
                    exit()
        if 'RealScalars' in settings:
            for k, v in settings['RealScalars'].items():
                if k not in allParticles:
                    allParticles[k] = v
                else:
                    loggingCritical(
                        f"Error : Particle '{k}' cannot be defined twice. Please check the model file."
                    )
                    exit()
        if 'ComplexScalars' in settings:
            for k, v in settings['ComplexScalars'].items():
                twice = []

                for f in v['RealFields']:
                    if '*' in f or '+' in f or '-' in f:
                        loggingCritical(
                            f"Error : Invalid field name '{f}' in RealScalars of particle '{k}'. Exiting"
                        )
                        exit()
                    if f in allParticles:
                        twice.append(f)
                    else:
                        allParticles[f] = None

                if k in allParticles:
                    twice.append(k)

                if twice != []:
                    for el in twice:
                        loggingCritical(
                            f"Error : Particle '{el}' cannot be defined twice. Please check the model file."
                        )
                    exit()

                allParticles[k] = v

        # Check that all the gauge groups are defined above
        for part, val in allParticles.items():
            if val is None:
                continue
            if 'Qnb' in val:
                tags = val['Qnb'].keys()
            else:
                tags = val.keys()
            if not all([el in groups for el in tags]):
                loggingCritical(
                    f"Error : the particle '{part}' is charged under an unknown gauge group."
                )
                exit()
        if not 'Potential' in settings:
            settings['Potential'] = {}
            self.saveSettings['Potential'] = {}

        ################
        # RUN settings #
        ################

        if 'Loops' in runSettings:
            maxLoops = {
                'GaugeCouplings': 3,
                'Yukawas': 2,
                'QuarticTerms': 2,
                'TrilinearTerms': 2,
                'ScalarMasses': 2,
                'FermionMasses': 2,
                'Vevs': 2
            }

            if type(runSettings['Loops']
                    ) == str and runSettings['Loops'].lower() == 'max':
                loops = 'max'
            else:
                try:
                    loops = eval(str(runSettings['Loops']))
                except:
                    loops = str(runSettings['Loops'])

            if type(loops) == int:
                self.nLoops = 7 * [loops]

                self.loopDic['GaugeCouplings'] = self.nLoops[0]
                self.loopDic['Yukawas'] = self.nLoops[1]
                self.loopDic['QuarticTerms'] = self.nLoops[2]

                self.loopDic['TrilinearTerms'] = self.nLoops[3]
                self.loopDic['ScalarMasses'] = self.nLoops[4]
                self.loopDic['FermionMasses'] = self.nLoops[5]

                self.loopDic['Vevs'] = self.nLoops[6]

            elif type(loops) == list and len(loops) == 3:
                self.nLoops = loops

                self.loopDic['GaugeCouplings'] = self.nLoops[0]
                self.loopDic['Yukawas'] = self.nLoops[1]
                self.loopDic['QuarticTerms'] = self.nLoops[2]

                self.loopDic['FermionMasses'] = self.loopDic['Yukawas']
                self.loopDic['TrilinearTerms'] = self.loopDic['QuarticTerms']
                self.loopDic['ScalarMasses'] = self.loopDic['QuarticTerms']

                self.loopDic['Vevs'] = self.loopDic['QuarticTerms']

            # elif type(loops) == list and len(loops) == 6:
            #     self.nLoops = loops

            #     self.loopDic['GaugeCouplings'] = self.nLoops[0]
            #     self.loopDic['Yukawas'] = self.nLoops[1]
            #     self.loopDic['QuarticTerms'] = self.nLoops[2]

            #     self.loopDic['TrilinearTerms'] = self.nLoops[3]
            #     self.loopDic['ScalarMasses'] = self.nLoops[4]
            #     self.loopDic['FermionMasses'] = self.nLoops[5]

            #     self.loopDic['Vevs'] = self.loopDic['QuarticTerms']

            # elif type(loops) == list and len(loops) == 7:
            #     self.nLoops = loops

            #     self.loopDic['GaugeCouplings'] = self.nLoops[0]
            #     self.loopDic['Yukawas'] = self.nLoops[1]
            #     self.loopDic['QuarticTerms'] = self.nLoops[2]

            #     self.loopDic['TrilinearTerms'] = self.nLoops[3]
            #     self.loopDic['ScalarMasses'] = self.nLoops[4]
            #     self.loopDic['FermionMasses'] = self.nLoops[5]

            #     self.loopDic['Vevs'] = self.nLoops[6]
            elif type(loops) == str and loops == 'max':
                self.nLoops = []
                for k, v in maxLoops.items():
                    self.nLoops.append(v)
                    self.loopDic[k] = v
            else:
                loggingCritical(
                    "Error : Loops should be in one of the following forms :\n"
                    + "\t- A single integer\n" +
                    # "\t- A list of three, six or seven integers\n" +
                    "\t- A list of three integers\n" + "\t- The keyword 'max'")
                exit()

            # Nothing to calculate ?
            if all([el == 0 for el in self.nLoops]):
                loggingCritical("Nothing to calculate ! Exiting.")
                exit()

            # If loop orders are too high, set them to the max allowed value
            for k, v in maxLoops.items():
                if self.loopDic[k] > v:
                    loggingInfo(
                        f"Warning : Loop level for '{k}' is too high ({self.loopDic[k]}). Setting it to {v}"
                    )
                    self.loopDic[k] = v

            # Anomalous
            self.loopDic['ScalarAnomalous'] = self.loopDic['QuarticTerms']
            self.loopDic['FermionAnomalous'] = self.loopDic['Yukawas']
Exemplo n.º 23
0
def exports(runSettings, model):
    loggingInfo("Exporting results...")

    tmpWD = os.getcwd()
    # Create a folder with the name of the model
    if runSettings['CreateFolder'] is True:
        path = os.path.join(runSettings['Results'], model._Name)
        if not (os.path.exists(path)):
            os.makedirs(path)
    else:
        path = runSettings['Results']

    if runSettings['LatexOutput'] is True:
        from Latex import LatexExport

        loggingInfo("\tExporting to Latex...", end=' ')
        latex = LatexExport(model)
        latex.write(os.path.join(path, model._Name + '.tex'))
        loggingInfo("Done.")

    if runSettings['MathematicaOutput'] is True:
        from Mathematica import MathematicaExport

        loggingInfo("\tExporting to Mathematica...", end=' ')
        mathematica = MathematicaExport(model)
        mathematica.write(os.path.join(path, model._Name + '.m'))
        loggingInfo("Done.")

    if runSettings['PythonOutput'] is True:
        from Python import PythonExport

        # If Latex export is disabled, create a Latex object anyway
        # to get the latex substitutions
        if runSettings['LatexOutput'] is False:
            from Latex import LatexExport
            latex = LatexExport(model, getLatexSubs=True)

        loggingInfo("\tExporting to Python...", end=' ')
        try:
            python = PythonExport(model, latexSubs=latex.latex)
            python.write(path)
        except TypeError as e:
            print('\nError : ' + str(e))
        else:
            loggingInfo("Done.")

    if runSettings['UFOfolder'] is not None:
        from UFO import UFOExport

        loggingInfo("\tExporting to UFO...", end=' ')
        try:
            ufo = UFOExport(model)
            ufo.write(runSettings['UFOfolder'])
        except TypeError as e:
            loggingCritical("An error occurred during the UFO export : \n" +  str(e))
        else:
            loggingInfo("Done.")


    # Copy the .model file in the results folder
    if runSettings['CopyModelFile']:
        fName = os.path.join(path, os.path.basename(runSettings['Model']))
        s = "# This model file was automatically copied by PyR@TE 3 on " + time.ctime() + "\n"
        s += runSettings['StoreModelFile']
        try:
            f = open(fName, 'w')
            f.write(s)
            f.close()
        except:
            loggingCritical("Error while copying the model file in the results folder.")

    # Now apply possible user-defined commands from 'default.settings'
    commands = [cmd.strip() for cmd in runSettings['EndCommands'].replace('[name]', model._Name).split(',')]
    loggingInfo("Running user-defined commands : ")
    os.chdir(path)
    shell = (sys.platform.startswith('win'))
    for cmd in commands:
        loggingInfo("\t-> '" + cmd + "'")
        try:
            run(cmd.split(' '), shell=shell, stdout=DEVNULL, stderr=STDOUT, check=True)
        except CalledProcessError as e:
            loggingCritical("An error occurred when running the command. Skipping.")
            loggingCritical(' >> ' + str(e))

    os.chdir(tmpWD)

    # This is for debugging, remove later
    model.latex = latex
    # model.python = python
Exemplo n.º 24
0
    def __init__(self, settings, runSettings, idb, realBasis='all'):
        ###############
        # Definitions #
        ###############
        self._Name = settings['Name'].replace(' ', '_').replace('/',
                                                                '_').replace(
                                                                    '\\', '_')
        self._Author = settings['Author']
        self._Date = settings['Date']
        self.times = runSettings['PrintComputationTimes']
        self.saveSettings = copy.deepcopy(settings)
        self.runSettings = runSettings

        # Declare an interactive db access object
        self.idb = idb

        self.loopDic = {}

        self.validateSettings(settings, runSettings)

        loggingInfo("Loading the model ...", end=' ')

        ####################
        # Get gauge groups #
        ####################

        self.gaugeGroups = {}
        self.gaugeGroupsList = []
        self.UgaugeGroups = []

        self.realBasis = runSettings['RealBasis']
        self.getGaugegroups(settings, realBasis=self.realBasis)

        # Number of U1 gauge factors
        self.nU = [g.abelian for g in self.gaugeGroupsList].count(True)
        self.kinMix = (self.nU > 1 and runSettings['NoKinMix'] is False)

        #################
        # Get particles #
        #################

        self.Particles = {}
        self.Fermions = {}
        self.Scalars = {}
        self.ComplexScalars = {}

        #The following dicts contain all the components of the fields
        self.allFermions = {}
        self.allScalars = {}

        self.symbolicGen = False
        self.getParticles(settings)

        ######################
        # Read the potential #
        ######################

        self.potential = settings['Potential']
        self.assumptions = {}

        self.getAssumptions()

        #Read the vevs + possible gauge fixing
        self.vevs = {}
        self.getVevs(settings)

        self.gaugeFixing = None
        if 'GaugeParameter' in settings:
            self.gaugeFixing = self.parseMathExpr(settings['GaugeParameter'],
                                                  real=True)

        #Read the anomalous dimensions
        self.scalarAnomalous = {}
        self.fermionAnomalous = {}

        self.getAnomalous(settings)

        #Identify the various couplings of the model
        self.allCouplings = {}
        self.couplingsPos = {'GaugeCouplings': {}}
        self.YukPos = {}

        self.ExplicitMatrices = []

        self.couplingStructure = {}

        self.gaugeCouplings = []
        for i, gp in enumerate(self.gaugeGroupsList):
            self.allCouplings[str(gp.g)] = ('GaugeCouplings', gp.g)
            self.couplingsPos['GaugeCouplings'][str(gp.g)] = i
            self.gaugeCouplings.append(str(gp.g))

        self.mixedGaugeCouplings = []

        self.upper = True
        if self.kinMix:
            self.kinMat = zeros(self.nU)
            for i in range(self.nU):
                for j in range(self.nU):
                    if (self.upper and i < j) or (not self.upper and i > j):
                        c = 'g_' + str(i + 1) + str(j + 1)
                        pos = [
                            self.gaugeGroupsList.index(self.UgaugeGroups[k])
                            for k in (i, j)
                        ]
                        self.allCouplings[c] = ('GaugeCouplings',
                                                Symbol(c, real=True))
                        self.couplingsPos['GaugeCouplings'][c] = max(pos) + .5

                        self.kinMat[i, j] = Symbol(c, real=True)

                        self.mixedGaugeCouplings.append(self.kinMat[i, j])
                        self.gaugeCouplings.append(c)
                    elif i == j:
                        self.kinMat[i, j] = self.UgaugeGroups[i].g

            self.kinMat2 = self.kinMat * self.kinMat.transpose()

        # Fill the dics related to the various couplings of the model
        self.nCouplings = 0
        for couplingType, terms in self.potential.items():
            if couplingType == 'Definitions':
                continue
            tKeys = list(terms.keys())
            for coupling in terms:
                self.nCouplings += 1

                # Add the various couplings to the Couplings dictionnary
                if couplingType == 'Yukawas':
                    self.YukPos[coupling] = tKeys.index(coupling)
                if couplingType == 'FermionMasses':
                    self.YukPos[coupling] = 100 + tKeys.index(coupling)

                if couplingType not in self.couplingsPos:
                    self.couplingsPos[couplingType] = {}

                self.couplingsPos[couplingType][coupling] = tKeys.index(
                    coupling)

                self.allCouplings[coupling] = couplingType

        if self.vevs != {}:
            self.couplingsPos['Vevs'] = {}
            for i, (k, v) in enumerate(self.vevs.items()):
                self.allCouplings[k] = ('Vevs', v[1])
                self.couplingsPos['Vevs'][k] = i

        # Read the beta-factor
        if 'BetaFactor' in settings:
            if type(settings['BetaFactor']) not in (list, tuple):
                self.betaFactor = self.parseMathExpr(settings['BetaFactor'])
                self.betaExponent = lambda n: 2 * n
            else:
                self.betaFactor = self.parseMathExpr(settings['BetaFactor'][0])
                self.betaExponent = self.parseMathExpr(
                    settings['BetaFactor'][1])
                if self.betaExponent.find('n') == set():
                    if self.betaExponent == 0:
                        self.betaExponent = lambda n: 0
                    else:
                        loggingCritical(
                            "Error : the beta-exponent must be an integer function of 'n'. Setting it to default (2*n)."
                        )
                        self.betaExponent = lambda n: 2 * n
                else:
                    lambdaExponent = lambdify(Symbol('n'), self.betaExponent)
                    self.betaExponent = lambda n: lambdaExponent(n)
            if self.betaFactor == 0:
                loggingCritical("Error : beta-factor cannot be 0. Exiting.")
                exit()
        else:
            self.betaFactor = Integer(1)
            self.betaExponent = lambda n: Integer(2) * n

        self.translateContent = {
            'GaugeCouplings': (0, 0),
            'Yukawas': (2, 1),
            'QuarticTerms': (0, 4),
            'TrilinearTerms': (0, 3),
            'ScalarMasses': (0, 2),
            'FermionMasses': (2, 0),
            'FermionAnomalous': (2, 0),
            'ScalarAnomalous': (0, 2),
            'Vevs': (0, 1)
        }

        self.translateDic = lambda RGmodule: {
            'Yukawas': RGmodule.YDic,
            'QuarticTerms': RGmodule.LambdaDic,
            'TrilinearTerms': RGmodule.Hdic,
            'ScalarMasses': RGmodule.MSdic,
            'FermionMasses': RGmodule.MFdic,
            'FermionAnomalous': RGmodule.gammaFdic,
            'ScalarAnomalous': RGmodule.gammaSdic,
            'Vevs': RGmodule.Vdic
        }

        self.translateBetaFunction = {
            'GaugeCouplings': GaugeBetaFunction,
            'Yukawas': YukawaBetaFunction,
            'QuarticTerms': QuarticBetaFunction,
            'TrilinearTerms': TrilinearBetaFunction,
            'ScalarMasses': ScalarMassBetaFunction,
            'FermionMasses': FermionMassBetaFunction,
            'FermionAnomalous': FermionAnomalous,
            'ScalarAnomalous': ScalarAnomalous,
            'Vevs': VevBetaFunction
        }

        self.lagrangianMapping = {}
        self.toCalculate = {}

        self.RGclasses = {}
        self.allRGEs = {}
        self.couplingRGEs = {}

        self.NonZeroCouplingRGEs = {}
        self.NonZeroDiagRGEs = {}
Exemplo n.º 25
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
Exemplo n.º 26
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()
Exemplo n.º 27
0
    def getParticles(self, settings):
        def completeTrivialReps(dic):
            for k, v in self.gaugeGroups.items():
                if k not in dic['Qnb']:
                    if v.abelian:
                        dic['Qnb'][k] = 0
                    else:
                        dic['Qnb'][k] = 1

        for key, value in settings.items():
            if key == 'Fermions':
                self.Fermions = value
                antiFermions = {}
                # Create the particle and store it in Fermions
                for part, val in value.items():
                    completeTrivialReps(val)
                    self.Fermions[part] = Particle(part, val, self.gaugeGroups,
                                                   self.idb)
                    antiFermions[part +
                                 'bar'] = self.Fermions[part].antiParticle()

                self.Fermions.update(antiFermions)
            elif key == 'RealScalars':
                # Copy the particles in the class
                for part, qnb in value.items():
                    norm = None
                    if 'Norm' in qnb:
                        norm = self.parseMathExpr(qnb['Norm'])
                    if 'Qnb' not in qnb:
                        Qnb = {'Gen': 1, 'Qnb': qnb}
                    else:
                        Qnb = qnb

                    completeTrivialReps(Qnb)
                    self.Scalars[part] = Particle(part, Qnb, self.gaugeGroups,
                                                  self.idb)

                    # Now check that the representations are compatible with a real scalar
                    for gName, g in self.gaugeGroups.items():
                        if g.abelian and self.Scalars[part].Qnb[gName] != 0:
                            loggingCritical(
                                f"\nError: real scalar '{part}' cannot be charged under the abelian gauge factor {gName}"
                            )
                            exit()
                        if not g.abelian:
                            rep = self.Scalars[part].Qnb[gName]
                            dimR = g.dimR(rep)
                            if dimR == 1:
                                continue

                            fs = self.idb.get(g.type, 'frobenius', rep)

                            if fs == 1:
                                loggingCritical(
                                    f"\nError: real scalar '{part}' cannot transform under the complex representation '{dimR}' of {gName}"
                                )
                                exit()
                            elif fs == -1:
                                self.Scalars[part].pseudoRealReps.append(
                                    (gName, g, rep, dimR))

                    if self.Scalars[part].pseudoRealReps != []:
                        if norm is None:
                            loggingInfo(
                                f"Warning: self-conjugate scalar '{part}' should be given a norm. Assuming 1/sqrt(2) by default."
                            )
                            norm = 1 / sqrt(2)
                        self.Scalars[part].pseudoNorm = norm
                    elif norm is not None:
                        loggingInfo(
                            f"Warning: ignoring the unnecessary 'Norm' keyword in real scalar '{part}'."
                        )

            elif key == 'Potential':
                self.potential = value

        self.Particles.update(self.Fermions)
        self.Particles.update(self.Scalars)

        if 'ComplexScalars' in settings:
            for part, setts in settings['ComplexScalars'].items():
                setts['Norm'] = self.parseMathExpr(setts['Norm'])
                if 'Gen' not in setts:
                    setts['Gen'] = 1

                completeTrivialReps(setts)
                self.ComplexScalars[part] = ComplexScalar(
                    part, setts, self.gaugeGroups, self.idb)
                self.ComplexScalars[
                    part + 'bar'] = self.ComplexScalars[part].antiParticle()

                for r in self.ComplexScalars[part].realFields:
                    self.Scalars[str(r)] = r

        self.Particles.update(self.ComplexScalars)

        nF = 0
        for fName, f in self.Fermions.items():
            ranges = [r for r in f.indicesRange.values()]
            nonNullRanges = [r for r in ranges if r != 0]
            if nonNullRanges == []:  #Singlet
                tup = [nF, f, tuple([-1] * len(ranges))]
                nF += 1
                self.allFermions[fName] = tuple(tup)
            else:
                for el in itertools.product(
                        *[(list(range(r)) if r != 0 else [-1])
                          for r in ranges]):
                    tup = [
                        nF, f,
                        tuple(el),
                        parse_expr(str(fName) + str([n
                                                     for n in el if n != -1]),
                                   local_dict={
                                       str(f._name): IndexedBase(str(f._name))
                                   })
                    ]
                    nF += 1
                    self.allFermions[fName + str([n for n in el
                                                  if n != -1])] = tuple(tup)

        nS = 0
        for sName, s in self.Scalars.items():
            ranges = [r for r in s.indicesRange.values()]
            nonNullRanges = [r for r in ranges if r != 0]
            if nonNullRanges == []:  #Singlet
                self.allScalars[sName] = (nS, s, tuple([-1] * len(ranges)))
                nS += 1
            else:
                storeNs = nS
                for el in itertools.product(
                        *[(list(range(r)) if r != 0 else [-1])
                          for r in ranges]):
                    tup = [
                        nS, s,
                        tuple(el),
                        parse_expr(str(sName) + str([n
                                                     for n in el if n != -1]),
                                   local_dict={
                                       str(s._name): IndexedBase(str(s._name))
                                   })
                    ]
                    self.allScalars[sName +
                                    str([n
                                         for n in el if n != -1])] = tuple(tup)
                    nS += 1

                # If the real scalar transforms under pseudo-real reps, some more work is needed
                if s.pseudoRealReps != []:
                    s.pseudoScalarHandling(list(self.allScalars.items()),
                                           storeNs)

        self.symbolicGen = any(
            [isinstance(p.gen, Symbol) for p in self.Particles.values()])
Exemplo n.º 28
0
    def checkGaugeInvariance(self):
        loggingInfo("Checking gauge invariance ...", end=' ')
        t0 = time.time()

        # fermionGauge = tensorAdd(tensorContract(self.T(A_,i_,j_),
        #                                         self.T(B_,j_,k_),
        #                                         freeDummies=[A_,B_,i_,k_],
        #                                         doit=True) ,
        #                           tensorMul(-1, tensorContract(self.T(B_,i_,j_),
        #                                                       self.T(A_,j_,k_),
        #                                                       freeDummies=[A_,B_,i_,k_],
        #                                                       doit=True)) ,
        #                           tensorMul(-I, tensorContract(self.f(A_,B_,C_),
        #                                                       self.T(C_,i_,k_),
        #                                                       freeDummies=[A_,B_,i_,k_],
        #                                                       doit=True)))

        # scalarGauge = tensorAdd(tensorContract(self.Ts(A_,i_,j_),
        #                                         self.Ts(B_,j_,k_),
        #                                         freeDummies=[A_,B_,i_,k_],
        #                                         doit=True) ,
        #                         tensorMul(-1, tensorContract(self.Ts(B_,i_,j_),
        #                                                       self.Ts(A_,j_,k_),
        #                                                       freeDummies=[A_,B_,i_,k_],
        #                                                       doit=True)) ,
        #                         tensorMul(-I, tensorContract(self.f(A_,B_,C_),
        #                                                       self.Ts(C_,i_,k_),
        #                                                       freeDummies=[A_,B_,i_,k_],
        #                                                       doit=True)))

        # if fermionGauge != {}:
        #     loggingCritical("Basic Lie algebra commutation relations are not satisfied among fermions.\n"
        #                     +"Please contact the author.")
        #     exit()
        # if scalarGauge != {}:
        #     loggingCritical("Basic Lie algebra commutation relations are not satisfied among scalars.\n"
        #                     +"Please contact the author.")
        #     exit()

        yuk = tensorAdd(
            tensorMul(
                -1,
                tensorContract(self.Tt(A_, i_, j_),
                               self.y(a_, j_, k_),
                               freeDummies=[A_, a_, i_, k_],
                               doit=True)),
            tensorContract(self.y(a_, i_, j_),
                           self.T(A_, j_, k_),
                           freeDummies=[A_, a_, i_, k_],
                           doit=True),
            tensorContract(self.y(b_, i_, k_),
                           self.Ts(A_, b_, a_),
                           freeDummies=[A_, a_, i_, k_],
                           doit=True))

        fermionMass = tensorAdd(
            tensorMul(
                -1,
                tensorContract(self.Tt(A_, i_, j_),
                               self.M(j_, k_),
                               freeDummies=[A_, i_, k_],
                               doit=True)),
            tensorContract(self.M(i_, j_),
                           self.T(A_, j_, k_),
                           freeDummies=[A_, i_, k_],
                           doit=True))

        quartics = tensorAdd(
            tensorContract(self.Ts(A_, a_, e_),
                           self.l(e_, b_, c_, d_),
                           freeDummies=[A_, a_, b_, c_, d_],
                           doit=True),
            tensorContract(self.Ts(A_, b_, e_),
                           self.l(a_, e_, c_, d_),
                           freeDummies=[A_, a_, b_, c_, d_],
                           doit=True),
            tensorContract(self.Ts(A_, c_, e_),
                           self.l(a_, b_, e_, d_),
                           freeDummies=[A_, a_, b_, c_, d_],
                           doit=True),
            tensorContract(self.Ts(A_, d_, e_),
                           self.l(a_, b_, c_, e_),
                           freeDummies=[A_, a_, b_, c_, d_],
                           doit=True))

        trilinears = tensorAdd(
            tensorContract(self.Ts(A_, a_, e_),
                           self.h(e_, b_, c_),
                           freeDummies=[A_, a_, b_, c_],
                           doit=True),
            tensorContract(self.Ts(A_, b_, e_),
                           self.h(a_, e_, c_),
                           freeDummies=[A_, a_, b_, c_],
                           doit=True),
            tensorContract(self.Ts(A_, c_, e_),
                           self.h(a_, b_, e_),
                           freeDummies=[A_, a_, b_, c_],
                           doit=True))

        scalarMass = tensorAdd(
            tensorContract(self.Ts(A_, a_, e_),
                           self.mu(e_, b_),
                           freeDummies=[A_, a_, b_],
                           doit=True),
            tensorContract(self.Ts(A_, b_, e_),
                           self.mu(a_, e_),
                           freeDummies=[A_, a_, b_],
                           doit=True))

        def which(dic):
            problematicCouplings = {}
            for k, el in dic.items():
                names = [
                    obj for obj in el.atoms() if not obj.is_number
                    and not (hasattr(obj, 'is_Identity') and obj.is_Identity)
                ]
                for c in names:
                    if str(c) not in problematicCouplings:
                        problematicCouplings[str(c)] = set()
                    problematicCouplings[str(c)].add(k[0][0])

            return "\n\t" + "\n\t".join([
                str(k) + ' (' + ', '.join([
                    self.model.gaugeGroupsList[g].name for g in sorted(list(v))
                ]) + ')' for k, v in problematicCouplings.items()
            ])

        if yuk != {}:
            loggingCritical(
                "Gauge invariance is not satisfied by the following Yukawa couplings :"
                + which(yuk))
        if quartics != {}:
            loggingCritical(
                "Gauge invariance is not satisfied by the following quartic couplings :"
                + which(quartics))
        if fermionMass != {}:
            loggingCritical(
                "Gauge invariance is not satisfied by the following fermion mass couplings :"
                + which(fermionMass))
        if trilinears != {}:
            loggingCritical(
                "Gauge invariance is not satisfied by the following trilinear couplings :"
                + which(trilinears))
        if scalarMass != {}:
            loggingCritical(
                "Gauge invariance is not satisfied by the following scalar mass couplings :"
                + which(scalarMass))
        if any([
                el != {}
                for el in (yuk, quartics, fermionMass, trilinears, scalarMass)
        ]):
            exit()

        loggingInfo("All OK !" + (
            f" ({time.time()-t0:.3f} seconds)" if self.model.times else ''))
Exemplo n.º 29
0
    def getAnomalous(self, settings):
        allAnomalous = lambda dic: (len(dic) == 1 and 'All' in dic and dic[
            'All'] is None)

        if 'ScalarAnomalous' in settings and settings[
                'ScalarAnomalous'] != {} and self.loopDic[
                    'ScalarAnomalous'] > 0:
            sa = settings['ScalarAnomalous']

            if not allAnomalous(sa):
                for k in sa:
                    if not (k[0] == '(' and k[-1] == ')'):
                        loggingCritical(
                            "Warning in ScalarAnomalous : the correct syntax is '(scalar1, scalar2)'.\n\
                                         Please check the term '" +
                            k.replace(';', ', ') + "'. Skipping.")
                        continue

                    fields = k[1:-1].split(';')

                    if len(fields) != 2:
                        loggingCritical(
                            "Warning in ScalarAnomalous : the correct syntax is '(scalar1, scalar2)'.\n\
                                         Please check the term '" +
                            k.replace(';', ', ') + "'. Skipping.")
                        continue

                    skip = False
                    for i, f in enumerate(fields):
                        if '[' not in f:
                            continue

                        base = f[:f.find('[')]
                        inds = f[f.find('['):]

                        try:
                            inds = str([el - 1 for el in eval(inds)])
                            fields[i] = base + inds
                        except:
                            skip = "unable to read the term '" + k.replace(
                                ';', ', ') + "'"
                            break

                        if fields[i] not in self.allScalars:
                            skip = "in term '" + k.replace(
                                ';', ', ') + "', scalar '" + f + "' is unknown"
                            break

                    if skip:
                        loggingCritical("Warning in ScalarAnomalous : " +
                                        skip + ". Skipping.")
                        continue

                    key = [
                        self.allScalars[s][(3 if len(self.allScalars[s]) > 3
                                            else 1)] for s in fields
                    ]
                    key = tuple([(k if isinstance(k, Indexed) else k._name)
                                 for k in key])
                    val = tuple([self.allScalars[s][0] for s in fields])

                    self.scalarAnomalous[key] = val
            else:
                # All anomalous
                self.saveSettings['ScalarAnomalous'] = 'All'

                for i, s1 in enumerate(self.allScalars.values()):
                    for j, s2 in enumerate(self.allScalars.values()):
                        if i > j:
                            continue

                        key = [s[(3 if len(s) > 3 else 1)] for s in (s1, s2)]
                        key = tuple([(k if isinstance(k, Indexed) else k._name)
                                     for k in key])
                        val = tuple([s[0] for s in (s1, s2)])

                        self.scalarAnomalous[key] = val

        if 'FermionAnomalous' in settings and settings[
                'FermionAnomalous'] != {} and self.loopDic[
                    'FermionAnomalous'] > 0:
            fa = settings['FermionAnomalous']

            if not allAnomalous(fa):
                for k in fa:
                    if not (k[0] == '(' and k[-1] == ')'):
                        loggingCritical(
                            "Warning in FermionAnomalous : the correct syntax is '(fermion1, fermion2)'.\n\
                                         Please check the term '" +
                            k.replace(';', ', ') + "'. Skipping.")
                        continue

                    fields = k[1:-1].split(';')

                    if len(fields) != 2:
                        loggingCritical(
                            "Warning in FermionAnomalous : the correct syntax is '(fermion1, fermion2)'.\n\
                                         Please check the term '" +
                            k.replace(';', ', ') + "'. Skipping.")
                        continue

                    skip = False
                    for i, f in enumerate(fields):
                        if '[' not in f:
                            continue

                        base = f[:f.find('[')]
                        inds = f[f.find('['):]

                        try:
                            inds = str([el - 1 for el in eval(inds)])
                            fields[i] = base + inds
                        except:
                            skip = "unable to read the term '" + k.replace(
                                ';', ', ') + "'"
                            break

                        if fields[i] not in self.allFermions:
                            skip = "in term '" + k.replace(
                                ';',
                                ', ') + "', fermion '" + f + "' is unknown"
                            break

                    if skip:
                        loggingCritical("Warning in FermionAnomalous : " +
                                        skip + ". Skipping.")
                        continue

                    key = [
                        self.allFermions[f][(3 if len(self.allFermions[f]) > 3
                                             else 1)] for f in fields
                    ]
                    key = tuple([(k if isinstance(k, Indexed) else k._name)
                                 for k in key])
                    val = tuple([self.allFermions[f][0] for f in fields])

                    self.fermionAnomalous[key] = val
            else:
                # All anomalous
                self.saveSettings['FermionAnomalous'] = 'All'

                for i, f1 in enumerate(self.allFermions.values()):
                    if f1[1].conj:
                        continue
                    for j, f2 in enumerate(self.allFermions.values()):
                        if f2[1].conj or i > j:
                            continue

                        key = [f[(3 if len(f) > 3 else 1)] for f in (f1, f2)]
                        key = tuple([(k if isinstance(k, Indexed) else k._name)
                                     for k in key])
                        val = tuple([f[0] for f in (f1, f2)])

                        self.fermionAnomalous[key] = val
Exemplo n.º 30
0
    def constructMapping(self, RGmodule):
        loggingInfo("Mapping the model onto the general Lagrangian ...")

        #Gauge couplings mapping, taking into account possible kinetic mixing
        noMix = {}
        mix = {}
        alreadyTaken = set()

        for el in itertools.combinations_with_replacement(
                range(RGmodule.nGi), 2):
            A, B = [RGmodule.gi[i] for i in el]
            c = RGmodule.G_(A, B)
            if c != 0 and c not in alreadyTaken:
                dic = noMix if A == B else mix

                if not self.upper:
                    A, B = B, A

                dic[(A, B)] = len(dic)
                alreadyTaken.add(c)

        newInds = {**noMix, **{k: v + len(noMix) for k, v in mix.items()}}
        gaugeMatrix = zeros(len(newInds))

        def delta(A, B):
            if A == B:
                return 1
            return 0

        def G(A, B):
            if RGmodule.G_(A, B) == 0:
                return 0
            if not self.kinMix or A not in RGmodule.Ugauge or B not in RGmodule.Ugauge:
                return sqrt(RGmodule.G_(A, B)).args[0]

            i, j = RGmodule.Ugauge.index(A), RGmodule.Ugauge.index(B)
            return self.kinMat[i, j]

        for (A, B), X in newInds.items():
            for (C, D), Y in newInds.items():
                gaugeMatrix[X,
                            Y] = G(B, D) * delta(A, C) + G(A, D) * delta(B, C)

        gaugeMatrix = simplify(gaugeMatrix.inv())

        couplingType = 'GaugeCouplings'
        self.potential[couplingType] = {}
        for c in self.gaugeCouplings:
            self.potential[couplingType][c] = 0

        self.lagrangianMapping[couplingType] = gaugeMatrix * self.betaFactor
        self.toCalculate[couplingType] = list(newInds.keys())

        count = 0
        translation = self.translateDic(RGmodule)
        for couplingType in self.potential:
            if couplingType == 'Definitions':
                continue
            if (couplingType in translation
                    and self.potential[couplingType] != {}
                    and translation[couplingType] != {}):
                coeffList = [c for c in self.potential[couplingType].keys()]
                mappingMatrix = SparseMatrix(len(coeffList), len(coeffList), 0)
                dicList = []

                auxDic = {}
                sortFunc = lambda x: (len(set(x[0])),
                                      len(x[1].as_coeff_add()[1]), x[0])

                for key, val in translation[couplingType].items():
                    if key[-1] is True:
                        continue
                    if val not in auxDic:
                        auxDic[val] = key
                    elif sortFunc((key, val)) < sortFunc((auxDic[val], val)):
                        auxDic[val] = key

                rank = 0
                for v, k in auxDic.items():
                    matTry = self.fillMappingMatrix(mappingMatrix, rank,
                                                    coeffList, (k, v))
                    newRank = matTry.rank()
                    if (newRank > rank):
                        mappingMatrix = matTry
                        rank = newRank
                        dicList.append(k)

                        count += 1
                        print_progress(count,
                                       self.nCouplings,
                                       prefix=' ' * 4,
                                       bar_length=20,
                                       printTime=self.times,
                                       logProgress=True)

                    if newRank == len(coeffList):
                        self.lagrangianMapping[couplingType] = Matrix(
                            mappingMatrix).inv() * self.betaFactor
                        break
                else:
                    # The mapping matrix is not invertible
                    ns = mappingMatrix.nullspace()
                    cVec = Matrix([
                        Symbol('O(' + el + ')') for el in coeffList
                    ]).transpose()

                    errorMess = "\n\nError in Lagrangian mapping: matrix of couplings is not invertible. "
                    errorMess += f"The following operators in '{couplingType}' are linearly dependent:\n\n"
                    for vec in ns:
                        errorMess += f"  {(cVec*vec)[0,0]} = 0\n"
                    loggingCritical(errorMess[:-1])
                    exit()

                self.toCalculate[couplingType] = dicList

        # Add vevs and anomalous dimensions by hand (not related to the Lagrangian)
        if self.vevs != {}:
            couplingType = 'Vevs'

            self.potential[couplingType] = {}
            for c in self.vevs:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(len(
                self.vevs)) * self.betaFactor
            self.toCalculate[couplingType] = list(RGmodule.Vdic.keys())

        if self.fermionAnomalous != {}:
            couplingType = 'FermionAnomalous'

            self.potential[couplingType] = {}
            for c in self.fermionAnomalous:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(
                len(self.fermionAnomalous))
            self.toCalculate[couplingType] = list(RGmodule.gammaFdic.keys())

        if self.scalarAnomalous != {}:
            couplingType = 'ScalarAnomalous'

            self.potential[couplingType] = {}
            for c in self.scalarAnomalous:
                self.potential[couplingType][c] = 0
            self.lagrangianMapping[couplingType] = eye(
                len(self.scalarAnomalous))
            self.toCalculate[couplingType] = list(RGmodule.gammaSdic.keys())