From e882cd68ac4e7ca80f0f18f96d68360ea9792208 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 1 Nov 2016 20:43:15 +0100 Subject: [PATCH 001/158] Implemented CreateChargeGetters[] --- meta/EDM.m | 696 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 696 insertions(+) create mode 100644 meta/EDM.m diff --git a/meta/EDM.m b/meta/EDM.m new file mode 100644 index 000000000..8379254e8 --- /dev/null +++ b/meta/EDM.m @@ -0,0 +1,696 @@ +BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "LoopMasses`", "Vertices`"}]; + +Test::usage=""; + +SetEDMParticles::usage="Set the particles for which the EDMs shall be calculated."; + +CreateParticles::usage="Returns the c++ code that contains all particle classes"; +CreateEDMParticleFunctions::usage="Returns the c++ code that contains all EDM particle functions"; +CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; +CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; + +CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; + +CreateDefinitions::usage="Returns the c++ that contains all function definitions" + +NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; + +(******** IMPORTANT NOTES: + If you add new kinds of vertices (e.g for new diagram types): + - Add the new types to vertexTypes + - Expand CouplingsForParticles[] and VertexTypeForParticles[] accordingly + - Write the c++ class for the new vertex type + + When adding support for new diagram types, do the following: + - Add the new types to contributingFeynmanDiagramTypes + - Write new overloads for CreateDiagramEvaluatorClass[], ContributingDiagramsOfType[] and VerticesForDiagram[] + - Write the necessary c++ code: loop functions, DiagramEvaluator<> specialisations + **********) + +Test[] := Print["blablabla" <> ToString @ SARAH`InsFields[{{C[Fe, SARAH`FieldToInsert[1], VP]}}]]; + +Begin["`Private`"]; + +(************* Begin public interface *******************) + +edmParticles = Null; +SetEDMParticles[particles_List] := (edmParticles = particles); + +IsSMParticle[particle_] := + SARAH`SMQ[particle] || TreeMasses`IsSMGoldstone[particle]; + +CreateSMParticleFlags[particle_] := + Module[{result = "", i, + numberOfGenerations = TreeMasses`GetDimension[particle]}, + For[i = 1, i <= numberOfGenerations, i++, + If[i > 1, result = result <> ", ";]; + If[IsSMParticle[particle[i]] === True || + IsSMParticle[particle] === True, + result = result <> "true";, + result = result <> "false"; + ]; + ]; + "{ " <> result <> " }" + ]; + +(* Create c++ classes for all particles *) +CreateParticles[] := + Module[{particles, code}, + (* Get a list of all particles *) + particles = TreeMasses`GetParticles[]; + + code = ("// Particles (SARAH-style)\n" <> + "struct Particle {};\n\n" <> + + StringJoin @ Riffle[("struct " <> ParticleToCXXName[#] <> + ": public Particle {\n" <> + TextFormatting`IndentText[ + "static const unsigned numberOfGenerations = " <> + ToString @ TreeMasses`GetDimension[#] <> ";\n" <> + "static const bool is_sm_particle[numberOfGenerations];" + ] <> "\n};\n" <> + "const bool " <> ParticleToCXXName[#] <> "::is_sm_particle[" <> + ParticleToCXXName[#] <> "::numberOfGenerations] = " <> + CreateSMParticleFlags[#] <> ";\n" + &) /@ particles, "\n"] <> "\n\n" <> + "// Special particle families\n" <> + "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> + "typedef " <> ParticleToCXXName @ GetMuonFamily[] <> " MuonFamily;\n\n" <> + + "// AntiParticles\n" <> + "template struct anti : public Particle\n" <> + "{\n" <> + IndentText @ + ("static const unsigned numberOfGenerations = P::numberOfGenerations;\n" <> + "typedef anti

type;\n") <> + "};\n" <> + "template struct anti> { typedef P type; };\n\n" <> + + "// Particles that are their own antiparticles\n" <> + StringJoin @ Riffle[("template<> struct " <> + "anti<" <> ParticleToCXXName[#] <> ">" <> + " { typedef " <> ParticleToCXXName[#] <> " type; };" + &) /@ Select[particles, (# == AntiParticle[#] &)], + "\n"] + ); + + Return[code]; + ]; + +CreateChargeGetters[particles_List] := + StringJoin @ Riffle[ + Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, + photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; + "template<>\n" <> + "double charge<" <> ParticleToCXXName[#] <> + If[particleDim === 1, "(", + "( unsigned index, "] <> "EvaluationContext& context)\n{\n" <> + IndentText[ + "typedef VertexFunction<" <> + StringJoin @ Riffle[ParticleToCXXName /@ photonVertexParticles, ", "] <> + "> VF;\n" <> + If[particleDim === 1, + "const std::array indices{};\n", + "const std::array indices{ index, index };\n" + ] <> + "return VF::vertex(indices, context).left().real();" + ] <> "\n}" + ], + "\n\n"] + +CreateDiagrams[] := + Module[{diagramTypes, diagramTypeHeads, code}, + diagrams = contributingFeynmanDiagramTypes; + diagramHeads = DeleteDuplicates @ (Head /@ diagrams); + + code = "// The different diagram types that contribute to the muon magnetic moment\n"; + code = (code <> + StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) + /@ diagramHeads, "\n"] <> + "\n\n"); + + code = (code <> "// Indexed diagram types\n" <> + StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> + "<" <> ToString @ #[[1]] <> "> {};" &) + /@ diagrams, "\n"]); + + code = (code <> "\n\n" <> + StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingFeynmanDiagramTypes, "\n\n"]); + + Return[code]; + ]; + +CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; + +CreateDiagramEvaluatorClass[type_OneLoopDiagram] := + ("template\n" <> + "struct DiagramEvaluator + ToString @ type[[1]] <> + ">, PhotonEmitter, ExchangeParticle>\n" <> + "{ static double value(EvaluationContext& context); };"); + +calculationCode = Null; +CreateCalculation[] := + Module[{code}, + (* If we have been here before return the old result *) + If[calculationCode =!= Null, Return[calculationCode]]; + + code = "/********** GMuonMinus2.m generated calculation code **********/\n\n"; + + (* Generate code that simply adds up all contributions *) + code = (code <> + "EvaluationContext context{ model };\n" <> + "double val = 0.0;\n\n" <> + StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ ConcreteDiagramEvaluators[], + "\n"] <> "\n\n" <> + "return val;" + ); + + calculationCode = code; + Return[code]; + ]; + +CreateDefinitions[vertexRules_List] := + (CreateEvaluationContextSpecializations[] <> "\n\n" <> + CreateMuonFunctions[vertexRules][[2]] <> "\n\n" <> + CreateVertices[vertexRules][[2]]); + +nPointFunctions = Null; +NPointFunctions[] := + Module[{contributingDiagrams, vertices}, + If[nPointFunctions =!= Null, Return[nPointFunctions]]; + + contributingDiagrams = ContributingDiagrams[]; + + vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; + AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; + vertices = DeleteDuplicates[vertices]; + + vertices = (OrderParticles[#, Ordering[(Vertices`StripFieldIndices /@ #)]] &) /@ vertices; + vertices = DeleteDuplicates[vertices, + (Vertices`StripFieldIndices[#1] === Vertices`StripFieldIndices[#2] &)]; + + nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertices)]; + Return[nPointFunctions]; + ]; + + +(**************** End public interface *****************) + +(* Effectively generate all mass calculation functions *) +CreateEvaluationContextSpecializations[] := +Module[{particles, code}, + particles = TreeMasses`GetParticles[]; + particles = Select[particles, (! TreeMasses`IsGhost[#] &)]; + + code = (StringJoin @ + Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> + If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> + "{ return model.get_M" <> ParticleToCXXName[#] <> + If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" + &) /@ particles, "\n\n"]); + + Return[code]; + ]; + +(************************ Begin helper routines *******************************) + +(* Return the name of the SARAH particle family containing the muon *) +GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, + SARAH`Electron, + Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], + {p_, {Description -> "Muon", ___}} -> p, 1][[1]] + ]; +(* If the muon has a generation index, return it, otherwise return Null. + e.g. CMSSMNoFV has no muon generation index *) +GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; + +GetPhoton[] := SARAH`Photon; + +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; +SetAttributes[StripLorentzIndices, {Listable}]; + +(* Takes a SARAH particle and returns its antiparticle *) +AntiParticle[SARAH`bar[p_]] := p; +AntiParticle[Susyno`LieGroups`conj[p_]] := p; +AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, + If[IsScalar[pNoIndices] || IsVector[pNoIndices], + Susyno`LieGroups`conj[p], + SARAH`bar[p]]]; +SetAttributes[AntiParticle, {Listable}]; + +(* Return a string corresponding to the c++ class name of the particle. + Note that "bar" and "conj" get turned into anti<...>::type! *) +ParticleToCXXName[p_] := SymbolName[p]; +ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; + +(* Return a string corresponding to the name of the particle. + Note that "bar" and "conj" are left as they are! *) +ParticleToSARAHString[p_] := SymbolName[p]; +ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; +ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; + +(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) +ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], + Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; + +(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) +IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := + ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); + +(* Returns the rules that are needed to change order of a prticle list. + i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} + For some reason SARAH expects the indices to always be in that order... *) +IndexReplacementRulesForParticleReordering[particles_List, ordering_] := +Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, + Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; + +(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) +OrderParticles[particles_List, ordering_] := Module[{indexRules}, + indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; + Return[particles[[ordering]] /. indexRules]; + ]; + +(* Essentially the same as above, but using the obtained rules, + transform a whole vertex expression, as returned by SARAH`Vertex[] *) +OrderVertex[vertex_, ordering_] := + Module[{indexRules, particles, expr, newVertex}, + indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; + + particles = vertex[[1]][[ordering]]; + expr = vertex[[2;;]]; + + newVertex = (Join[{particles}, expr] /. indexRules); + Return[newVertex]; + ]; + +(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) +(* MemoizingVertex[] only works when __no__ indices are specified!!! *) +(* Use of memoization gives ~30% speedup for the MSSM! *) +memoizedVertices = {}; +MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := + Module[{memo, ordering, orderedParticles}, + (* First we sort the particles *) + ordering = Ordering[particles]; + orderedParticles = particles[[ordering]]; + + memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; + If[memo =!= {}, memo = memo[[1]], + (* Create a new entry *) + memo = SARAH`Vertex[orderedParticles, options]; + AppendTo[memoizedVertices, memo];]; + + (* Now return the particles to their original order *) + memo = OrderVertex[memo, Ordering[ordering]]; + Return[memo]]; + +MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; + +(* Test whether a SARAH Vertex[] result is nonzero (exact) *) +IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; + +(* Returns the name of the coupling function that FlexibleSUSY generates for + a specific vertex in a canonical order! *) +NameOfCouplingFunction[particles_List] := +((* FIXME: Not upwards compatible if naming conventions change *) + "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); + +(********************** End helper routines **************************) + +(* The different vertex types that are supported. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; + +(* The different diagram types that should be taken into consideration *) +(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) +(* There is no bounds check done on the integers, so they have to fit + into a standard c++ unsigned (!) int *) +contributingFeynmanDiagramTypes = { + OneLoopDiagram[3], (* Photon is emitted by a fermion, exchange particle is a scalar *) + OneLoopDiagram[4] (* Photon is emitted by a scalar, exchange particle is a fermion *) +}; + +(* IMPORTANT: If you want to add support for type 1 and 2 diagrams, hardly any + changes are necessary here. Just add the diagram types to contributingFeynmanDiagramTypes, + write corresponding helper lines as below and have ContributingDiagramsOfType[] + operate on type 1 and 2 diagrams as well. + You should not have to modify the actual code in ContributingDiagramsOfType[] + unless you are adding type 5 and 6 diagrams or completely other diagram types. *) + +(* This is just a convenient way to help ContributingDiagramsOfType[] *) +OneLoopDiagram[3][fermions_, scalars_, vectors_] := {fermions, scalars}; +OneLoopDiagram[4][fermions_, scalars_, vectors_] := {scalars, fermions}; + +(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +(* For now only LoopDiagrams 3 through 4 (see further above) are supported. + If you are adding more diagram types, you should probably make a new overload + of ContributingDiagramsOfType[] instead of extending this one. *) +(* IMPORTANT: Return value should be a list of Diagram[DIAGRAMTYPENAME[_Integer], Particles___] + This is important for the c++ conversion that assumes every argument after the type + is a particle and uses ParticleToCXXName for conversion *) + +ContributingDiagramsOfType[type : (OneLoopDiagram[3] | OneLoopDiagram[4]), fermions_, scalars_, vectors_] := + Module[{photonEmitters, exchangeParticles, photonVertices, muonVertices, test}, + (* Get the photon emitter and the exchange particle categories corresponding to the + diagram type *) + {photonEmitters, exchangeParticles} = type[fermions, scalars, vectors]; + + (* For every potential photon emitter, check whether it actually can emit a photon *) + photonVertices = (MemoizingVertex[{GetPhoton[], #, AntiParticle[#]}, + SARAH`UseDependences -> True, + SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &) /@ photonEmitters; + photonVertices = Select[photonVertices, IsNonZeroVertex]; + + (* From SARAH's more or less cryptically formatted result extract the particles' names *) + photonEmitters = (Vertices`StripFieldIndices /@ photonVertices)[[All, 1]][[All, 2]]; + + (* Since we do not know anything about the particles, we have to include their + corresponding antiparticles as well *) + photonEmitters = Union[photonEmitters, AntiParticle[photonEmitters]]; + exchangeParticles = Union[exchangeParticles, AntiParticle[exchangeParticles]]; + + (* Now we check which of the photon emitting particles actually can interact with + a muon in the way we want. *) + muonVertices = Outer[(MemoizingVertex[{GetMuonFamily[], #1, #2}, + SARAH`UseDependences -> True, + SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &), + photonEmitters, exchangeParticles]; + muonVertices = Select[#, IsNonZeroVertex] & /@ muonVertices; + muonVertices = Cases[muonVertices, Except[{}]]; + + (* We return the antiparticles of the particles we just found to *) + (* This is just a convention and nothing serious. The returned + particles are the decay products of the muon: + i.e. if muon ---> p1 + p2 + Then p1 and p2 are returned *) + test = (Diagram[type, AntiParticle[#[[1]]], AntiParticle[#[[2]]]] &) /@ + (Vertices`StripFieldIndices /@ # &) /@ Flatten[muonVertices[[All, All, 1, 2 ;;]], 1] + ]; + +(* Returns the necessary c++ code corresponding to the vertices that need to be calculated. + The returned value is a list {prototypes, definitions}. *) +createdVertices = Null; +CreateVertices[vertexRules_List] := + Module[{contributingDiagrams, vertices, + vertexClassesPrototypes, vertexClassesDefinitions}, + If[createdVertices =!= Null, Return[createdVertices]]; + contributingDiagrams = ContributingDiagrams[]; + + vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; + AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; + vertices = DeleteDuplicates[vertices]; + + {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); + vertexClassesPrototypes = Cases[vertexClassesPrototypes, Except[""]]; + vertexClassesDefinitions = Cases[vertexClassesDefinitions, Except[""]]; + + createdVertices = {vertexClassesPrototypes, vertexClassesDefinitions}; + createdVertices = (StringJoin @ Riffle[#, "\n\n"] &) /@ createdVertices; + + Return[createdVertices]; + ]; + +(* Returns the vertices that are present in the specified diagram. + This function should be overloaded for future diagram types. + IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) +VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, photonEmitter_, exchangeParticle_]] := + Module[{photonVertex, muonVertex}, + photonVertex = MemoizingVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; + muonVertex = MemoizingVertex[{GetMuonFamily[], AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; + + photonVertex = StripLorentzIndices @ photonVertex[[1]]; + muonVertex = StripLorentzIndices @ muonVertex[[1]]; + + Return[{photonVertex, muonVertex}]; + ]; + +(* Returns the vertex type for a vertex with a given list of particles *) +VertexTypeForParticles[particles_List] := + Module[{strippedParticles, scalars, vectors, fermions, scalarCount, vectorCount, fermionCount}, + strippedParticles = Vertices`StripFieldIndices /@ particles; + + scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiParticle[#]] &)]; + vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiParticle[#]] &)]; + fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiParticle[#]] &)]; + + scalarCount = Length[scalars]; + vectorCount = Length[vectors]; + fermionCount = Length[fermions]; + + If[fermionCount === 2 && scalarCount === 1 && vectorCount === 0, + Return[LeftAndRightComponentedVertex]]; + If[fermionCount === 2 && scalarCount === 0 && vectorCount === 1, + If[fermions[[1]] === AntiParticle[fermions[[2]]], + Return[LeftAndRightComponentedVertex]]]; + If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, + Return[SingleComponentedVertex]]; + + Return[Null]; + ]; + +(* Returns the different SARAH`Cp coupling parts for a vertex with a given list of particles *) +CouplingsForParticles[particles_List] := + Module[{vertexType, couplings}, + vertexType = VertexTypeForParticles[particles]; + couplings = {ReplacePart[particles, 0 -> SARAH`Cp]}; + + couplings = Switch[vertexType, + SingleComponentedVertex, couplings, + LeftAndRightComponentedVertex, {couplings[[1]][SARAH`PL], couplings[[1]][SARAH`PR]}]; + Return[couplings]; + ]; + +(* Creates the actual c++ code for a vertex with given particles. + This involves creating the VertexFunctionData<> code as well as + the VertexFunction<> code. You should never need to change this code! *) +vertexFunctions = {}; +CreateVertexFunction[indexedParticles_List, vertexRules_List] := + Module[{prototypes, definitions = "", ordering, particles, orderedParticles, + orderedIndexedParticles, addSpacing = True}, + particles = Vertices`StripFieldIndices /@ indexedParticles; + If[MemberQ[vertexFunctions, particles], Return[{"",""}]]; + + ordering = Ordering[particles]; + orderedParticles = particles[[ordering]]; + orderedIndexedParticles = OrderParticles[indexedParticles, ordering]; + + If[MemberQ[vertexFunctions, orderedParticles] === True, + (* There is already an entry *) + prototypes = ""; + addSpacing = False, + (* There is no entry yet, create it *) + {prototypes, definitions} = CreateOrderedVertexFunction[orderedIndexedParticles, vertexRules]; + AppendTo[vertexFunctions, orderedParticles]; + ]; + + If[ordering === Table[i, {i, 1, Length[ordering]}], + Return[{prototypes, definitions}]]; + + orderedVertexFunction = ("VertexFunction<" <> + StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> + ">"); + + prototypes = (prototypes <> If[addSpacing, "\n\n", ""] <> + "template<> struct VertexFunctionData<" <> + StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> + ">\n" <> + "{\n" <> + IndentText @ + ("static const bool is_permutation = true;\n" <> + "typedef " <> orderedVertexFunction <> " orig_type;\n" <> + "typedef boost::mpl::vector_c + StringJoin @ Riffle[ToString /@ (Ordering[ordering] - 1), ", "] <> + "> particlePermutation;\n" + ) <> + "};"); + + AppendTo[vertexFunctions, particles]; + Return[{prototypes, definitions}]; + ]; + +(* Creates local declarations of field indices, whose values are taken + from the elements of `arrayName'. + *) +DeclareIndices[indexedParticles_List, arrayName_String] := + Module[{p, total = 0, fieldIndexList, decl = ""}, + DeclareIndex[idx_, num_Integer, an_String] := ( + "const unsigned " <> CConversion`ToValidCSymbolString[idx] <> + " = " <> an <> "[" <> ToString[num] <> "];\n"); + For[p = 1, p <= Length[indexedParticles], p++, + fieldIndexList = FieldIndexList[indexedParticles[[p]]]; + decl = decl <> StringJoin[DeclareIndex[#, total++, arrayName]& /@ fieldIndexList]; + ]; + Assert[total == Total[Length[FieldIndexList[#]]& /@ indexedParticles]]; + decl + ]; + +(* ParsedVertex structure: + ParsedVertex[ + {numP1Indices, numP2Indices, ...}, + {{minIndex1, minIndex2, ...}, {maxIndex1+1, maxIndex2+1, ...}}, + VertexClassName, + VertexFunctionBody + ] + + Getters are available! Given below ParseVertex[] + *) + +(* The heart of the algorithm! From the particle content, determine all + necessary information. *) +ParseVertex[indexedParticles_List, vertexRules_List] := + Module[{particles, numberOfIndices, declareIndices, + parsedVertex, vertexClassName, vertexFunctionBody, + sarahParticles, particleInfo, indexBounds, expr, exprL, exprR}, + numberOfIndices = ((Length @ FieldIndexList[#] &) /@ indexedParticles); + particles = Vertices`StripFieldIndices /@ indexedParticles; + declareIndices = DeclareIndices[indexedParticles, "indices"]; + + vertexClassName = SymbolName[VertexTypeForParticles[particles]]; + vertexFunctionBody = Switch[vertexClassName, + "SingleComponentedVertex", + expr = (SARAH`Cp @@ indexedParticles) /. vertexRules; + expr = TreeMasses`ReplaceDependenciesReverse[expr]; + "std::complex result;\n\n" <> + declareIndices <> + Parameters`CreateLocalConstRefs[expr] <> "\n" <> + TreeMasses`ExpressionToString[expr, "result"] <> "\n" <> + "return vertex_type(result);", + + "LeftAndRightComponentedVertex", + exprL = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PL] /. vertexRules; + exprR = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PR] /. vertexRules; + exprL = TreeMasses`ReplaceDependenciesReverse[exprL]; + exprR = TreeMasses`ReplaceDependenciesReverse[exprR]; + "std::complex left, right;\n\n" <> + declareIndices <> + Parameters`CreateLocalConstRefs[exprL + exprR] <> "\n" <> + TreeMasses`ExpressionToString[exprL, "left"] <> "\n" <> + TreeMasses`ExpressionToString[exprR, "right"] <> "\n" <> + "return vertex_type(left, right);"]; + + sarahParticles = SARAH`getParticleName /@ particles; + particleInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ + sarahParticles, 1]; + + (* INFO: I do not think this ever occurs... *) + particleInfo = DeleteCases[particleInfo, {SARAH`generation, 1}, {3}]; + particleInfo = DeleteCases[particleInfo, {SARAH`lorentz, _}, {3}]; + + indexBounds = (With[{particleIndex = #}, + (If[#[[1]] === SARAH`generation, + {particleInfo[[particleIndex, 2]]-1, particleInfo[[particleIndex, 3]]}, + {1, #[[2]]}] + &) /@ particleInfo[[particleIndex, 5]]] + &) /@ Table[i, {i, Length[particles]}]; + indexBounds = Cases[Flatten[indexBounds, 1], Except[{}]]; + + If[indexBounds === {}, + indexBounds = {{},{}}, + indexBounds = Transpose @ indexBounds]; + + parsedVertex = ParsedVertex[numberOfIndices, + indexBounds, + vertexClassName, + vertexFunctionBody]; + + Return[parsedVertex]; + ]; + +(** Getters to the ParsedVertex structure **) +NumberOfIndices[parsedVertex_ParsedVertex] := Total[parsedVertex[[1]]]; +NumberOfIndices[parsedVertex_ParsedVertex, pIndex_Integer] := parsedVertex[[1, pIndex]]; + +IndexBounds[parsedVertex_ParsedVertex] := parsedVertex[[2]]; + +VertexClassName[parsedVertex_ParsedVertex] := parsedVertex[[3]]; +VertexFunctionBody[parsedVertex_ParsedVertex] := parsedVertex[[4]]; +(** End getters **) + +(* Create the c++ code for a canonically ordered vertex *) +CreateOrderedVertexFunction[orderedIndexedParticles_List, vertexRules_List] := + Module[{prototype, definition, orderedParticles, dataClassName, functionClassName, + parsedVertex, particleIndexStartF, particleIndexStart, indexBounds}, + orderedParticles = Vertices`StripFieldIndices /@ orderedIndexedParticles; + parsedVertex = ParseVertex[orderedIndexedParticles, vertexRules]; + dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; + functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; + + particleIndexStartF[1] = 0; + particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; + particleIndexStartF[Length[orderedParticles]+1] = NumberOfIndices[parsedVertex]; + + particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[orderedParticles] + 1}]; + + prototype = ("template<> struct " <> dataClassName <> "\n" <> + "{\n" <> + IndentText @ + ("static const bool is_permutation = false;\n" <> + "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> + "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> + "typedef boost::mpl::vector_c + StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> + "> particleIndexStart;\n" <> + "static const index_bounds indexB;\n" + ) <> + "};"); + + indexBounds = IndexBounds[parsedVertex]; + + If[NumberOfIndices[parsedVertex] =!= 0, + prototype = (prototype <> "\n" <> + "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" + );]; + definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> + functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> + "{\n" <> + IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> + "}"); + + Return[{prototype, definition}]; + ]; + +(* Find all contributing diagrams *) +cachedContributingDiagrams = Null; +ContributingDiagrams[] := + Module[{particles, fermions, scalars, vectors}, + If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; + + particles = TreeMasses`GetParticles[]; + fermions = Select[particles, TreeMasses`IsFermion]; + scalars = Select[particles, TreeMasses`IsScalar]; + vectors = Select[particles, TreeMasses`IsVector]; + + cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#, fermions, scalars, vectors] &) + /@ contributingFeynmanDiagramTypes + , 1]; + Return[cachedContributingDiagrams]; + ]; + +(* Returns a list of all concrete diagram evaluators (as strings) + e.g. "DiagramEvaluator, Fe, VP>" + that need to be invoked in our calculation *) +ConcreteDiagramEvaluators[] := + (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> + ToString @ #[[1,1]] <> ">, " <> + StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> + ">" &) + /@ ContributingDiagrams[]); + +End[]; + +EndPackage[]; From ad854a582a151eedd24efe030da92893610e8a07 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 1 Nov 2016 21:00:11 +0100 Subject: [PATCH 002/158] Ported ConcreteDiagramEvaluators[] --- meta/EDM.m | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 8379254e8..1a2c834fc 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -143,10 +143,10 @@ If you add new kinds of vertices (e.g for new diagram types): CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; CreateDiagramEvaluatorClass[type_OneLoopDiagram] := - ("template\n" <> + ("template\n" <> "struct DiagramEvaluator ToString @ type[[1]] <> - ">, PhotonEmitter, ExchangeParticle>\n" <> + ">, EDMParticle, PhotonEmitter, ExchangeParticle>\n" <> "{ static double value(EvaluationContext& context); };"); calculationCode = Null; @@ -155,7 +155,7 @@ If you add new kinds of vertices (e.g for new diagram types): (* If we have been here before return the old result *) If[calculationCode =!= Null, Return[calculationCode]]; - code = "/********** GMuonMinus2.m generated calculation code **********/\n\n"; + code = "/********** EDM.m generated calculation code **********/\n\n"; (* Generate code that simply adds up all contributions *) code = (code <> @@ -681,15 +681,18 @@ If you add new kinds of vertices (e.g for new diagram types): Return[cachedContributingDiagrams]; ]; -(* Returns a list of all concrete diagram evaluators (as strings) - e.g. "DiagramEvaluator, Fe, VP>" +(* Returns a list of all concrete diagram evaluators + format: {{edmParticle1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, + {edmParticle2, {"...", ... }}, + ...} that need to be invoked in our calculation *) ConcreteDiagramEvaluators[] := - (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> - ToString @ #[[1,1]] <> ">, " <> - StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> - ">" &) - /@ ContributingDiagrams[]); + ({#[[1]], + (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> + ToString @ #[[1,1]] <> ">, " <> + StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> + ">" &) + /@ #[[2]]) &) /@ ContributingDiagrams[]); End[]; From a7aa4ec1eb9ba8eeeb9698eec7bee6c9ccff3d73 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 18:25:58 +0100 Subject: [PATCH 003/158] Small fixes --- meta/EDM.m | 70 ++++++++++-------------------------------------------- 1 file changed, 13 insertions(+), 57 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 1a2c834fc..51fd028fe 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -22,14 +22,12 @@ If you add new kinds of vertices (e.g for new diagram types): - Write the c++ class for the new vertex type When adding support for new diagram types, do the following: - - Add the new types to contributingFeynmanDiagramTypes + - Add the new types to contributingDiagramTypes - Write new overloads for CreateDiagramEvaluatorClass[], ContributingDiagramsOfType[] and VerticesForDiagram[] - Write the necessary c++ code: loop functions, DiagramEvaluator<> specialisations **********) -Test[] := Print["blablabla" <> ToString @ SARAH`InsFields[{{C[Fe, SARAH`FieldToInsert[1], VP]}}]]; - -Begin["`Private`"]; +(* TODO: privatize interface again Begin["`Private`"]; *) (************* Begin public interface *******************) @@ -120,7 +118,7 @@ If you add new kinds of vertices (e.g for new diagram types): CreateDiagrams[] := Module[{diagramTypes, diagramTypeHeads, code}, - diagrams = contributingFeynmanDiagramTypes; + diagrams = contributingDiagramTypes; diagramHeads = DeleteDuplicates @ (Head /@ diagrams); code = "// The different diagram types that contribute to the muon magnetic moment\n"; @@ -135,7 +133,7 @@ If you add new kinds of vertices (e.g for new diagram types): /@ diagrams, "\n"]); code = (code <> "\n\n" <> - StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingFeynmanDiagramTypes, "\n\n"]); + StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingDiagramTypes, "\n\n"]); Return[code]; ]; @@ -338,67 +336,25 @@ If you add new kinds of vertices (e.g for new diagram types): (* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) -contributingFeynmanDiagramTypes = { +contributingDiagramTypes = { OneLoopDiagram[3], (* Photon is emitted by a fermion, exchange particle is a scalar *) OneLoopDiagram[4] (* Photon is emitted by a scalar, exchange particle is a fermion *) }; -(* IMPORTANT: If you want to add support for type 1 and 2 diagrams, hardly any - changes are necessary here. Just add the diagram types to contributingFeynmanDiagramTypes, - write corresponding helper lines as below and have ContributingDiagramsOfType[] - operate on type 1 and 2 diagrams as well. - You should not have to modify the actual code in ContributingDiagramsOfType[] - unless you are adding type 5 and 6 diagrams or completely other diagram types. *) - (* This is just a convenient way to help ContributingDiagramsOfType[] *) OneLoopDiagram[3][fermions_, scalars_, vectors_] := {fermions, scalars}; OneLoopDiagram[4][fermions_, scalars_, vectors_] := {scalars, fermions}; (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) -(* For now only LoopDiagrams 3 through 4 (see further above) are supported. - If you are adding more diagram types, you should probably make a new overload - of ContributingDiagramsOfType[] instead of extending this one. *) -(* IMPORTANT: Return value should be a list of Diagram[DIAGRAMTYPENAME[_Integer], Particles___] +(* IMPORTANT: Return value should have the format + {{edmParticle1, {Diagram[DIAGRAMTYPENAME[_Integer], Particles___], Diagram[...], ...}}, + {edmParticle2, {...}}, + ...} This is important for the c++ conversion that assumes every argument after the type is a particle and uses ParticleToCXXName for conversion *) ContributingDiagramsOfType[type : (OneLoopDiagram[3] | OneLoopDiagram[4]), fermions_, scalars_, vectors_] := - Module[{photonEmitters, exchangeParticles, photonVertices, muonVertices, test}, - (* Get the photon emitter and the exchange particle categories corresponding to the - diagram type *) - {photonEmitters, exchangeParticles} = type[fermions, scalars, vectors]; - - (* For every potential photon emitter, check whether it actually can emit a photon *) - photonVertices = (MemoizingVertex[{GetPhoton[], #, AntiParticle[#]}, - SARAH`UseDependences -> True, - SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &) /@ photonEmitters; - photonVertices = Select[photonVertices, IsNonZeroVertex]; - - (* From SARAH's more or less cryptically formatted result extract the particles' names *) - photonEmitters = (Vertices`StripFieldIndices /@ photonVertices)[[All, 1]][[All, 2]]; - - (* Since we do not know anything about the particles, we have to include their - corresponding antiparticles as well *) - photonEmitters = Union[photonEmitters, AntiParticle[photonEmitters]]; - exchangeParticles = Union[exchangeParticles, AntiParticle[exchangeParticles]]; - - (* Now we check which of the photon emitting particles actually can interact with - a muon in the way we want. *) - muonVertices = Outer[(MemoizingVertex[{GetMuonFamily[], #1, #2}, - SARAH`UseDependences -> True, - SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &), - photonEmitters, exchangeParticles]; - muonVertices = Select[#, IsNonZeroVertex] & /@ muonVertices; - muonVertices = Cases[muonVertices, Except[{}]]; - - (* We return the antiparticles of the particles we just found to *) - (* This is just a convention and nothing serious. The returned - particles are the decay products of the muon: - i.e. if muon ---> p1 + p2 - Then p1 and p2 are returned *) - test = (Diagram[type, AntiParticle[#[[1]]], AntiParticle[#[[2]]]] &) /@ - (Vertices`StripFieldIndices /@ # &) /@ Flatten[muonVertices[[All, All, 1, 2 ;;]], 1] - ]; + Module[]; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. The returned value is a list {prototypes, definitions}. *) @@ -676,7 +632,7 @@ If you add new kinds of vertices (e.g for new diagram types): vectors = Select[particles, TreeMasses`IsVector]; cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#, fermions, scalars, vectors] &) - /@ contributingFeynmanDiagramTypes + /@ contributingDiagramTypes , 1]; Return[cachedContributingDiagrams]; ]; @@ -692,8 +648,8 @@ If you add new kinds of vertices (e.g for new diagram types): ToString @ #[[1,1]] <> ">, " <> StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> ">" &) - /@ #[[2]]) &) /@ ContributingDiagrams[]); + /@ #[[2]]) } &) /@ ContributingDiagrams[]; -End[]; +(* TODO: End[]; *) EndPackage[]; From 5835c310e6d4395806e02c0dcaaf1a186bee8eb7 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 18:32:26 +0100 Subject: [PATCH 004/158] Fixed CreateChargeGetters[] --- meta/EDM.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 51fd028fe..055cf85bd 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -97,10 +97,10 @@ If you add new kinds of vertices (e.g for new diagram types): CreateChargeGetters[particles_List] := StringJoin @ Riffle[ - Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, + (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; "template<>\n" <> - "double charge<" <> ParticleToCXXName[#] <> + "double charge<" <> ParticleToCXXName[#] <> ">" <> If[particleDim === 1, "(", "( unsigned index, "] <> "EvaluationContext& context)\n{\n" <> IndentText[ @@ -113,7 +113,7 @@ If you add new kinds of vertices (e.g for new diagram types): ] <> "return VF::vertex(indices, context).left().real();" ] <> "\n}" - ], + ] &) /@ particles, "\n\n"] CreateDiagrams[] := From 316939afa4fed05702864064e63555113efe09e0 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 19:00:32 +0100 Subject: [PATCH 005/158] Fixed CreateChargeGetters[] for real --- meta/EDM.m | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 055cf85bd..66455e483 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -32,7 +32,7 @@ If you add new kinds of vertices (e.g for new diagram types): (************* Begin public interface *******************) edmParticles = Null; -SetEDMParticles[particles_List] := (edmParticles = particles); +SetEDMParticles[particles_List] := (edmParticles = particles;) IsSMParticle[particle_] := SARAH`SMQ[particle] || TreeMasses`IsSMGoldstone[particle]; @@ -95,14 +95,18 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateChargeGetters[particles_List] := +CreateChargeGetters[] := + "template\n" <> + "double charge( EvaluationContext & );\n\n" <> + "template\n" <> + "double charge( unsigned, EvaluationContext & );\n\n" <> StringJoin @ Riffle[ (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; "template<>\n" <> "double charge<" <> ParticleToCXXName[#] <> ">" <> - If[particleDim === 1, "(", - "( unsigned index, "] <> "EvaluationContext& context)\n{\n" <> + If[particleDim === 1, "( ", + "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> IndentText[ "typedef VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ photonVertexParticles, ", "] <> @@ -113,7 +117,7 @@ If you add new kinds of vertices (e.g for new diagram types): ] <> "return VF::vertex(indices, context).left().real();" ] <> "\n}" - ] &) /@ particles, + ] &) /@ edmParticles, "\n\n"] CreateDiagrams[] := @@ -170,7 +174,6 @@ If you add new kinds of vertices (e.g for new diagram types): CreateDefinitions[vertexRules_List] := (CreateEvaluationContextSpecializations[] <> "\n\n" <> - CreateMuonFunctions[vertexRules][[2]] <> "\n\n" <> CreateVertices[vertexRules][[2]]); nPointFunctions = Null; From 68829be78cfd744e718b41a6121f959a08d251fb Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 19:32:44 +0100 Subject: [PATCH 006/158] Rewrote CreateCalculation[] to match ConcreteDiagramEvaluators[]'s new output format. --- meta/EDM.m | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 66455e483..158544799 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -142,8 +142,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; - CreateDiagramEvaluatorClass[type_OneLoopDiagram] := ("template\n" <> "struct DiagramEvaluator @@ -151,22 +149,30 @@ If you add new kinds of vertices (e.g for new diagram types): ">, EDMParticle, PhotonEmitter, ExchangeParticle>\n" <> "{ static double value(EvaluationContext& context); };"); +CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; + calculationCode = Null; CreateCalculation[] := - Module[{code}, + Module[{code, evaluators}, (* If we have been here before return the old result *) If[calculationCode =!= Null, Return[calculationCode]]; - - code = "/********** EDM.m generated calculation code **********/\n\n"; - - (* Generate code that simply adds up all contributions *) - code = (code <> - "EvaluationContext context{ model };\n" <> - "double val = 0.0;\n\n" <> - StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ ConcreteDiagramEvaluators[], - "\n"] <> "\n\n" <> - "return val;" - ); + + evaluators = ConcreteDiagramEvaluators[]; + + code = "/********** EDM.m generated calculation code **********/\n\n" <> + "template double edm( void );\n\n"; + + code = code <> StringJoin @ Riffle[ + Module[{pEvaluators = Cases[evaluators, {#, ev_List} -> ev]}, + "template<> double edm<" <> ParticleToCXXName[#] <> ">( void )\n" <> + "{\n" <> + IndentText["EvaluationContext context{ model };\n" <> + "double val = 0.0\n\n;" <> + StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ pEvaluators, + "\n"] <> "\n\n" <> + "return val;" + ] <> + "}"] & /@ evaluators, "\n\n"]; calculationCode = code; Return[code]; From ae4fa134030b7b7e62e86414cd6ec8bea9db8e36 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 20:33:42 +0100 Subject: [PATCH 007/158] Implemented ContributingDiagramsOfType[OneLoopDiagram[0]] --- meta/EDM.m | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 158544799..bd66b0795 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -346,24 +346,27 @@ If you add new kinds of vertices (e.g for new diagram types): (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) contributingDiagramTypes = { - OneLoopDiagram[3], (* Photon is emitted by a fermion, exchange particle is a scalar *) - OneLoopDiagram[4] (* Photon is emitted by a scalar, exchange particle is a fermion *) + OneLoopDiagram[0] }; -(* This is just a convenient way to help ContributingDiagramsOfType[] *) -OneLoopDiagram[3][fermions_, scalars_, vectors_] := {fermions, scalars}; -OneLoopDiagram[4][fermions_, scalars_, vectors_] := {scalars, fermions}; - (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) (* IMPORTANT: Return value should have the format {{edmParticle1, {Diagram[DIAGRAMTYPENAME[_Integer], Particles___], Diagram[...], ...}}, {edmParticle2, {...}}, - ...} - This is important for the c++ conversion that assumes every argument after the type - is a particle and uses ParticleToCXXName for conversion *) - -ContributingDiagramsOfType[type : (OneLoopDiagram[3] | OneLoopDiagram[4]), fermions_, scalars_, vectors_] := - Module[]; + ...} *) + +ContributingDiagramsOfType[OneLoopDiagram[0]] := + Module[{edmParticle = #, diagrams = SARAH`InsFields[ + {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], + SARAH`AntiField[SARAH`FieldToInsert[2]]], + C[SARAH`FieldToInsert[1], GetPhoton[], + SARAH`AntiField[SARAH`FieldToInsert[1]]], + C[SARAH`FieldToInsert[1], SARAH`FieldToInsert[2], + SARAH`AntiField[#]]}}]}, + {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[1,3,1]], + exchangeParticle = #[[1,3,2]]}, + Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] + &) /@ diagrams]}] & /@ edmParticles; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. The returned value is a list {prototypes, definitions}. *) From a4b6f1c144ae0d0b9256fdca72bf9f2a5ab6f073 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 20:59:14 +0100 Subject: [PATCH 008/158] Implemented ContributingDiagrams[] --- meta/EDM.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index bd66b0795..32f8c1020 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -346,7 +346,8 @@ If you add new kinds of vertices (e.g for new diagram types): (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) contributingDiagramTypes = { - OneLoopDiagram[0] + OneLoopDiagram[0], + OneLoopDiagram[1] }; (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) @@ -355,7 +356,7 @@ If you add new kinds of vertices (e.g for new diagram types): {edmParticle2, {...}}, ...} *) -ContributingDiagramsOfType[OneLoopDiagram[0]] := +ContributingDiagramsOfType[type : (OneLoopDiagram[0] | OneLoopDiagram[1])] := Module[{edmParticle = #, diagrams = SARAH`InsFields[ {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], SARAH`AntiField[SARAH`FieldToInsert[2]]], @@ -365,7 +366,7 @@ If you add new kinds of vertices (e.g for new diagram types): SARAH`AntiField[#]]}}]}, {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[1,3,1]], exchangeParticle = #[[1,3,2]]}, - Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] + Diagram[type, edmParticle, photonEmitter, exchangeParticle]] &) /@ diagrams]}] & /@ edmParticles; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. @@ -635,17 +636,16 @@ If you add new kinds of vertices (e.g for new diagram types): (* Find all contributing diagrams *) cachedContributingDiagrams = Null; ContributingDiagrams[] := - Module[{particles, fermions, scalars, vectors}, + Module[{diagrams}, If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; - particles = TreeMasses`GetParticles[]; - fermions = Select[particles, TreeMasses`IsFermion]; - scalars = Select[particles, TreeMasses`IsScalar]; - vectors = Select[particles, TreeMasses`IsVector]; - - cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#, fermions, scalars, vectors] &) + cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#] &) /@ contributingDiagramTypes , 1]; + cachedContributingDiagrams = ({#, Union @ + ReplacePart[Cases[cachedContributingDiagrams, + {#, diagrams_List} -> diagrams], 0 -> Sequence]} &) /@ edmParticles; + Return[cachedContributingDiagrams]; ]; From 461ca46ae62e0f1c73b0764484e4b33e48457213 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 21:08:51 +0100 Subject: [PATCH 009/158] Fixed bug in ContributingDiagramsOfType[] --- meta/EDM.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 32f8c1020..ac70ca348 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -346,8 +346,7 @@ If you add new kinds of vertices (e.g for new diagram types): (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) contributingDiagramTypes = { - OneLoopDiagram[0], - OneLoopDiagram[1] + OneLoopDiagram[0] }; (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) @@ -356,17 +355,18 @@ If you add new kinds of vertices (e.g for new diagram types): {edmParticle2, {...}}, ...} *) -ContributingDiagramsOfType[type : (OneLoopDiagram[0] | OneLoopDiagram[1])] := +ContributingDiagramsOfType[OneLoopDiagram[0]] := Module[{edmParticle = #, diagrams = SARAH`InsFields[ {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], SARAH`AntiField[SARAH`FieldToInsert[2]]], C[SARAH`FieldToInsert[1], GetPhoton[], SARAH`AntiField[SARAH`FieldToInsert[1]]], C[SARAH`FieldToInsert[1], SARAH`FieldToInsert[2], - SARAH`AntiField[#]]}}]}, - {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[1,3,1]], - exchangeParticle = #[[1,3,2]]}, - Diagram[type, edmParticle, photonEmitter, exchangeParticle]] + SARAH`AntiField[#]]}, + {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}]}, + {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[2,1]], + exchangeParticle = #[[2,2]]}, + Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] &) /@ diagrams]}] & /@ edmParticles; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. From d2efef4bc5d4fa856e690390277062960f6bd147 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 17:48:44 +0100 Subject: [PATCH 010/158] Rewrote VerticesForDiagram[], next up MemoizingVertex[] -> CachedVertices[] --- meta/EDM.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index ac70ca348..94b09031f 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -395,15 +395,17 @@ If you add new kinds of vertices (e.g for new diagram types): (* Returns the vertices that are present in the specified diagram. This function should be overloaded for future diagram types. IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) -VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, photonEmitter_, exchangeParticle_]] := - Module[{photonVertex, muonVertex}, - photonVertex = MemoizingVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; - muonVertex = MemoizingVertex[{GetMuonFamily[], AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; +VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := + Module[{edmVertex1, photonVertex, edmVertex2}, + edmVertex1 = CachedVertex[{edmParticle, AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; + photonVertex = CachedVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; + edmVertex2 = CachedVertex[{AntiParticle[edmParticle], photonEmitter, exchangeParticle}]; + edmVertex1 = StripLorentzIndices @ edmVertex1[[1]]; photonVertex = StripLorentzIndices @ photonVertex[[1]]; - muonVertex = StripLorentzIndices @ muonVertex[[1]]; + edmVertex2 = StripLorentzIndices @ edmVertex2[[1]]; - Return[{photonVertex, muonVertex}]; + Return[{edmVertex1, photonVertex, edmVertex2}]; ]; (* Returns the vertex type for a vertex with a given list of particles *) From 9867e0b20fe8fbf82a2322b1b50e577f3362dae1 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 18:07:24 +0100 Subject: [PATCH 011/158] Implemented CachedVertices[] --- meta/EDM.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/meta/EDM.m b/meta/EDM.m index 94b09031f..ca3f86f86 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -301,6 +301,14 @@ If you add new kinds of vertices (e.g for new diagram types): Return[newVertex]; ]; +CachedVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := + Module[{vertexPattern = ReplacePart[({#, ___} &) /@ + Permutations[(#[___] &) /@ particles], + 0 -> Alternatives], + vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, + FirstCase[vertexList, vertexPattern]; + ]; + (* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) (* MemoizingVertex[] only works when __no__ indices are specified!!! *) (* Use of memoization gives ~30% speedup for the MSSM! *) From a929bcd2716fd0757d5b40268ab390a288763948 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 18:08:54 +0100 Subject: [PATCH 012/158] Removed MemoizingVertex[] and friends. --- meta/EDM.m | 59 ------------------------------------------------------ 1 file changed, 59 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index ca3f86f86..1017243f3 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -267,40 +267,6 @@ If you add new kinds of vertices (e.g for new diagram types): ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; -(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) -ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], - Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; - -(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) -IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := - ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); - -(* Returns the rules that are needed to change order of a prticle list. - i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} - For some reason SARAH expects the indices to always be in that order... *) -IndexReplacementRulesForParticleReordering[particles_List, ordering_] := -Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, - Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; - -(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) -OrderParticles[particles_List, ordering_] := Module[{indexRules}, - indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; - Return[particles[[ordering]] /. indexRules]; - ]; - -(* Essentially the same as above, but using the obtained rules, - transform a whole vertex expression, as returned by SARAH`Vertex[] *) -OrderVertex[vertex_, ordering_] := - Module[{indexRules, particles, expr, newVertex}, - indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; - - particles = vertex[[1]][[ordering]]; - expr = vertex[[2;;]]; - - newVertex = (Join[{particles}, expr] /. indexRules); - Return[newVertex]; - ]; - CachedVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := Module[{vertexPattern = ReplacePart[({#, ___} &) /@ Permutations[(#[___] &) /@ particles], @@ -309,31 +275,6 @@ If you add new kinds of vertices (e.g for new diagram types): FirstCase[vertexList, vertexPattern]; ]; -(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) -(* MemoizingVertex[] only works when __no__ indices are specified!!! *) -(* Use of memoization gives ~30% speedup for the MSSM! *) -memoizedVertices = {}; -MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := - Module[{memo, ordering, orderedParticles}, - (* First we sort the particles *) - ordering = Ordering[particles]; - orderedParticles = particles[[ordering]]; - - memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; - If[memo =!= {}, memo = memo[[1]], - (* Create a new entry *) - memo = SARAH`Vertex[orderedParticles, options]; - AppendTo[memoizedVertices, memo];]; - - (* Now return the particles to their original order *) - memo = OrderVertex[memo, Ordering[ordering]]; - Return[memo]]; - -MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; - -(* Test whether a SARAH Vertex[] result is nonzero (exact) *) -IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; - (* Returns the name of the coupling function that FlexibleSUSY generates for a specific vertex in a canonical order! *) NameOfCouplingFunction[particles_List] := From 0e1afe07531620ad643c27d84299d88ea8d70d50 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 19:49:14 +0100 Subject: [PATCH 013/158] Fixed lots of problems in CachedVertex[]. --- meta/EDM.m | 66 +++++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 1017243f3..0154d2425 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -75,7 +75,7 @@ If you add new kinds of vertices (e.g for new diagram types): "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> "typedef " <> ParticleToCXXName @ GetMuonFamily[] <> " MuonFamily;\n\n" <> - "// AntiParticles\n" <> + "// AntiFields\n" <> "template struct anti : public Particle\n" <> "{\n" <> IndentText @ @@ -84,11 +84,11 @@ If you add new kinds of vertices (e.g for new diagram types): "};\n" <> "template struct anti> { typedef P type; };\n\n" <> - "// Particles that are their own antiparticles\n" <> + "// Particles that are their own AntiFields\n" <> StringJoin @ Riffle[("template<> struct " <> "anti<" <> ParticleToCXXName[#] <> ">" <> " { typedef " <> ParticleToCXXName[#] <> " type; };" - &) /@ Select[particles, (# == AntiParticle[#] &)], + &) /@ Select[particles, (# == AntiField[#] &)], "\n"] ); @@ -102,7 +102,7 @@ If you add new kinds of vertices (e.g for new diagram types): "double charge( unsigned, EvaluationContext & );\n\n" <> StringJoin @ Riffle[ (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, - photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; + photonVertexParticles = {GetPhoton[], #, AntiField[#]}; "template<>\n" <> "double charge<" <> ParticleToCXXName[#] <> ">" <> If[particleDim === 1, "( ", @@ -201,7 +201,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[nPointFunctions]; ]; - (**************** End public interface *****************) (* Effectively generate all mass calculation functions *) @@ -222,16 +221,6 @@ If you add new kinds of vertices (e.g for new diagram types): (************************ Begin helper routines *******************************) -(* Return the name of the SARAH particle family containing the muon *) -GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, - SARAH`Electron, - Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], - {p_, {Description -> "Muon", ___}} -> p, 1][[1]] - ]; -(* If the muon has a generation index, return it, otherwise return Null. - e.g. CMSSMNoFV has no muon generation index *) -GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; - GetPhoton[] := SARAH`Photon; IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; @@ -246,15 +235,6 @@ If you add new kinds of vertices (e.g for new diagram types): ]; SetAttributes[StripLorentzIndices, {Listable}]; -(* Takes a SARAH particle and returns its antiparticle *) -AntiParticle[SARAH`bar[p_]] := p; -AntiParticle[Susyno`LieGroups`conj[p_]] := p; -AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, - If[IsScalar[pNoIndices] || IsVector[pNoIndices], - Susyno`LieGroups`conj[p], - SARAH`bar[p]]]; -SetAttributes[AntiParticle, {Listable}]; - (* Return a string corresponding to the c++ class name of the particle. Note that "bar" and "conj" get turned into anti<...>::type! *) ParticleToCXXName[p_] := SymbolName[p]; @@ -267,12 +247,18 @@ If you add new kinds of vertices (e.g for new diagram types): ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; -CachedVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := - Module[{vertexPattern = ReplacePart[({#, ___} &) /@ - Permutations[(#[___] &) /@ particles], +subIndexPattern = (ReplacePart[SARAH`subIndizes[[All, 1]], 0 -> Alternatives] -> ___); +AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; +AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; +AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; + +CachedVertex[particles_List] := + Module[{ + vertexPattern = ReplacePart[({#, ___} &) /@ + Permutations[AddIndexPattern /@ particles], 0 -> Alternatives], vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, - FirstCase[vertexList, vertexPattern]; + FirstCase[vertexList, vertexPattern] ]; (* Returns the name of the coupling function that FlexibleSUSY generates for @@ -327,11 +313,11 @@ If you add new kinds of vertices (e.g for new diagram types): If[createdVertices =!= Null, Return[createdVertices]]; contributingDiagrams = ContributingDiagrams[]; - vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; - AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; - vertices = DeleteDuplicates[vertices]; + vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ + Flatten @ contributingDiagrams[[All, 2]], 1]; - {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); + {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ + ((CreateVertexFunction[#, vertexRules] &) /@ vertices); vertexClassesPrototypes = Cases[vertexClassesPrototypes, Except[""]]; vertexClassesDefinitions = Cases[vertexClassesDefinitions, Except[""]]; @@ -346,10 +332,10 @@ If you add new kinds of vertices (e.g for new diagram types): IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := Module[{edmVertex1, photonVertex, edmVertex2}, - edmVertex1 = CachedVertex[{edmParticle, AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; - photonVertex = CachedVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; - edmVertex2 = CachedVertex[{AntiParticle[edmParticle], photonEmitter, exchangeParticle}]; - + edmVertex1 = CachedVertex[{edmParticle, AntiField[photonEmitter], AntiField[exchangeParticle]}]; + photonVertex = CachedVertex[{photonEmitter, GetPhoton[], AntiField[photonEmitter]}]; + edmVertex2 = CachedVertex[{photonEmitter, exchangeParticle, AntiField[edmParticle]}]; + edmVertex1 = StripLorentzIndices @ edmVertex1[[1]]; photonVertex = StripLorentzIndices @ photonVertex[[1]]; edmVertex2 = StripLorentzIndices @ edmVertex2[[1]]; @@ -362,9 +348,9 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{strippedParticles, scalars, vectors, fermions, scalarCount, vectorCount, fermionCount}, strippedParticles = Vertices`StripFieldIndices /@ particles; - scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiParticle[#]] &)]; - vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiParticle[#]] &)]; - fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiParticle[#]] &)]; + scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiField[#]] &)]; + vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiField[#]] &)]; + fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiField[#]] &)]; scalarCount = Length[scalars]; vectorCount = Length[vectors]; @@ -373,7 +359,7 @@ If you add new kinds of vertices (e.g for new diagram types): If[fermionCount === 2 && scalarCount === 1 && vectorCount === 0, Return[LeftAndRightComponentedVertex]]; If[fermionCount === 2 && scalarCount === 0 && vectorCount === 1, - If[fermions[[1]] === AntiParticle[fermions[[2]]], + If[fermions[[1]] === AntiField[fermions[[2]]], Return[LeftAndRightComponentedVertex]]]; If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, Return[SingleComponentedVertex]]; From ba9204b36fe966f599f5cf19a8ec5603bdb9a071 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:04:16 +0100 Subject: [PATCH 014/158] Rewrote CreateVertexFunction[] --- meta/EDM.m | 143 +++++++++++++++++++---------------------------------- 1 file changed, 50 insertions(+), 93 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 0154d2425..f2de5cca9 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -315,6 +315,8 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; + + (* TODO: Add every permutation of the above vertices *) {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); @@ -328,17 +330,12 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (* Returns the vertices that are present in the specified diagram. - This function should be overloaded for future diagram types. - IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) + This function should be overloaded for future diagram types. *) VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := Module[{edmVertex1, photonVertex, edmVertex2}, edmVertex1 = CachedVertex[{edmParticle, AntiField[photonEmitter], AntiField[exchangeParticle]}]; photonVertex = CachedVertex[{photonEmitter, GetPhoton[], AntiField[photonEmitter]}]; edmVertex2 = CachedVertex[{photonEmitter, exchangeParticle, AntiField[edmParticle]}]; - - edmVertex1 = StripLorentzIndices @ edmVertex1[[1]]; - photonVertex = StripLorentzIndices @ photonVertex[[1]]; - edmVertex2 = StripLorentzIndices @ edmVertex2[[1]]; Return[{edmVertex1, photonVertex, edmVertex2}]; ]; @@ -380,51 +377,56 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (* Creates the actual c++ code for a vertex with given particles. + If the c++ for the particle list has already been created, two + empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) -vertexFunctions = {}; +createdVertexFunctions = {}; CreateVertexFunction[indexedParticles_List, vertexRules_List] := - Module[{prototypes, definitions = "", ordering, particles, orderedParticles, - orderedIndexedParticles, addSpacing = True}, - particles = Vertices`StripFieldIndices /@ indexedParticles; - If[MemberQ[vertexFunctions, particles], Return[{"",""}]]; - - ordering = Ordering[particles]; - orderedParticles = particles[[ordering]]; - orderedIndexedParticles = OrderParticles[indexedParticles, ordering]; - - If[MemberQ[vertexFunctions, orderedParticles] === True, - (* There is already an entry *) - prototypes = ""; - addSpacing = False, - (* There is no entry yet, create it *) - {prototypes, definitions} = CreateOrderedVertexFunction[orderedIndexedParticles, vertexRules]; - AppendTo[vertexFunctions, orderedParticles]; - ]; - - If[ordering === Table[i, {i, 1, Length[ordering]}], - Return[{prototypes, definitions}]]; - - orderedVertexFunction = ("VertexFunction<" <> - StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> - ">"); - - prototypes = (prototypes <> If[addSpacing, "\n\n", ""] <> - "template<> struct VertexFunctionData<" <> - StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> - ">\n" <> - "{\n" <> - IndentText @ - ("static const bool is_permutation = true;\n" <> - "typedef " <> orderedVertexFunction <> " orig_type;\n" <> - "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ (Ordering[ordering] - 1), ", "] <> - "> particlePermutation;\n" - ) <> - "};"); - - AppendTo[vertexFunctions, particles]; - Return[{prototypes, definitions}]; + Module[{prototype, definition, + particles = Vertices`StripFieldIndices /@ indexedParticles, + parsedVertex, dataClassName, functionClassName, particleIndexStartF, + particleIndexStart, indexBounds}, + If[MemberQ[createdVertexFunctions, particles], Return[{"",""}]]; + + parsedVertex = ParseVertex[indexedParticles, vertexRules]; + dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; + functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; + + particleIndexStartF[1] = 0; + particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; + particleIndexStartF[Length[particles]+1] = NumberOfIndices[parsedVertex]; + + particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[particles] + 1}]; + + prototype = ("template<> struct " <> dataClassName <> "\n" <> + "{\n" <> + IndentText @ + ("static const bool is_permutation = false;\n" <> + "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> + "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> + "typedef boost::mpl::vector_c + StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> + "> particleIndexStart;\n" <> + "static const index_bounds indexB;\n" + ) <> + "};"); + + indexBounds = IndexBounds[parsedVertex]; + + If[NumberOfIndices[parsedVertex] =!= 0, + prototype = (prototype <> "\n" <> + "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" + );]; + definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> + functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> + "{\n" <> + IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> + "}"); + + AppendTo[vertexFunctions, particles]; ]; (* Creates local declarations of field indices, whose values are taken @@ -525,51 +527,6 @@ If you add new kinds of vertices (e.g for new diagram types): VertexFunctionBody[parsedVertex_ParsedVertex] := parsedVertex[[4]]; (** End getters **) -(* Create the c++ code for a canonically ordered vertex *) -CreateOrderedVertexFunction[orderedIndexedParticles_List, vertexRules_List] := - Module[{prototype, definition, orderedParticles, dataClassName, functionClassName, - parsedVertex, particleIndexStartF, particleIndexStart, indexBounds}, - orderedParticles = Vertices`StripFieldIndices /@ orderedIndexedParticles; - parsedVertex = ParseVertex[orderedIndexedParticles, vertexRules]; - dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; - functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; - - particleIndexStartF[1] = 0; - particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; - particleIndexStartF[Length[orderedParticles]+1] = NumberOfIndices[parsedVertex]; - - particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[orderedParticles] + 1}]; - - prototype = ("template<> struct " <> dataClassName <> "\n" <> - "{\n" <> - IndentText @ - ("static const bool is_permutation = false;\n" <> - "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> - "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> - "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> - "> particleIndexStart;\n" <> - "static const index_bounds indexB;\n" - ) <> - "};"); - - indexBounds = IndexBounds[parsedVertex]; - - If[NumberOfIndices[parsedVertex] =!= 0, - prototype = (prototype <> "\n" <> - "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" - );]; - definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> - functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> - "{\n" <> - IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> - "}"); - - Return[{prototype, definition}]; - ]; - (* Find all contributing diagrams *) cachedContributingDiagrams = Null; ContributingDiagrams[] := From ba8fc62e2629315ecd0abda8e0401d93c4ecf1e3 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:04:44 +0100 Subject: [PATCH 015/158] Fixed typo --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index f2de5cca9..e404e519c 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -426,7 +426,7 @@ If you add new kinds of vertices (e.g for new diagram types): IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); - AppendTo[vertexFunctions, particles]; + AppendTo[createdVertexFunctions, particles]; ]; (* Creates local declarations of field indices, whose values are taken From 7f7b99771ea18c40c45f335571a9d219085df285 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:13:02 +0100 Subject: [PATCH 016/158] First steps towards integrating the EDM module. --- meta/FlexibleSUSY.m | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index fd71aa57a..d50b9a0d2 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1443,6 +1443,35 @@ corresponding tadpole is real or imaginary (only in models with CP } ]; ]; +(* Write the EDM c++ files *) +WriteEDMClass[vertexRules_List, files_List] := +Module[{edmParticles, particles, chargeGetters, diagrams, vertexFunctionData, + definitions, calculationCode}, + edmParticles = {SARAH`Electron}; + + SetEDMParticles[edmParticles]; + + Print[EDM`CreateVertices[vertexRules]]; + (* + particles = EDM`CreateParticles[]; + chargeGetters = EDM`CreateChargeGetters[]; + diagrams = EDM`CreateDiagrams[]; + + vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; + definitions = EDM`CreateDefinitions[vertexRules]; + calculationCode = EDM`CreateCalculation[]; + + WriteOut`ReplaceInFiles[files, + { "@EDM_Particles@" -> particles, + "@EDM_ChargeGetters@" -> chargeGetters, + "@EDM_Diagrams@" -> diagrams, + "@EDM_VertexFunctionData@" -> vertexFunctionData, + "@EDM_Definitions@" -> definitions, + "@EDM_Calculation@" -> IndentText[calculationCode], + Sequence @@ GeneralReplacementRules[] + } ];*) + ]; + EnableForBVPSolver[solver_, statements_String] := Module[{result = "#ifdef "}, Switch[solver, @@ -1997,6 +2026,9 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; +(* Get all nPointFunctions that EDM needs *) +PrepareEDM[] := EDM`NPointFunctions[]; + PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2144,7 +2176,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, + gmm2Vertices = {}, edmVertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2191,6 +2223,8 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; + (* EDM vertices *) + edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; @@ -2700,10 +2734,17 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; +<<<<<<< 2f6a3062c3ce3b875f83065972915e93fa9ee0fd Put[vertexRules = Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; +======= + Put[vertexRules = + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], + vertexRuleFileName], + vertexRules = Get[vertexRuleFileName]; +>>>>>>> First steps towards integrating the EDM module. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; From 1a3c569998b77eea1e5573910835cb960a15a8da Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:14:11 +0100 Subject: [PATCH 017/158] First attempt at running EDM. --- meta/FlexibleSUSY.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index d50b9a0d2..3e4d565d4 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2945,7 +2945,11 @@ corresponding tadpole is real or imaginary (only in models with CP {{FileNameJoin[{$flexiblesusyTemplateDir, "a_muon.hpp.in"}], FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.hpp"}]}, {FileNameJoin[{$flexiblesusyTemplateDir, "a_muon.cpp.in"}], - FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; + + Print["Creating class EDM"]; + WriteGMuonMinus2Class[vertexRules, + {}]; PrintHeadline["Creating Mathematica interface"]; Print["Creating LibraryLink ", FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> ".mx"}], " ..."]; From 75558fe2f30f3b814e399c3aa987bd242307010d Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:18:37 +0100 Subject: [PATCH 018/158] rewrote NPointFunctions[]. --- meta/EDM.m | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index e404e519c..2233ed3c7 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -189,13 +189,8 @@ If you add new kinds of vertices (e.g for new diagram types): contributingDiagrams = ContributingDiagrams[]; - vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; - AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; - vertices = DeleteDuplicates[vertices]; - - vertices = (OrderParticles[#, Ordering[(Vertices`StripFieldIndices /@ #)]] &) /@ vertices; - vertices = DeleteDuplicates[vertices, - (Vertices`StripFieldIndices[#1] === Vertices`StripFieldIndices[#2] &)]; + vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ + Flatten @ contributingDiagrams[[All, 2]], 1]; nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertices)]; Return[nPointFunctions]; From 9f2c481674ce7df112d891e750be840a0b7b012e Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:52:23 +0100 Subject: [PATCH 019/158] Fixed NPointFunctions[]. Added next TODO. --- meta/EDM.m | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 2233ed3c7..f2a43abbb 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -184,15 +184,16 @@ If you add new kinds of vertices (e.g for new diagram types): nPointFunctions = Null; NPointFunctions[] := - Module[{contributingDiagrams, vertices}, + Module[{contributingDiagrams, vertices, vertexParticles}, If[nPointFunctions =!= Null, Return[nPointFunctions]]; contributingDiagrams = ContributingDiagrams[]; vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - - nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertices)]; + vertexParticles = vertices[[All, 1]]; + + nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertexParticles)]; Return[nPointFunctions]; ]; @@ -355,7 +356,12 @@ If you add new kinds of vertices (e.g for new diagram types): Return[LeftAndRightComponentedVertex]]]; If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, Return[SingleComponentedVertex]]; - + + (* TODO: Add support for 1 scalar, two vector vertices *) + + Print[particles]; + Print[fermionCount, scalarCount, vectorCount]; + Return[Null]; ]; From cf8e3bdb5d84db4368e315e68f2012e33a864f6f Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 7 Nov 2016 16:31:07 +0100 Subject: [PATCH 020/158] Some small fixes --- meta/EDM.m | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index f2a43abbb..48d01c176 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -5,7 +5,7 @@ SetEDMParticles::usage="Set the particles for which the EDMs shall be calculated."; CreateParticles::usage="Returns the c++ code that contains all particle classes"; -CreateEDMParticleFunctions::usage="Returns the c++ code that contains all EDM particle functions"; +CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM particles."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; @@ -73,7 +73,6 @@ If you add new kinds of vertices (e.g for new diagram types): &) /@ particles, "\n"] <> "\n\n" <> "// Special particle families\n" <> "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> - "typedef " <> ParticleToCXXName @ GetMuonFamily[] <> " MuonFamily;\n\n" <> "// AntiFields\n" <> "template struct anti : public Particle\n" <> @@ -122,8 +121,7 @@ If you add new kinds of vertices (e.g for new diagram types): CreateDiagrams[] := Module[{diagramTypes, diagramTypeHeads, code}, - diagrams = contributingDiagramTypes; - diagramHeads = DeleteDuplicates @ (Head /@ diagrams); + diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); code = "// The different diagram types that contribute to the muon magnetic moment\n"; code = (code <> @@ -134,7 +132,7 @@ If you add new kinds of vertices (e.g for new diagram types): code = (code <> "// Indexed diagram types\n" <> StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> "<" <> ToString @ #[[1]] <> "> {};" &) - /@ diagrams, "\n"]); + /@ contributingDiagramTypes, "\n"]); code = (code <> "\n\n" <> StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingDiagramTypes, "\n\n"]); @@ -243,16 +241,15 @@ If you add new kinds of vertices (e.g for new diagram types): ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; -subIndexPattern = (ReplacePart[SARAH`subIndizes[[All, 1]], 0 -> Alternatives] -> ___); +subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; CachedVertex[particles_List] := Module[{ - vertexPattern = ReplacePart[({#, ___} &) /@ + vertexPattern = Alternatives @@ ({#, ___} &) /@ Permutations[AddIndexPattern /@ particles], - 0 -> Alternatives], vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, FirstCase[vertexList, vertexPattern] ]; @@ -369,7 +366,7 @@ If you add new kinds of vertices (e.g for new diagram types): CouplingsForParticles[particles_List] := Module[{vertexType, couplings}, vertexType = VertexTypeForParticles[particles]; - couplings = {ReplacePart[particles, 0 -> SARAH`Cp]}; + couplings = {SARAH`Cp @@ particles}; couplings = Switch[vertexType, SingleComponentedVertex, couplings, @@ -538,8 +535,8 @@ If you add new kinds of vertices (e.g for new diagram types): /@ contributingDiagramTypes , 1]; cachedContributingDiagrams = ({#, Union @ - ReplacePart[Cases[cachedContributingDiagrams, - {#, diagrams_List} -> diagrams], 0 -> Sequence]} &) /@ edmParticles; + (Sequence @@ Cases[cachedContributingDiagrams, + {#, diagrams_List} -> diagrams])} &) /@ edmParticles; Return[cachedContributingDiagrams]; ]; @@ -553,7 +550,7 @@ If you add new kinds of vertices (e.g for new diagram types): ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> ToString @ #[[1,1]] <> ">, " <> - StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> + StringJoin @ (Riffle[ParticleToCXXName /@ List @@ #[[2;;]], ", "]) <> ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; From 3cb7f914d6ab3c5318c1b8abf3aa10852c9d7842 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 14 Nov 2016 22:13:09 +0100 Subject: [PATCH 021/158] Too much to describe... --- meta/EDM.m | 627 +++++++++++++++++++------------------------- meta/FlexibleSUSY.m | 29 +- 2 files changed, 297 insertions(+), 359 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 48d01c176..176671bbd 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -1,309 +1,249 @@ -BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "LoopMasses`", "Vertices`"}]; +BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "Vertices`"}]; -Test::usage=""; +(* This module generates c++ code that calculates electric dipole moments of fields *) -SetEDMParticles::usage="Set the particles for which the EDMs shall be calculated."; +SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; -CreateParticles::usage="Returns the c++ code that contains all particle classes"; -CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM particles."; +CreateFields::usage="Returns the c++ code that contains all field fields"; +CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM fields."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; - -CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; - CreateDefinitions::usage="Returns the c++ that contains all function definitions" +CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; -(******** IMPORTANT NOTES: +(******** TODO: IMPORTANT NOTES: If you add new kinds of vertices (e.g for new diagram types): - Add the new types to vertexTypes - - Expand CouplingsForParticles[] and VertexTypeForParticles[] accordingly + - Expand CouplingsForFields[] and VertexTypeForFields[] accordingly - Write the c++ class for the new vertex type - + When adding support for new diagram types, do the following: - - Add the new types to contributingDiagramTypes + - Add the new types to diagramTypes - Write new overloads for CreateDiagramEvaluatorClass[], ContributingDiagramsOfType[] and VerticesForDiagram[] - Write the necessary c++ code: loop functions, DiagramEvaluator<> specialisations **********) -(* TODO: privatize interface again Begin["`Private`"]; *) - (************* Begin public interface *******************) -edmParticles = Null; -SetEDMParticles[particles_List] := (edmParticles = particles;) - -IsSMParticle[particle_] := - SARAH`SMQ[particle] || TreeMasses`IsSMGoldstone[particle]; - -CreateSMParticleFlags[particle_] := - Module[{result = "", i, - numberOfGenerations = TreeMasses`GetDimension[particle]}, - For[i = 1, i <= numberOfGenerations, i++, - If[i > 1, result = result <> ", ";]; - If[IsSMParticle[particle[i]] === True || - IsSMParticle[particle] === True, - result = result <> "true";, - result = result <> "false"; - ]; - ]; - "{ " <> result <> " }" - ]; - -(* Create c++ classes for all particles *) -CreateParticles[] := - Module[{particles, code}, - (* Get a list of all particles *) - particles = TreeMasses`GetParticles[]; - - code = ("// Particles (SARAH-style)\n" <> - "struct Particle {};\n\n" <> - - StringJoin @ Riffle[("struct " <> ParticleToCXXName[#] <> - ": public Particle {\n" <> - TextFormatting`IndentText[ - "static const unsigned numberOfGenerations = " <> - ToString @ TreeMasses`GetDimension[#] <> ";\n" <> - "static const bool is_sm_particle[numberOfGenerations];" - ] <> "\n};\n" <> - "const bool " <> ParticleToCXXName[#] <> "::is_sm_particle[" <> - ParticleToCXXName[#] <> "::numberOfGenerations] = " <> - CreateSMParticleFlags[#] <> ";\n" - &) /@ particles, "\n"] <> "\n\n" <> - "// Special particle families\n" <> - "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> - - "// AntiFields\n" <> - "template struct anti : public Particle\n" <> - "{\n" <> - IndentText @ - ("static const unsigned numberOfGenerations = P::numberOfGenerations;\n" <> - "typedef anti

type;\n") <> - "};\n" <> - "template struct anti> { typedef P type; };\n\n" <> - - "// Particles that are their own AntiFields\n" <> - StringJoin @ Riffle[("template<> struct " <> - "anti<" <> ParticleToCXXName[#] <> ">" <> - " { typedef " <> ParticleToCXXName[#] <> " type; };" - &) /@ Select[particles, (# == AntiField[#] &)], - "\n"] - ); - - Return[code]; - ]; +edmFields = Null; +SetEDMFields[fields_List] := (edmFields = fields;) + +CreateFields[] := +Module[{fields, code}, + fields = TreeMasses`GetParticles[]; + + code = ("struct Field {};\n\n" <> + + StringJoin @ Riffle[("struct " <> CXXNameOfField[#] <> + ": public Field {\n" <> + TextFormatting`IndentText["static const unsigned numberOfGenerations = " <> + ToString @ TreeMasses`GetDimension[#] <> ";\n"] <> + "};\n" &) /@ fields, "\n"] <> "\n\n" <> + "// Special field families\n" <> + "using Photon = " <> CXXNameOfField @ SARAH`Photon <> ";\n" <> + + "// Anti fields\n" <> + "template struct anti : public Field\n" <> + "{\n" <> + IndentText @ + ("static const unsigned numberOfGenerations = P::numberOfGenerations;\n" <> + "using type = anti

;\n") <> + "};\n" <> + "template struct anti> { using type = P; };\n\n" <> + + "// Fields that are their own anti fields\n" <> + StringJoin @ Riffle[("template<> struct " <> + "anti<" <> CXXNameOfField[#] <> ">" <> + " { using type = " <> CXXNameOfField[#] <> "; };" + &) /@ Select[fields, (# == SARAH`AntiField[#] &)], + "\n"] + ); + + Return[code]; + ]; CreateChargeGetters[] := - "template\n" <> - "double charge( EvaluationContext & );\n\n" <> - "template\n" <> - "double charge( unsigned, EvaluationContext & );\n\n" <> - StringJoin @ Riffle[ - (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, - photonVertexParticles = {GetPhoton[], #, AntiField[#]}; - "template<>\n" <> - "double charge<" <> ParticleToCXXName[#] <> ">" <> - If[particleDim === 1, "( ", - "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> - IndentText[ - "typedef VertexFunction<" <> - StringJoin @ Riffle[ParticleToCXXName /@ photonVertexParticles, ", "] <> - "> VF;\n" <> - If[particleDim === 1, - "const std::array indices{};\n", - "const std::array indices{ index, index };\n" - ] <> - "return VF::vertex(indices, context).left().real();" - ] <> "\n}" - ] &) /@ edmParticles, - "\n\n"] +"template\n" <> +"double charge( EvaluationContext & );\n\n" <> +"template\n" <> +"double charge( unsigned, EvaluationContext & );\n\n" <> +StringJoin @ Riffle[(Module[{photonVertexFields, fieldDim = TreeMasses`GetDimension[#]}, + photonVertexFields = {SARAH`Photon, #, SARAH`AntiField[#]}; + "template<>\n" <> + "double charge<" <> CXXNameOfField[#] <> ">" <> + If[fieldDim === 1, "( ", + "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> + IndentText["using VF = VertexFunction<" <> + StringJoin @ Riffle[CXXNameOfField /@ photonVertexFields, ", "] <> + ">;\n" <> + If[fieldDim === 1, + "constexpr std::array indices{};\n", + "const std::array indices{ index, index };\n" + ] <> + "return VF::vertex(indices, context).left().real();" + ] <> "\n}" + ] &) /@ edmFields, + "\n\n"] CreateDiagrams[] := - Module[{diagramTypes, diagramTypeHeads, code}, - diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); - - code = "// The different diagram types that contribute to the muon magnetic moment\n"; - code = (code <> - StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) - /@ diagramHeads, "\n"] <> - "\n\n"); - - code = (code <> "// Indexed diagram types\n" <> - StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> - "<" <> ToString @ #[[1]] <> "> {};" &) - /@ contributingDiagramTypes, "\n"]); - - code = (code <> "\n\n" <> - StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingDiagramTypes, "\n\n"]); - - Return[code]; - ]; - -CreateDiagramEvaluatorClass[type_OneLoopDiagram] := - ("template\n" <> - "struct DiagramEvaluator - ToString @ type[[1]] <> - ">, EDMParticle, PhotonEmitter, ExchangeParticle>\n" <> - "{ static double value(EvaluationContext& context); };"); +Module[{diagramSubIndices, diagramTypeHeads, code}, + + code = StringJoin @ Riffle[(Module[{diagramType = #}, + "template class " <> SymbolName[diagramType] <> ";\n" <> + StringJoin @ Riffle[("template<> class " <> SymbolName[diagramType] <> + "<" <> ToString @ # <> "> {};" + &) /@ diagramSubTypes[diagramType], "\n"] + ] &) /@ diagramTypes, "\n\n"]; + + code = (code <> "\n\n" <> + StringJoin @ Riffle[(Module[{diagramType = #}, + StringJoin @ Riffle[ + ("template\n" <> + "struct DiagramEvaluator<" <> SymbolName[diagramType] <> + "<" <> ToString @ # <> + ">, EDMField, PhotonEmitter, ExchangeField>\n" <> + "{ static double value(EvaluationContext& context); };" + &) /@ diagramSubTypes[diagramType], "\n\n"]] &) /@ diagramTypes, "\n\n"] + ); + + Return[code]; + ]; CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; -calculationCode = Null; -CreateCalculation[] := - Module[{code, evaluators}, - (* If we have been here before return the old result *) - If[calculationCode =!= Null, Return[calculationCode]]; - - evaluators = ConcreteDiagramEvaluators[]; - - code = "/********** EDM.m generated calculation code **********/\n\n" <> - "template double edm( void );\n\n"; - - code = code <> StringJoin @ Riffle[ - Module[{pEvaluators = Cases[evaluators, {#, ev_List} -> ev]}, - "template<> double edm<" <> ParticleToCXXName[#] <> ">( void )\n" <> - "{\n" <> - IndentText["EvaluationContext context{ model };\n" <> - "double val = 0.0\n\n;" <> - StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ pEvaluators, - "\n"] <> "\n\n" <> - "return val;" - ] <> - "}"] & /@ evaluators, "\n\n"]; - - calculationCode = code; - Return[code]; - ]; - CreateDefinitions[vertexRules_List] := - (CreateEvaluationContextSpecializations[] <> "\n\n" <> - CreateVertices[vertexRules][[2]]); +(CreateEvaluationContextSpecializations[] <> "\n\n" <> + CreateVertices[vertexRules][[2]]); -nPointFunctions = Null; -NPointFunctions[] := - Module[{contributingDiagrams, vertices, vertexParticles}, - If[nPointFunctions =!= Null, Return[nPointFunctions]]; - - contributingDiagrams = ContributingDiagrams[]; +CreateCalculation[] := +Module[{code, evaluators}, + evaluators = ConcreteDiagramEvaluators[]; + + code = "template double edm( void );\n\n"; + code = (code <> + StringJoin @ Riffle[Module[{field = #[[1]], + fieldEvaluators = #[[2]]}, + "template<> double edm<" <> CXXNameOfField[field] <> ">( void )\n" <> + "{\n" <> + IndentText["EvaluationContext context{ model };\n" <> + "double val = 0.0;\n\n" <> + StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(context);" &) /@ fieldEvaluators, "\n"] <> "\n\n" <> + "return val;" + ] <> + "\n}"] & /@ evaluators, "\n\n"]); + + Return[code]; + ]; - vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ - Flatten @ contributingDiagrams[[All, 2]], 1]; - vertexParticles = vertices[[All, 1]]; - - nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertexParticles)]; - Return[nPointFunctions]; - ]; +NPointFunctions[] := +Module[{contributingDiagrams, vertices}, + contributingDiagrams = ContributingDiagrams[]; + + vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ + Flatten @ contributingDiagrams[[All, 2]], 1]; + + Flatten[(Null[Null, #] &) /@ ((CouplingsForFields[#] &) /@ vertices)] + ]; (**************** End public interface *****************) +(* TODO: privatize interface again Begin["`Private`"]; *) -(* Effectively generate all mass calculation functions *) -CreateEvaluationContextSpecializations[] := -Module[{particles, code}, - particles = TreeMasses`GetParticles[]; - particles = Select[particles, (! TreeMasses`IsGhost[#] &)]; - - code = (StringJoin @ - Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> - If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> - "{ return model.get_M" <> ParticleToCXXName[#] <> - If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" - &) /@ particles, "\n\n"]); - - Return[code]; - ]; - -(************************ Begin helper routines *******************************) +(* The supported vertex types. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; -GetPhoton[] := SARAH`Photon; +(* The supported diagram types. + They have the same names as their c++ counterparts. *) +diagramTypes = { + OneLoopDiagram +}; -IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; +(* The supported diagram types. + Indexed by the diagram type, gives a set of (c++-compatible) unsigned integer indices. *) +diagramSubTypes[OneLoopDiagram] = { 0, 1 }; (* 0: fermion emits photon, exchange field is a scalar + 1: scalar emits photon, exchange field is a fermion *) -StripLorentzIndices[p_Symbol] := p; -StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; -StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; -StripLorentzIndices[p_] := Module[{remainingIndices}, - remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; - If[Length[remainingIndices] === 0, Head[p], - Head[p][remainingIndices]] - ]; -SetAttributes[StripLorentzIndices, {Listable}]; +(**************** CXX conversion routines ***************) -(* Return a string corresponding to the c++ class name of the particle. +(* Return a string corresponding to the c++ class name of the field. Note that "bar" and "conj" get turned into anti<...>::type! *) -ParticleToCXXName[p_] := SymbolName[p]; -ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +CXXNameOfField[p_] := SymbolName[p]; +CXXNameOfField[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +CXXNameOfField[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -(* Return a string corresponding to the name of the particle. - Note that "bar" and "conj" are left as they are! *) -ParticleToSARAHString[p_] := SymbolName[p]; -ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; -ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; +(**************** Other Functions ***************) subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; -AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; - -CachedVertex[particles_List] := - Module[{ - vertexPattern = Alternatives @@ ({#, ___} &) /@ - Permutations[AddIndexPattern /@ particles], - vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, - FirstCase[vertexList, vertexPattern] - ]; - -(* Returns the name of the coupling function that FlexibleSUSY generates for - a specific vertex in a canonical order! *) -NameOfCouplingFunction[particles_List] := -((* FIXME: Not upwards compatible if naming conventions change *) - "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); +AddIndexPattern[field_] := SARAH`getFull[SARAH`getBlank[field]] /. subIndexPattern; + +CachedVertex[fields_List] := +Module[{ + vertexPattern = Alternatives @@ ({#, ___} &) /@ + Permutations[AddIndexPattern /@ fields], + vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[fields]]}, + FirstCase[vertexList, vertexPattern] + ]; -(********************** End helper routines **************************) +CreateEvaluationContextSpecializations[] := +Module[{fields, code}, + fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; -(* The different vertex types that are supported. - They have the same names as their c++ counterparts. *) -vertexTypes = { - SingleComponentedVertex, - LeftAndRightComponentedVertex -}; + code = (StringJoin @ + Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> + If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> + "{ return model.get_M" <> CXXNameOfField[#] <> + If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" + &) /@ fields, "\n\n"]); -(* The different diagram types that should be taken into consideration *) -(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) -(* There is no bounds check done on the integers, so they have to fit - into a standard c++ unsigned (!) int *) -contributingDiagramTypes = { - OneLoopDiagram[0] -}; + Return[code]; + ]; -(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +(* Find all diagrams of the type type_, testing all corresponding combinations of fields *) (* IMPORTANT: Return value should have the format - {{edmParticle1, {Diagram[DIAGRAMTYPENAME[_Integer], Particles___], Diagram[...], ...}}, - {edmParticle2, {...}}, + {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, + {edmField2, {...}}, ...} *) - -ContributingDiagramsOfType[OneLoopDiagram[0]] := - Module[{edmParticle = #, diagrams = SARAH`InsFields[ +ContributingDiagramsOfType[OneLoopDiagram] := + Module[{edmField = #, diagrams = SARAH`InsFields[ {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], SARAH`AntiField[SARAH`FieldToInsert[2]]], - C[SARAH`FieldToInsert[1], GetPhoton[], + C[SARAH`FieldToInsert[1], SARAH`Photon, SARAH`AntiField[SARAH`FieldToInsert[1]]], C[SARAH`FieldToInsert[1], SARAH`FieldToInsert[2], SARAH`AntiField[#]]}, - {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}]}, - {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[2,1]], - exchangeParticle = #[[2,2]]}, - Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] - &) /@ diagrams]}] & /@ edmParticles; + {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}], + subtypedDiagrams, uniqueDiagrams}, + + subtypedDiagrams = (Module[{photonEmitter = #[[2,1]], + exchangeField = #[[2,2]], + subType}, + subType = If[TreeMasses`IsFermion[photonEmitter] && + TreeMasses`IsScalar[exchangeField], + 0, + If[TreeMasses`IsScalar[photonEmitter] && + TreeMasses`IsFermion[exchangeField], + 1]]; + If[subType === Null, + Null, + Diagram[OneLoopDiagram[subType], edmField, photonEmitter, exchangeField]] + ] + &) /@ diagrams; + uniqueDiagrams = DeleteDuplicates @ Cases[subtypedDiagrams, Except[Null]]; + + {edmField, uniqueDiagrams}] & /@ edmFields; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. The returned value is a list {prototypes, definitions}. *) -createdVertices = Null; CreateVertices[vertexRules_List] := Module[{contributingDiagrams, vertices, vertexClassesPrototypes, vertexClassesDefinitions}, - If[createdVertices =!= Null, Return[createdVertices]]; contributingDiagrams = ContributingDiagrams[]; vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ @@ -313,99 +253,81 @@ If you add new kinds of vertices (e.g for new diagram types): {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); - vertexClassesPrototypes = Cases[vertexClassesPrototypes, Except[""]]; - vertexClassesDefinitions = Cases[vertexClassesDefinitions, Except[""]]; - - createdVertices = {vertexClassesPrototypes, vertexClassesDefinitions}; - createdVertices = (StringJoin @ Riffle[#, "\n\n"] &) /@ createdVertices; - Return[createdVertices]; + (StringJoin @ Riffle[#, "\n\n"] &) /@ {vertexClassesPrototypes, vertexClassesDefinitions} ]; (* Returns the vertices that are present in the specified diagram. This function should be overloaded for future diagram types. *) -VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := - Module[{edmVertex1, photonVertex, edmVertex2}, - edmVertex1 = CachedVertex[{edmParticle, AntiField[photonEmitter], AntiField[exchangeParticle]}]; - photonVertex = CachedVertex[{photonEmitter, GetPhoton[], AntiField[photonEmitter]}]; - edmVertex2 = CachedVertex[{photonEmitter, exchangeParticle, AntiField[edmParticle]}]; - - Return[{edmVertex1, photonVertex, edmVertex2}]; +VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmField_, photonEmitter_, exchangeField_]] := + Module[{edmVertex}, + edmVertex = {edmField, SARAH`AntiField[photonEmitter], SARAH`AntiField[exchangeField]}; + Return[{edmVertex}]; ]; -(* Returns the vertex type for a vertex with a given list of particles *) -VertexTypeForParticles[particles_List] := - Module[{strippedParticles, scalars, vectors, fermions, scalarCount, vectorCount, fermionCount}, - strippedParticles = Vertices`StripFieldIndices /@ particles; - - scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiField[#]] &)]; - vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiField[#]] &)]; - fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiField[#]] &)]; - - scalarCount = Length[scalars]; - vectorCount = Length[vectors]; - fermionCount = Length[fermions]; - +(* Returns the vertex type for a vertex with a given list of fields *) +VertexTypeForFields[fields_List] := + Module[{fermions, scalarCount, vectorCount, fermionCount}, + fermions = Select[fields, TreeMasses`IsFermion]; + + scalarCount = Length @ Select[fields, TreeMasses`IsScalar]; + vectorCount = Length @ Select[fields, TreeMasses`IsVector]; + fermionCount = Length @ fermions; + If[fermionCount === 2 && scalarCount === 1 && vectorCount === 0, Return[LeftAndRightComponentedVertex]]; If[fermionCount === 2 && scalarCount === 0 && vectorCount === 1, - If[fermions[[1]] === AntiField[fermions[[2]]], + If[fermions[[1]] === SARAH`AntiField[fermions[[2]]], Return[LeftAndRightComponentedVertex]]]; If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, Return[SingleComponentedVertex]]; - (* TODO: Add support for 1 scalar, two vector vertices *) - - Print[particles]; - Print[fermionCount, scalarCount, vectorCount]; - Return[Null]; ]; -(* Returns the different SARAH`Cp coupling parts for a vertex with a given list of particles *) -CouplingsForParticles[particles_List] := +(* Returns the different SARAH`Cp coupling parts for a vertex with a given list of fields *) +CouplingsForFields[fields_List] := Module[{vertexType, couplings}, - vertexType = VertexTypeForParticles[particles]; - couplings = {SARAH`Cp @@ particles}; + vertexType = VertexTypeForFields[fields]; + + couplings = {SARAH`Cp @@ fields}; - couplings = Switch[vertexType, - SingleComponentedVertex, couplings, - LeftAndRightComponentedVertex, {couplings[[1]][SARAH`PL], couplings[[1]][SARAH`PR]}]; - Return[couplings]; + Switch[vertexType, + SingleComponentedVertex, couplings, + LeftAndRightComponentedVertex, {couplings[[1]][SARAH`PL], couplings[[1]][SARAH`PR]}] ]; -(* Creates the actual c++ code for a vertex with given particles. - If the c++ for the particle list has already been created, two +(* Creates the actual c++ code for a vertex with given fields. + If the c++ for the field list has already been created, two empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) createdVertexFunctions = {}; -CreateVertexFunction[indexedParticles_List, vertexRules_List] := +CreateVertexFunction[fields_List, vertexRules_List] := Module[{prototype, definition, - particles = Vertices`StripFieldIndices /@ indexedParticles, - parsedVertex, dataClassName, functionClassName, particleIndexStartF, - particleIndexStart, indexBounds}, - If[MemberQ[createdVertexFunctions, particles], Return[{"",""}]]; - - parsedVertex = ParseVertex[indexedParticles, vertexRules]; - dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; - functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; + parsedVertex, dataClassName, functionClassName, fieldIndexStartF, + fieldIndexStart, indexBounds}, + If[MemberQ[createdVertexFunctions, fields], Return[{"",""}]]; + + parsedVertex = ParseVertex[fields, vertexRules]; - particleIndexStartF[1] = 0; - particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; - particleIndexStartF[Length[particles]+1] = NumberOfIndices[parsedVertex]; + dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[CXXNameOfField /@ fields, ", "] <> ">"; + functionClassName = "VertexFunction<" <> StringJoin @ Riffle[CXXNameOfField /@ fields, ", "] <> ">"; - particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[particles] + 1}]; + fieldIndexStartF[1] = 0; + fieldIndexStartF[pIndex_] := fieldIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; + fieldIndexStartF[Length[fields]+1] = NumberOfIndices[parsedVertex]; + + fieldIndexStart = Table[fieldIndexStartF[i], {i, 1, Length[fields] + 1}]; prototype = ("template<> struct " <> dataClassName <> "\n" <> "{\n" <> IndentText @ - ("static const bool is_permutation = false;\n" <> - "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> + ("typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> - "> particleIndexStart;\n" <> + StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + "> fieldIndexStart;\n" <> "static const index_bounds indexB;\n" ) <> "};"); @@ -424,22 +346,23 @@ If you add new kinds of vertices (e.g for new diagram types): IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); - AppendTo[createdVertexFunctions, particles]; + AppendTo[createdVertexFunctions, fields]; + Return[{prototype, definition}]; ]; (* Creates local declarations of field indices, whose values are taken from the elements of `arrayName'. *) -DeclareIndices[indexedParticles_List, arrayName_String] := +DeclareIndices[indexedFields_List, arrayName_String] := Module[{p, total = 0, fieldIndexList, decl = ""}, DeclareIndex[idx_, num_Integer, an_String] := ( "const unsigned " <> CConversion`ToValidCSymbolString[idx] <> " = " <> an <> "[" <> ToString[num] <> "];\n"); - For[p = 1, p <= Length[indexedParticles], p++, - fieldIndexList = FieldIndexList[indexedParticles[[p]]]; + For[p = 1, p <= Length[indexedFields], p++, + fieldIndexList = Vertices`FieldIndexList[indexedFields[[p]]]; decl = decl <> StringJoin[DeclareIndex[#, total++, arrayName]& /@ fieldIndexList]; ]; - Assert[total == Total[Length[FieldIndexList[#]]& /@ indexedParticles]]; + Assert[total == Total[Length[Vertices`FieldIndexList[#]]& /@ indexedFields]]; decl ]; @@ -454,20 +377,25 @@ If you add new kinds of vertices (e.g for new diagram types): Getters are available! Given below ParseVertex[] *) -(* The heart of the algorithm! From the particle content, determine all +(* The heart of the algorithm! From the field content, determine all necessary information. *) -ParseVertex[indexedParticles_List, vertexRules_List] := - Module[{particles, numberOfIndices, declareIndices, +ParseVertex[fields_List, vertexRules_List] := + Module[{indexedFields, numberOfIndices, declareIndices, parsedVertex, vertexClassName, vertexFunctionBody, - sarahParticles, particleInfo, indexBounds, expr, exprL, exprR}, - numberOfIndices = ((Length @ FieldIndexList[#] &) /@ indexedParticles); - particles = Vertices`StripFieldIndices /@ indexedParticles; - declareIndices = DeclareIndices[indexedParticles, "indices"]; - - vertexClassName = SymbolName[VertexTypeForParticles[particles]]; + sarahFields, fieldInfo, trIndexBounds, indexBounds, + expr, exprL, exprR}, + indexedFields = MapIndexed[(Module[{field = #1, + index = #2[[1]]}, + SARAH`getFull[#1] /.subGC[index] /. subIndFinal[index,index] + ] &), fields]; + + numberOfIndices = ((Length @ Vertices`FieldIndexList[#] &) /@ indexedFields); + declareIndices = DeclareIndices[indexedFields, "indices"]; + + vertexClassName = SymbolName[VertexTypeForFields[fields]]; vertexFunctionBody = Switch[vertexClassName, "SingleComponentedVertex", - expr = (SARAH`Cp @@ indexedParticles) /. vertexRules; + expr = (SARAH`Cp @@ fields) /. vertexRules; expr = TreeMasses`ReplaceDependenciesReverse[expr]; "std::complex result;\n\n" <> declareIndices <> @@ -476,8 +404,8 @@ If you add new kinds of vertices (e.g for new diagram types): "return vertex_type(result);", "LeftAndRightComponentedVertex", - exprL = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PL] /. vertexRules; - exprR = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PR] /. vertexRules; + exprL = SARAH`Cp[Sequence @@ fields][SARAH`PL] /. vertexRules; + exprR = SARAH`Cp[Sequence @@ fields][SARAH`PR] /. vertexRules; exprL = TreeMasses`ReplaceDependenciesReverse[exprL]; exprR = TreeMasses`ReplaceDependenciesReverse[exprR]; "std::complex left, right;\n\n" <> @@ -487,25 +415,22 @@ If you add new kinds of vertices (e.g for new diagram types): TreeMasses`ExpressionToString[exprR, "right"] <> "\n" <> "return vertex_type(left, right);"]; - sarahParticles = SARAH`getParticleName /@ particles; - particleInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ - sarahParticles, 1]; - - (* INFO: I do not think this ever occurs... *) - particleInfo = DeleteCases[particleInfo, {SARAH`generation, 1}, {3}]; - particleInfo = DeleteCases[particleInfo, {SARAH`lorentz, _}, {3}]; - - indexBounds = (With[{particleIndex = #}, - (If[#[[1]] === SARAH`generation, - {particleInfo[[particleIndex, 2]]-1, particleInfo[[particleIndex, 3]]}, - {1, #[[2]]}] - &) /@ particleInfo[[particleIndex, 5]]] - &) /@ Table[i, {i, Length[particles]}]; - indexBounds = Cases[Flatten[indexBounds, 1], Except[{}]]; - - If[indexBounds === {}, + sarahFields = SARAH`getParticleName /@ fields; + fieldInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ + sarahFields, 1]; + + trIndexBounds = Cases[Flatten[(With[{fieldIndex = #}, + (If[#[[1]] === SARAH`generation, + {fieldInfo[[fieldIndex, 2]]-1, fieldInfo[[fieldIndex, 3]]}, + {1, #[[2]]}] + &) /@ fieldInfo[[fieldIndex, 5]]] + &) /@ Table[i, {i, Length[fields]}], + 1], + Except[{}]]; + + If[trIndexBounds === {}, indexBounds = {{},{}}, - indexBounds = Transpose @ indexBounds]; + indexBounds = Transpose @ trIndexBounds]; parsedVertex = ParsedVertex[numberOfIndices, indexBounds, @@ -516,7 +441,7 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (** Getters to the ParsedVertex structure **) -NumberOfIndices[parsedVertex_ParsedVertex] := Total[parsedVertex[[1]]]; +NumberOfIndices[parsedVertex_ParsedVertex] := Total @ parsedVertex[[1]]; NumberOfIndices[parsedVertex_ParsedVertex, pIndex_Integer] := parsedVertex[[1, pIndex]]; IndexBounds[parsedVertex_ParsedVertex] := parsedVertex[[2]]; @@ -531,26 +456,26 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{diagrams}, If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; - cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#] &) - /@ contributingDiagramTypes - , 1]; + diagrams = Flatten[(ContributingDiagramsOfType[#] &) + /@ diagramTypes + , 1]; cachedContributingDiagrams = ({#, Union @ - (Sequence @@ Cases[cachedContributingDiagrams, - {#, diagrams_List} -> diagrams])} &) /@ edmParticles; - + (Sequence @@ Cases[diagrams, + {#, diags_List} -> diags])} &) /@ edmFields; + Return[cachedContributingDiagrams]; ]; (* Returns a list of all concrete diagram evaluators - format: {{edmParticle1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, - {edmParticle2, {"...", ... }}, + format: {{edmField1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, + {edmField2, {"...", ... }}, ...} that need to be invoked in our calculation *) ConcreteDiagramEvaluators[] := ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> ToString @ #[[1,1]] <> ">, " <> - StringJoin @ (Riffle[ParticleToCXXName /@ List @@ #[[2;;]], ", "]) <> + StringJoin @ (Riffle[CXXNameOfField /@ List @@ #[[2;;]], ", "]) <> ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 3e4d565d4..cdb33b0de 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1451,6 +1451,7 @@ corresponding tadpole is real or imaginary (only in models with CP SetEDMParticles[edmParticles]; +<<<<<<< f022a76758c5793154e4da8f864942d0900151ac Print[EDM`CreateVertices[vertexRules]]; (* particles = EDM`CreateParticles[]; @@ -1470,6 +1471,25 @@ corresponding tadpole is real or imaginary (only in models with CP "@EDM_Calculation@" -> IndentText[calculationCode], Sequence @@ GeneralReplacementRules[] } ];*) +======= + particles = EDM`CreateParticles[]; + chargeGetters = EDM`CreateChargeGetters[]; + diagrams = EDM`CreateDiagrams[]; + + vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; + definitions = EDM`CreateDefinitions[vertexRules]; + calculationCode = EDM`CreateCalculation[]; + + (*WriteOut`ReplaceInFiles[files, + { "@EDM_Particles@" -> particles, + "@EDM_ChargeGetters@" -> chargeGetters, + "@EDM_Diagrams@" -> diagrams, + "@EDM_VertexFunctionData@" -> vertexFunctionData, + "@EDM_Definitions@" -> definitions, + "@EDM_Calculation@" -> IndentText[calculationCode], + Sequence @@ GeneralReplacementRules[] + } ];*) +>>>>>>> Too much to describe... ]; EnableForBVPSolver[solver_, statements_String] := @@ -2734,17 +2754,10 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; -<<<<<<< 2f6a3062c3ce3b875f83065972915e93fa9ee0fd Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; -======= - Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], - vertexRuleFileName], - vertexRules = Get[vertexRuleFileName]; ->>>>>>> First steps towards integrating the EDM module. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; From 6362173c1d78f664cd266c9c2d3d990d0f5f17ab Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:01:32 +0100 Subject: [PATCH 022/158] Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. --- meta/EDM.m | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 176671bbd..7c8c6f727 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -221,6 +221,9 @@ If you add new kinds of vertices (e.g for new diagram types): {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}], subtypedDiagrams, uniqueDiagrams}, + If[TreeMasses`IsFermion[edmField] =!= True, + Return[{edmField,{}}]]; + subtypedDiagrams = (Module[{photonEmitter = #[[2,1]], exchangeField = #[[2,2]], subType}, @@ -466,11 +469,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[cachedContributingDiagrams]; ]; -(* Returns a list of all concrete diagram evaluators - format: {{edmField1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, - {edmField2, {"...", ... }}, - ...} - that need to be invoked in our calculation *) ConcreteDiagramEvaluators[] := ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> From 7a2ba4dac8cb0bb864b691a2c9d143479f7c02bc Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:02:58 +0100 Subject: [PATCH 023/158] Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. --- meta/FlexibleSUSY.m | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index cdb33b0de..6964a2231 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -5,7 +5,7 @@ "Phases`", "LoopMasses`", "WriteOut`", "Constraint`", "ThresholdCorrections`", "ConvergenceTester`", "Utils`", "ThreeLoopSM`", "ThreeLoopMSSM`", "Observables`", - "GMuonMinus2`", "EffectiveCouplings`", + "GMuonMinus2`", "EDM`", "EffectiveCouplings`", "FlexibleEFTHiggsMatching`", "FSMathLink`", "FlexibleTower`"}]; @@ -1480,7 +1480,7 @@ corresponding tadpole is real or imaginary (only in models with CP definitions = EDM`CreateDefinitions[vertexRules]; calculationCode = EDM`CreateCalculation[]; - (*WriteOut`ReplaceInFiles[files, + WriteOut`ReplaceInFiles[files, { "@EDM_Particles@" -> particles, "@EDM_ChargeGetters@" -> chargeGetters, "@EDM_Diagrams@" -> diagrams, @@ -1488,8 +1488,12 @@ corresponding tadpole is real or imaginary (only in models with CP "@EDM_Definitions@" -> definitions, "@EDM_Calculation@" -> IndentText[calculationCode], Sequence @@ GeneralReplacementRules[] +<<<<<<< 39b7519c812c04e0347cb5e65bcfdcc4fc687214 } ];*) >>>>>>> Too much to describe... +======= + } ]; +>>>>>>> Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. ]; EnableForBVPSolver[solver_, statements_String] := @@ -2961,8 +2965,11 @@ corresponding tadpole is real or imaginary (only in models with CP FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; Print["Creating class EDM"]; - WriteGMuonMinus2Class[vertexRules, - {}]; + WriteEDMClass[vertexRules, + {{FileNameJoin[{$flexiblesusyTemplateDir, "edm.hpp.in"}], + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.hpp"}]}, + {FileNameJoin[{$flexiblesusyTemplateDir, "edm.cpp.in"}], + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.cpp"}]}}]; PrintHeadline["Creating Mathematica interface"]; Print["Creating LibraryLink ", FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> ".mx"}], " ..."]; From 9d4066e3b28e9ba70d2706f776a092464c3c1f85 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:58:04 +0100 Subject: [PATCH 024/158] Preparing for first run. --- meta/EDM.m | 12 +- meta/FlexibleSUSY.m | 38 +--- templates/edm.cpp.in | 511 +++++++++++++++++++++++++++++++++++++++++++ templates/edm.hpp.in | 43 ++++ 4 files changed, 571 insertions(+), 33 deletions(-) create mode 100644 templates/edm.cpp.in create mode 100644 templates/edm.hpp.in diff --git a/meta/EDM.m b/meta/EDM.m index 7c8c6f727..7316f4fb5 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -343,7 +343,7 @@ If you add new kinds of vertices (e.g for new diagram types): "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" );]; - definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> + definition = ("template<> " <> functionClassName <> "::vertex_type\n" <> functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> "{\n" <> IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> @@ -458,6 +458,7 @@ If you add new kinds of vertices (e.g for new diagram types): ContributingDiagrams[] := Module[{diagrams}, If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; + LoadVerticesIfNecessary[]; diagrams = Flatten[(ContributingDiagramsOfType[#] &) /@ diagramTypes @@ -469,6 +470,15 @@ If you add new kinds of vertices (e.g for new diagram types): Return[cachedContributingDiagrams]; ]; +LoadVerticesIfNecessary[] := + Module[{}, + If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, + SARAH`InitVertexCalculation[FSEigenstates`FSEigenstates, False]; + SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; + SARAH`MakeCouplingLists; + ]; + ]; + ConcreteDiagramEvaluators[] := ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 6964a2231..8d10c6cbe 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1445,34 +1445,13 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the EDM c++ files *) WriteEDMClass[vertexRules_List, files_List] := -Module[{edmParticles, particles, chargeGetters, diagrams, vertexFunctionData, +Module[{fields, edmFields, chargeGetters, diagrams, vertexFunctionData, definitions, calculationCode}, - edmParticles = {SARAH`Electron}; + edmFields = {SARAH`Electron}; + EDM`SetEDMFields[edmParticles]; - SetEDMParticles[edmParticles]; + fields = EDM`CreateFields[]; -<<<<<<< f022a76758c5793154e4da8f864942d0900151ac - Print[EDM`CreateVertices[vertexRules]]; - (* - particles = EDM`CreateParticles[]; - chargeGetters = EDM`CreateChargeGetters[]; - diagrams = EDM`CreateDiagrams[]; - - vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; - definitions = EDM`CreateDefinitions[vertexRules]; - calculationCode = EDM`CreateCalculation[]; - - WriteOut`ReplaceInFiles[files, - { "@EDM_Particles@" -> particles, - "@EDM_ChargeGetters@" -> chargeGetters, - "@EDM_Diagrams@" -> diagrams, - "@EDM_VertexFunctionData@" -> vertexFunctionData, - "@EDM_Definitions@" -> definitions, - "@EDM_Calculation@" -> IndentText[calculationCode], - Sequence @@ GeneralReplacementRules[] - } ];*) -======= - particles = EDM`CreateParticles[]; chargeGetters = EDM`CreateChargeGetters[]; diagrams = EDM`CreateDiagrams[]; @@ -1481,19 +1460,14 @@ corresponding tadpole is real or imaginary (only in models with CP calculationCode = EDM`CreateCalculation[]; WriteOut`ReplaceInFiles[files, - { "@EDM_Particles@" -> particles, + { "@EDM_Fields@" -> fields, "@EDM_ChargeGetters@" -> chargeGetters, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, "@EDM_Calculation@" -> IndentText[calculationCode], Sequence @@ GeneralReplacementRules[] -<<<<<<< 39b7519c812c04e0347cb5e65bcfdcc4fc687214 - } ];*) ->>>>>>> Too much to describe... -======= } ]; ->>>>>>> Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. ]; EnableForBVPSolver[solver_, statements_String] := @@ -2051,7 +2025,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := EDM`NPointFunctions[]; +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in new file mode 100644 index 000000000..e10a9b3cd --- /dev/null +++ b/templates/edm.cpp.in @@ -0,0 +1,511 @@ +// ==================================================================== +// This file is part of FlexibleSUSY. +// +// FlexibleSUSY is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// FlexibleSUSY is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with FlexibleSUSY. If not, see +// . +// ==================================================================== + +// File generated at @DateAndTime@ + +/** + * @file @ModelName@_edm.cpp + * + * This file was generated at @DateAndTime@ with FlexibleSUSY + * @FlexibleSUSYVersion@ and SARAH @SARAHVersion@ . + */ + +#include "@ModelName@_edm.hpp" +#include "@ModelName@_mass_eigenstates.hpp" + +#include "numerics2.hpp" +#include "wrappers.hpp" + +#include +#include +#include +#include + +#define INPUTPARAMETER(p) context.model.get_input().p +#define MODELPARAMETER(p) context.model.get_##p() +#define DERIVEDPARAMETER(p) context.model.p() + +using namespace flexiblesusy; + +namespace { +/** + * @class IndexBounds + * @brief A class representing multiple (N) index ranges. + * + * N is a non-negative integer. + * The ranges are specified the c++ way; The range begins are inclusive + * and the range ends are exclusive. Misspecified ranges result in + * undefined behaviour! + * The intended use is to iterate over an IndexBounds using the normal + * begin()/end() syntax, which will iterate over every possible combination + * of the indices within their respective ranges. + * The ranges are const! Once they are initialized they cannot be changed. + * Initialization is done like = {{ beg1, beg2, ... }, { end1, end2, ... }} + */ +template struct IndexBounds; + +/** + * @class IndexIterator + * @brief The iterator class used by IndexBounds. + * + * It only fulfils the input iterator requirements! + * The value_type is a const std::array + * containing the current indices. + * Incrementing the iterator results in a new index combination. + */ +template struct IndexIterator +: public std::iterator< +std::input_iterator_tag, +const std::array> +{ + friend class IndexBounds; +private: + const IndexBounds *bounds; + std::array indices; + + IndexIterator(const IndexBounds &b, const unsigned *i) + : bounds(&b) + { + std::memcpy(indices.data(), i, N * sizeof(unsigned)); + } +public: + const std::array &operator*() const { + return indices; + } + + const std::array *operator->() const { + return &indices; + } + + IndexIterator &operator++() { + for (unsigned i = 0; i != N; i++) { + indices[i]++; + if (indices[i] == bounds->indexEnd[i]) { + indices[i] = bounds->indexBegin[i]; + continue; + } + + return *this; + } + + std::memcpy(indices.data(), bounds->indexEnd, N * sizeof(unsigned)); + return *this; + } + + IndexIterator operator++(int) { + IndexIterator it(*this); + this->operator++(); + return it; + } + + template + friend bool operator==(const IndexIterator &it1, const IndexIterator &it2); +}; + +template +bool operator==(const IndexIterator &it1, const IndexIterator &it2) +{ + return it1.indices == it2.indices; +} + +template +bool operator!=(const IndexIterator &it1, const IndexIterator &it2) +{ + return !(it1 == it2); +} + +template struct IndexBounds { + typedef const std::array indices_type; + + unsigned indexBegin[N]; + unsigned indexEnd[N]; + + typedef IndexIterator const_iterator; + + const_iterator begin() const { + return const_iterator(*this, indexBegin); + } + + const_iterator end() const { + return const_iterator(*this, indexEnd); + } +}; + +template<> struct IndexBounds<0> { + typedef const std::array indices_type; + typedef indices_type * const_iterator; + + static const indices_type dummyIndex; + + const_iterator begin() const + { return &dummyIndex; } + const_iterator end() const + { return (begin()+1); } +}; +IndexBounds<0>::indices_type IndexBounds<0>::dummyIndex{}; + +@EDM_Fields@ + +template struct remove_anti { typedef P type; }; +template struct remove_anti> { typedef P type; }; + +/** + * @class EvaluationContext + * @brief Represents an evaluation context. + * + * Actually it simply contains a reference to a model object. + * All computational functions are forwarded to that object, + * e.g. mass calculation functions. + */ +struct EvaluationContext { + @ModelName@_mass_eigenstates& model; ///< The model object. + + /** + * @fn mass

+ * @brief Returns the mass of a particle. + */ + template double mass() const { + return mass::type>(); + } + + template double mass(unsigned index) const { + return mass::type>(index); + } +}; + +/** + * @class DiagramEvaluator + * @brief A template that can calculate disagrams. + * + * This template is completely general. The intended use is + * to have specialisations of the kind: + * DiagramEvaluator + * along with a static member function: + * static double value( EvaluationContext &context ); + * that calculates the contribution to the edm + * for a specific diagram class with specified particles. + */ +template struct DiagramEvaluator; + +double OneLoopFunctionF1C(double); +double OneLoopFunctionF2C(double); +double OneLoopFunctionF1N(double); +double OneLoopFunctionF2N(double); + +@EDM_MuonFunctionPrototypes@ + +@EDM_Diagrams@ + +/** + * @class SingleComponentedVertex + * @brief A vertex whose value can be represented by a single complex number + */ +class SingleComponentedVertex { +private: + std::complex val; ///< The value +public: + SingleComponentedVertex(std::complex v) + : val(v) {} + + /** + * @fn value + * @brief Returns the value of the vertex. + */ + std::complex value() const { + return val; + } + + /** + * @fn isZero + * @brief Tests whether the value is numerically significant + */ + bool isZero() const { + return (is_zero(val.real()) && is_zero(val.imag())); + } +}; + +/** + * @class LeftAndRightComponentedVertex + * @brief A vertex whose value can be represented by two complex numbers + */ +class LeftAndRightComponentedVertex { +private: + std::pair, std::complex> value; ///< The values +public: + LeftAndRightComponentedVertex(const std::complex &left, + const std::complex &right) + : value(left, right) {} + + /** + * @fn left + * @brief Returns the left component of the vertex. + */ + std::complex left() const { + return value.first; + } + + /** + * @fn right + * @brief Returns the left component of the vertex. + */ + std::complex right() const { + return value.second; + } + + /** + * @fn isZero + * @brief Tests whether the values are numerically significant + */ + bool isZero() const { + return (is_zero(value.first.real()) && is_zero(value.first.imag()) && + is_zero(value.second.real()) && is_zero(value.second.imag())); + } +}; + +/** + * @class VertexFunctionData + * @brief Vertex data for a vertex with the particles specified by P... + * + * All elements in P... have to be publicly derived from Particle. + * The data includes the type of the vertex, whether P... is in + * canonical order or permuted as well as index bounds referring to + * the specific particles (generation and colour indices, etc). + * The intention is to have a program generate VertexFunctionData<> + * specialisations that are then used by the VertexFunction<> template. + */ +template struct VertexFunctionData; + +/** + * @class VertexFunction + * @brief A template that represents a vertex with open particle indices. + * + * All elements in P... have to be publicly derived from Particle. + * To obtain a conrete value, use the static member function vertex() + * along with the desired particle indices. + */ +template class VertexFunction { +{ +private: +typedef VertexFunctionData Base; +typedef typename Base::particleIndexStart particleIndexStart; +using Base::indexB; +public: +typedef typename Base::index_bounds index_bounds; +typedef typename index_bounds::indices_type indices_type; +typedef typename Base::vertex_type vertex_type; +public: + + + + + using Data = VertexFunctionData; +public: + using index_bounds = Data::index_bounds index_bounds; + using indices_type = index_bounds::indices_type; + using vertex_type = Data::vertex_type; + + /** + * @fn indexBounds + * @brief Returns the IndexBounds<> object of the VertexFunction. + */ + static const index_bounds &indexBounds() { + return indexB; + } + + /** + * @fn particleIndices + * @brief Returns the subset of indices belonging to + * a particle at a given index. + * @param indices The complete set of indices for all particles + * + * The particle indexing is in the same order as the template arguments + * and starts at 0. + */ + template + static std::vector particleIndices(const indices_type &indices) + { + auto begin = indices.begin() + boost::mpl::at_c::type::value; + auto end = indices.begin() + boost::mpl::at_c::type::value; + return std::vector(begin, end); + } + + /** + * @fn vertex + * @brief Calculates the vertex for a given set of particle indices. + * @param indices The particle indices + * @param context The evaluation context + */ + static vertex_type vertex(const indices_type &indices, EvaluationContext &context); +}; + +@EDM_VertexFunctionData@ +} + +@EDM_Calculation@ + +double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstates& model_) +{ + // make copy since model is modified via call to calculate_MFe_pole() + @ModelName@_mass_eigenstates model(model_); + + return edm(); +} + +namespace { +/** +* @defgroup LoopFunctions +* @brief The loop functions necessary for \f$a_\mu\f$ one-loop calculations. +* +* These are OneLoopFunctionF1C(), OneLoopFunctionF2C(), +* OneLoopFunctionF1N() and OneLoopFunctionF2N() +* as specified in arXiv:1311.1775 +*/ + +double OneLoopFunctionF1C(double x) +{ + if (is_zero(x)) + return 4.0; + + // error around x=1 is <= 10^-12 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.21) { + return (1.0000000000000000000 - + 0.60000000000000000000 * y + + 0.40000000000000000000 * y * y - + 0.28571428571428571429 * y * y * y + + 0.21428571428571428571 * y * y * y * y - + 0.16666666666666666667 * y * y * y * y * y + + 0.13333333333333333333 * y * y * y * y * y * y - + 0.10909090909090909091 * y * y * y * y * y * y * y + + 0.090909090909090909091 * y * y * y * y * y * y * y * y - + 0.076923076923076923077 * y * y * y * y * y * y * y * y * y + + 0.065934065934065934066 * y * y * y * y * y * y * y * y * y * y - + 0.057142857142857142857 * y * y * y * y * y * y * y * y * y * y * y + + 0.050000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.044117647058823529412 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.039215686274509803922 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.035087719298245614035 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + } + + return 2.0 / (y * y * y * y) * (2.0 + 3.0 * x - 6.0 * x * x + x * x * x + 6.0 * x * std::log(x)); +} + +double OneLoopFunctionF2C(double x) +{ + // error around x=1 is <= 10^-13 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.155) + return (1.0 - 0.75 * y + 0.6 * y * y - + 0.50000000000000000000 * y * y * y + + 0.4285714285714285714 * y * y * y * y - + 0.37500000000000000000 * y * y * y * y * y + + 0.33333333333333333333 * y * y * y * y * y * y - + 0.3000000000000000000 * y * y * y * y * y * y * y + + 0.2727272727272727273 * y * y * y * y * y * y * y * y - + 0.2500000000000000000 * y * y * y * y * y * y * y * y * y + + 0.23076923076923076923 * y * y * y * y * y * y * y * y * y * y - + 0.21428571428571428571 * y * y * y * y * y * y * y * y * y * y * y + + 0.2000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.1875000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.1764705882352941176 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.16666666666666666667 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + + return -3.0 / (2.0 * y * y * y) * (-3.0 + 4.0 * x - x * x - 2.0 * std::log(x)); +} + +double OneLoopFunctionF1N(double x) +{ + if (is_zero(x)) + return 2.0; + + // error around x=1 is <= 10^-12 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.23) + return (1.0000000000000000000 - + 0.4000000000000000000 * y + + 0.2000000000000000000 * y * y - + 0.11428571428571428571 * y * y * y + + 0.07142857142857142857 * y * y * y * y - + 0.04761904761904761905 * y * y * y * y * y + + 0.03333333333333333333 * y * y * y * y * y * y - + 0.02424242424242424242 * y * y * y * y * y * y * y + + 0.0181818181818181818 * y * y * y * y * y * y * y * y - + 0.01398601398601398601 * y * y * y * y * y * y * y * y * y + + 0.01098901098901098901 * y * y * y * y * y * y * y * y * y * y - + 0.0087912087912087912 * y * y * y * y * y * y * y * y * y * y * y + + 0.00714285714285714286 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.0058823529411764706 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.0049019607843137255 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.0041279669762641899 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + + return 2.0 / (y * y * y * y) * (1.0 - 6.0 * x + 3.0 * x * x + 2.0 * x * x * x - 6.0 * x * x * std::log(x)); +} + +double OneLoopFunctionF2N(double x) +{ + if (is_zero(x)) + return 3.0; + + // error around x=1 is <= 10^-13 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.185) + return (1.0000000000000000000 - + 0.50000000000000000000 * y + + 0.30000000000000000000 * y * y - + 0.2000000000000000000 * y * y * y + + 0.14285714285714285714 * y * y * y * y - + 0.10714285714285714286 * y * y * y * y * y + + 0.08333333333333333333 * y * y * y * y * y * y - + 0.06666666666666666667 * y * y * y * y * y * y * y + + 0.05454545454545454545 * y * y * y * y * y * y * y * y - + 0.0454545454545454545 * y * y * y * y * y * y * y * y * y + + 0.0384615384615384615 * y * y * y * y * y * y * y * y * y * y - + 0.03296703296703296703 * y * y * y * y * y * y * y * y * y * y * y + + 0.0285714285714285714 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.02500000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.0220588235294117647 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.0196078431372549020 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + + return -3.0 / (y * y * y) * (1.0 - x * x + 2.0 * x * std::log(x)); +} + +@EDM_Definitions@ + +template +double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +{ + double res = 0.0; + + + return res; +} + +template +double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +{ + double res = 0.0; + + + + return res; +} +} diff --git a/templates/edm.hpp.in b/templates/edm.hpp.in new file mode 100644 index 000000000..880373086 --- /dev/null +++ b/templates/edm.hpp.in @@ -0,0 +1,43 @@ +// ==================================================================== +// This file is part of FlexibleSUSY. +// +// FlexibleSUSY is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// FlexibleSUSY is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with FlexibleSUSY. If not, see +// . +// ==================================================================== + +// File generated at @DateAndTime@ + +/** + * @file @ModelName@_edm.hpp + * + * This file was generated at @DateAndTime@ with FlexibleSUSY + * @FlexibleSUSYVersion@ and SARAH @SARAHVersion@ . + */ + +#ifndef @ModelName@_EDM_H +#define @ModelName@_EDM_H + +namespace flexiblesusy { +class @ModelName@_mass_eigenstates; + +namespace @ModelName@_edm { +/** +* @fn calculate_edm_electron +* @brief Calculates the electromagnetic dipole moment of the electron. +*/ +double calculate_edm_electron(const @ModelName@_mass_eigenstates& model); +} // namespace @ModelName@_edm +} // namespace flexiblesusy + +#endif From 6c5230305d9c0121c1258b7ff81a70bcd02191d9 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:02:39 +0100 Subject: [PATCH 025/158] Fixed Typo --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 7316f4fb5..9f43fdc5e 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -473,7 +473,7 @@ If you add new kinds of vertices (e.g for new diagram types): LoadVerticesIfNecessary[] := Module[{}, If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, - SARAH`InitVertexCalculation[FSEigenstates`FSEigenstates, False]; + SARAH`InitVertexCalculation[FlexibleSUSY`FSEigenstates, False]; SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; SARAH`MakeCouplingLists; ]; From 4399c34e193bbb2e17d6aa3c5d756fb880ea973d Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:43:59 +0100 Subject: [PATCH 026/158] Added edm as build template. Lots of small codegen fixes. --- meta/EDM.m | 5 ++- meta/FlexibleSUSY.m | 4 +- templates/edm.cpp.in | 99 ++++++++++++++++++++---------------------- templates/module.mk | 2 + templates/module.mk.in | 3 ++ 5 files changed, 56 insertions(+), 57 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 9f43fdc5e..a451b5443 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -43,6 +43,7 @@ If you add new kinds of vertices (e.g for new diagram types): "};\n" &) /@ fields, "\n"] <> "\n\n" <> "// Special field families\n" <> "using Photon = " <> CXXNameOfField @ SARAH`Photon <> ";\n" <> + "using Electron = " <> CXXNameOfField @ SARAH`Electron <> ";\n\n" <> "// Anti fields\n" <> "template struct anti : public Field\n" <> @@ -121,11 +122,11 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{code, evaluators}, evaluators = ConcreteDiagramEvaluators[]; - code = "template double edm( void );\n\n"; + code = "template double edm( CMSSM_mass_eigenstates& model );\n\n"; code = (code <> StringJoin @ Riffle[Module[{field = #[[1]], fieldEvaluators = #[[2]]}, - "template<> double edm<" <> CXXNameOfField[field] <> ">( void )\n" <> + "template<> double edm<" <> CXXNameOfField[field] <> ">( CMSSM_mass_eigenstates& model )\n" <> "{\n" <> IndentText["EvaluationContext context{ model };\n" <> "double val = 0.0;\n\n" <> diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 8d10c6cbe..d5340d16d 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1465,7 +1465,7 @@ corresponding tadpole is real or imaginary (only in models with CP "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, - "@EDM_Calculation@" -> IndentText[calculationCode], + "@EDM_Calculation@" -> calculationCode, Sequence @@ GeneralReplacementRules[] } ]; ]; @@ -2025,7 +2025,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index e10a9b3cd..e2ff9de09 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -161,8 +161,8 @@ IndexBounds<0>::indices_type IndexBounds<0>::dummyIndex{}; @EDM_Fields@ -template struct remove_anti { typedef P type; }; -template struct remove_anti> { typedef P type; }; +template struct remove_anti { typedef F type; }; +template struct remove_anti> { typedef F type; }; /** * @class EvaluationContext @@ -176,15 +176,15 @@ struct EvaluationContext { @ModelName@_mass_eigenstates& model; ///< The model object. /** - * @fn mass

- * @brief Returns the mass of a particle. + * @fn mass + * @brief Returns the mass of a field. */ - template double mass() const { - return mass::type>(); + template double mass() const { + return mass::type>(); } - template double mass(unsigned index) const { - return mass::type>(index); + template double mass(unsigned index) const { + return mass::type>(index); } }; @@ -194,11 +194,11 @@ struct EvaluationContext { * * This template is completely general. The intended use is * to have specialisations of the kind: - * DiagramEvaluator + * DiagramEvaluator * along with a static member function: * static double value( EvaluationContext &context ); * that calculates the contribution to the edm - * for a specific diagram class with specified particles. + * for a specific diagram class with specified fields. */ template struct DiagramEvaluator; @@ -207,7 +207,7 @@ double OneLoopFunctionF2C(double); double OneLoopFunctionF1N(double); double OneLoopFunctionF2N(double); -@EDM_MuonFunctionPrototypes@ +@EDM_ChargeGetters@ @EDM_Diagrams@ @@ -278,46 +278,35 @@ public: }; /** - * @class VertexFunctionData - * @brief Vertex data for a vertex with the particles specified by P... + * @class VertexFunctionData + * @brief Vertex data for a vertex with the fields specified by F... * - * All elements in P... have to be publicly derived from Particle. - * The data includes the type of the vertex, whether P... is in + * All elements in F... have to be publicly derived from Field. + * The data includes the type of the vertex, whether F... is in * canonical order or permuted as well as index bounds referring to - * the specific particles (generation and colour indices, etc). + * the specific fields (generation and colour indices, etc). * The intention is to have a program generate VertexFunctionData<> * specialisations that are then used by the VertexFunction<> template. */ -template struct VertexFunctionData; +template struct VertexFunctionData; /** - * @class VertexFunction - * @brief A template that represents a vertex with open particle indices. + * @class VertexFunction + * @brief A template that represents a vertex with open field indices. * - * All elements in P... have to be publicly derived from Particle. + * All elements in F... have to be publicly derived from Field. * To obtain a conrete value, use the static member function vertex() - * along with the desired particle indices. + * along with the desired field indices. */ -template class VertexFunction { +template class VertexFunction { { -private: -typedef VertexFunctionData Base; -typedef typename Base::particleIndexStart particleIndexStart; -using Base::indexB; -public: -typedef typename Base::index_bounds index_bounds; -typedef typename index_bounds::indices_type indices_type; -typedef typename Base::vertex_type vertex_type; + using Data = VertexFunctionData; public: + using index_bounds = typename Data::index_bounds index_bounds; + using indices_type = typename index_bounds::indices_type; + using vertex_type = typename Data::vertex_type; - - - - using Data = VertexFunctionData; -public: - using index_bounds = Data::index_bounds index_bounds; - using indices_type = index_bounds::indices_type; - using vertex_type = Data::vertex_type; + using fieldIndexStart = typename Data::fieldIndexStart; /** * @fn indexBounds @@ -328,26 +317,26 @@ public: } /** - * @fn particleIndices + * @fn fieldIndices * @brief Returns the subset of indices belonging to - * a particle at a given index. - * @param indices The complete set of indices for all particles + * a field at a given index. + * @param indices The complete set of indices for all fields * - * The particle indexing is in the same order as the template arguments + * The field indexing is in the same order as the template arguments * and starts at 0. */ - template - static std::vector particleIndices(const indices_type &indices) + template + static std::vector fieldIndices(const indices_type &indices) { - auto begin = indices.begin() + boost::mpl::at_c::type::value; - auto end = indices.begin() + boost::mpl::at_c::type::value; + auto begin = indices.begin() + boost::mpl::at_c::type::value; + auto end = indices.begin() + boost::mpl::at_c::type::value; return std::vector(begin, end); } /** * @fn vertex - * @brief Calculates the vertex for a given set of particle indices. - * @param indices The particle indices + * @brief Calculates the vertex for a given set of field indices. + * @param indices The field indices * @param context The evaluation context */ static vertex_type vertex(const indices_type &indices, EvaluationContext &context); @@ -363,7 +352,7 @@ double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstate // make copy since model is modified via call to calculate_MFe_pole() @ModelName@_mass_eigenstates model(model_); - return edm(); + return edm( model ); } namespace { @@ -490,8 +479,10 @@ double OneLoopFunctionF2N(double x) @EDM_Definitions@ -template -double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +template +double DiagramEvaluator, + EDMField, PhotonEmitter, ExchangeField +>::value(EvaluationContext &context) { double res = 0.0; @@ -499,8 +490,10 @@ double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::val return res; } -template -double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +template +double DiagramEvaluator, + EDMField, PhotonEmitter, ExchangeField +>::value(EvaluationContext &context) { double res = 0.0; diff --git a/templates/module.mk b/templates/module.mk index c28d91ddc..f5c55b3ad 100644 --- a/templates/module.mk +++ b/templates/module.mk @@ -4,6 +4,8 @@ MODNAME := templates BASE_TEMPLATES := \ $(DIR)/a_muon.hpp.in \ $(DIR)/a_muon.cpp.in \ + $(DIR)/edm.hpp.in \ + $(DIR)/edm.cpp.in \ $(DIR)/convergence_tester.hpp.in \ $(DIR)/effective_couplings.hpp.in \ $(DIR)/effective_couplings.cpp.in \ diff --git a/templates/module.mk.in b/templates/module.mk.in index b7a42ce9b..f35ada05a 100644 --- a/templates/module.mk.in +++ b/templates/module.mk.in @@ -31,6 +31,7 @@ WITH_$(MODNAME) := yes LIB@CLASSNAME@_SRC := \ $(DIR)/@CLASSNAME@_a_muon.cpp \ + $(DIR)/@CLASSNAME@_edm.cpp \ $(DIR)/@CLASSNAME@_effective_couplings.cpp \ $(DIR)/@CLASSNAME@_info.cpp \ $(DIR)/@CLASSNAME@_input_parameters.cpp \ @@ -58,6 +59,8 @@ LL@CLASSNAME@_MMA := \ LIB@CLASSNAME@_HDR := \ $(DIR)/@CLASSNAME@_a_muon.hpp \ + $(DIR)/@CLASSNAME@_edm.hpp \ + $(DIR)/@CLASSNAME@_convergence_tester.hpp \ $(DIR)/@CLASSNAME@_effective_couplings.hpp \ $(DIR)/@CLASSNAME@_info.hpp \ $(DIR)/@CLASSNAME@_input_parameters.hpp \ From d698c6e5af055a4a0c216c39facad1fe6ccb9fef Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:57:55 +0100 Subject: [PATCH 027/158] Fixed a dependency on a SARAH symbol that is only available after SARAH`Start[]. --- meta/EDM.m | 5 ++++- meta/FlexibleSUSY.m | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index a451b5443..04dacc4e1 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -2,6 +2,8 @@ (* This module generates c++ code that calculates electric dipole moments of fields *) +Initialize::usage="Initialize the EDM module."; + SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; CreateFields::usage="Returns the c++ code that contains all field fields"; @@ -27,6 +29,8 @@ If you add new kinds of vertices (e.g for new diagram types): (************* Begin public interface *******************) +Initialize[] := (subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___);) + edmFields = Null; SetEDMFields[fields_List] := (edmFields = fields;) @@ -179,7 +183,6 @@ If you add new kinds of vertices (e.g for new diagram types): (**************** Other Functions ***************) -subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; AddIndexPattern[field_] := SARAH`getFull[SARAH`getBlank[field]] /. subIndexPattern; diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index d5340d16d..c04116364 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2025,7 +2025,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); +PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, From 2a7335141f3aa70a7f2f2a9041412bb36a2b17fa Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 15:34:31 +0100 Subject: [PATCH 028/158] Fixed scoping issues. --- meta/EDM.m | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 04dacc4e1..2f03f17b2 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -153,7 +153,7 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (**************** End public interface *****************) -(* TODO: privatize interface again Begin["`Private`"]; *) +Begin["`Private`"]; (* The supported vertex types. They have the same names as their c++ counterparts. *) @@ -361,7 +361,7 @@ If you add new kinds of vertices (e.g for new diagram types): from the elements of `arrayName'. *) DeclareIndices[indexedFields_List, arrayName_String] := - Module[{p, total = 0, fieldIndexList, decl = ""}, + Module[{p, total = 0, fieldIndexList, decl = "", idx}, DeclareIndex[idx_, num_Integer, an_String] := ( "const unsigned " <> CConversion`ToValidCSymbolString[idx] <> " = " <> an <> "[" <> ToString[num] <> "];\n"); @@ -393,7 +393,7 @@ If you add new kinds of vertices (e.g for new diagram types): expr, exprL, exprR}, indexedFields = MapIndexed[(Module[{field = #1, index = #2[[1]]}, - SARAH`getFull[#1] /.subGC[index] /. subIndFinal[index,index] + SARAH`getFull[#1] /. SARAH`subGC[index] /. SARAH`subIndFinal[index,index] ] &), fields]; numberOfIndices = ((Length @ Vertices`FieldIndexList[#] &) /@ indexedFields); @@ -467,6 +467,7 @@ If you add new kinds of vertices (e.g for new diagram types): diagrams = Flatten[(ContributingDiagramsOfType[#] &) /@ diagramTypes , 1]; + cachedContributingDiagrams = ({#, Union @ (Sequence @@ Cases[diagrams, {#, diags_List} -> diags])} &) /@ edmFields; @@ -477,6 +478,7 @@ If you add new kinds of vertices (e.g for new diagram types): LoadVerticesIfNecessary[] := Module[{}, If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, + SA`CurrentStates = FlexibleSUSY`FSEigenstates; SARAH`InitVertexCalculation[FlexibleSUSY`FSEigenstates, False]; SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; SARAH`MakeCouplingLists; @@ -491,6 +493,6 @@ If you add new kinds of vertices (e.g for new diagram types): ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; -(* TODO: End[]; *) +End[]; EndPackage[]; From 175e85672d792afcee29d62c73f13f4d07701935 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:43:57 +0100 Subject: [PATCH 029/158] Fixed scoping issue. --- meta/EDM.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 2f03f17b2..0e04a8637 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -407,7 +407,7 @@ If you add new kinds of vertices (e.g for new diagram types): "std::complex result;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[expr] <> "\n" <> - TreeMasses`ExpressionToString[expr, "result"] <> "\n" <> + Parameters`ExpressionToString[expr, "result"] <> "\n" <> "return vertex_type(result);", "LeftAndRightComponentedVertex", @@ -418,8 +418,8 @@ If you add new kinds of vertices (e.g for new diagram types): "std::complex left, right;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[exprL + exprR] <> "\n" <> - TreeMasses`ExpressionToString[exprL, "left"] <> "\n" <> - TreeMasses`ExpressionToString[exprR, "right"] <> "\n" <> + Parameters`ExpressionToString[exprL, "left"] <> "\n" <> + Parameters`ExpressionToString[exprR, "right"] <> "\n" <> "return vertex_type(left, right);"]; sarahFields = SARAH`getParticleName /@ fields; From fb29771131b7308d72e91688ec9ee53bea6401c7 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:44:50 +0100 Subject: [PATCH 030/158] Moved Vertex logic to a place where the vertex files definitely exist. --- meta/FlexibleSUSY.m | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index c04116364..5e7af59bf 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,9 +2024,6 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; -(* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); - PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2174,7 +2171,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, edmVertices = {}, + gmm2Vertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2221,8 +2218,6 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; - (* EDM vertices *) - edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; @@ -2733,7 +2728,7 @@ corresponding tadpole is real or imaginary (only in models with CP effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; effectiveCouplings = Get[effectiveCouplingsFileName]; @@ -2939,7 +2934,10 @@ corresponding tadpole is real or imaginary (only in models with CP FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; Print["Creating class EDM"]; - WriteEDMClass[vertexRules, + EDM`Initialize[]; + EDM`SetEDMFields[{SARAH`Electron}]; + + WriteEDMClass[Join[vertexRules, Vertices`VertexRules[EDM`NPointFunctions[], Lat$massMatrices]], {{FileNameJoin[{$flexiblesusyTemplateDir, "edm.hpp.in"}], FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.hpp"}]}, {FileNameJoin[{$flexiblesusyTemplateDir, "edm.cpp.in"}], From 2664abf73086a691fac9340e4f7bebed5b00971e Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:45:19 +0100 Subject: [PATCH 031/158] Fixed typos. --- templates/edm.cpp.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index e2ff9de09..8fdb604e7 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -299,10 +299,9 @@ template struct VertexFunctionData; * along with the desired field indices. */ template class VertexFunction { -{ using Data = VertexFunctionData; public: - using index_bounds = typename Data::index_bounds index_bounds; + using index_bounds = typename Data::index_bounds; using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; From 0b3d868e6a02e77b3da33090b55cbbdb8e603d08 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 18:44:01 +0100 Subject: [PATCH 032/158] Added explicit dependency on Parameters module. --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 0e04a8637..865308370 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -1,4 +1,4 @@ -BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "Vertices`"}]; +BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "Vertices`", "Parameters`"}]; (* This module generates c++ code that calculates electric dipole moments of fields *) From 44e463316ef0fe15a0ee4e2d0f9b71a71020ac6d Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 19:26:26 +0100 Subject: [PATCH 033/158] CreateVertexFunction[] does not use a cache anymore. --- meta/EDM.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 865308370..f633ea7fa 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -309,13 +309,10 @@ If you add new kinds of vertices (e.g for new diagram types): empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) -createdVertexFunctions = {}; CreateVertexFunction[fields_List, vertexRules_List] := Module[{prototype, definition, parsedVertex, dataClassName, functionClassName, fieldIndexStartF, fieldIndexStart, indexBounds}, - If[MemberQ[createdVertexFunctions, fields], Return[{"",""}]]; - parsedVertex = ParseVertex[fields, vertexRules]; dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[CXXNameOfField /@ fields, ", "] <> ">"; @@ -353,7 +350,6 @@ If you add new kinds of vertices (e.g for new diagram types): IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); - AppendTo[createdVertexFunctions, fields]; Return[{prototype, definition}]; ]; From 1c9cd4ec857d5bb3ea2cac058dc44a6e88ad94a7 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 19:27:01 +0100 Subject: [PATCH 034/158] Refactoring issue --- templates/edm.cpp.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 8fdb604e7..233edaea6 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -312,7 +312,7 @@ public: * @brief Returns the IndexBounds<> object of the VertexFunction. */ static const index_bounds &indexBounds() { - return indexB; + return index_bounds(); } /** From 265d93a6807da00e630dfbb37e0bdb5f10d56c78 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 22 Nov 2016 09:10:34 +0100 Subject: [PATCH 035/158] Reintroduced some cxx conversion function calls that for some weird reason got lost along the way... --- meta/EDM.m | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index f633ea7fa..3aa5ceee9 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -369,6 +369,9 @@ If you add new kinds of vertices (e.g for new diagram types): decl ]; +GetComplexScalarCType[] := + CConversion`CreateCType[CConversion`ScalarType[CConversion`complexScalarCType]]; + (* ParsedVertex structure: ParsedVertex[ {numP1Indices, numP2Indices, ...}, @@ -400,22 +403,23 @@ If you add new kinds of vertices (e.g for new diagram types): "SingleComponentedVertex", expr = (SARAH`Cp @@ fields) /. vertexRules; expr = TreeMasses`ReplaceDependenciesReverse[expr]; - "std::complex result;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[expr] <> "\n" <> - Parameters`ExpressionToString[expr, "result"] <> "\n" <> + "const " <> GetComplexScalarCType[] <> " result = " <> + Parameters`ExpressionToString[expr] <> ";\n\n" <> "return vertex_type(result);", - + "LeftAndRightComponentedVertex", exprL = SARAH`Cp[Sequence @@ fields][SARAH`PL] /. vertexRules; exprR = SARAH`Cp[Sequence @@ fields][SARAH`PR] /. vertexRules; exprL = TreeMasses`ReplaceDependenciesReverse[exprL]; exprR = TreeMasses`ReplaceDependenciesReverse[exprR]; - "std::complex left, right;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[exprL + exprR] <> "\n" <> - Parameters`ExpressionToString[exprL, "left"] <> "\n" <> - Parameters`ExpressionToString[exprR, "right"] <> "\n" <> + "const " <> GetComplexScalarCType[] <> " left = " <> + Parameters`ExpressionToString[exprL] <> ";\n\n" <> + "const " <> GetComplexScalarCType[] <> " right = " <> + Parameters`ExpressionToString[exprR] <> ";\n\n" <> "return vertex_type(left, right);"]; sarahFields = SARAH`getParticleName /@ fields; From 1af7c8423a2ef0e2fba370308a81f9586ea98403 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 22 Nov 2016 15:46:58 +0100 Subject: [PATCH 036/158] Some simplifications due to better c++11 support (constexpr). --- meta/EDM.m | 29 ++++++------- templates/edm.cpp.in | 99 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 104 insertions(+), 24 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 3aa5ceee9..01edab1d4 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -324,26 +324,27 @@ If you add new kinds of vertices (e.g for new diagram types): fieldIndexStart = Table[fieldIndexStartF[i], {i, 1, Length[fields] + 1}]; + indexBounds = IndexBounds[parsedVertex]; + prototype = ("template<> struct " <> dataClassName <> "\n" <> "{\n" <> IndentText @ - ("typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> - "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> - "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> - "> fieldIndexStart;\n" <> - "static const index_bounds indexB;\n" + ("constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> + "> index_bounds" <> + If[NumberOfIndices[parsedVertex] =!= 0, + "= { " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };\n" + , + ";/n" + ] <> + "constexpr std::array ToString @ Length[fieldIndexStart] <> + "> fieldIndexStart = { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + " };\n" <> + "using vertex_type = " <> VertexClassName[parsedVertex] <> ";\n" ) <> "};"); - indexBounds = IndexBounds[parsedVertex]; - - If[NumberOfIndices[parsedVertex] =!= 0, - prototype = (prototype <> "\n" <> - "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" - );]; definition = ("template<> " <> functionClassName <> "::vertex_type\n" <> functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> "{\n" <> diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 233edaea6..52670ec48 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -43,6 +43,87 @@ using namespace flexiblesusy; namespace { +/** \brief Helper template for utils::make_array + */ +template +struct make_array_it +{ + using decayed_type = typename std::decay< + typename std::iterator_traits::value_type + >::type; + static constexpr bool use_cast = !std::is_same::value; + + template + static auto iterate( ForwardIterator begin, Args &&...args ) + -> typename std::enable_if< + !use_cast, + std::array + >::type + { + ForwardIterator copy( begin ); + return make_array_it::iterate( ++begin, + std::forward( args )..., *copy ); + } + + template + static auto iterate( ForwardIterator begin, Args &&...args ) + -> typename std::enable_if< + use_cast, + std::array + >::type + { + ForwardIterator copy( begin ); + return make_array_it::iterate( ++begin, + std::forward( args )..., T( *copy ) ); + } +}; + +/** \brief Specialized helper template for utils::make_array */ +template +struct make_array_it +{ + template + static auto iterate( ForwardIterator begin, Args &&...args ) + { + return std::array{ std::forward( args )... }; + } +}; + +/** \class make_array +* \brief Facility for easy construction of \a std::array +* objects. +* \tparam N The size of the to be constructed array +* \tparam T The type of the objects the array should hold +* or void (by default) if the type should be +* inferred. +*/ +template +struct make_array +{ + /** \brief Construct a \a std::array by copying values + * from a range. + * \tparam ForwardIterator The iterator type (usually inferred) + * \param[in] begin The iterator marking the beginning of + * the range to be copied. + * \returns A \a std::array holding the desired objects. + * \warning \a begin must be incrementable sufficiently + * often (\a N times) otherwise the behaviour + * is undefined. + */ + template + static auto iterate( ForwardIterator begin ) + { + using value_type = typename std::conditional< + std::is_void::value, + typename std::iterator_traits::value_type, + T + >::type; + + return detail::make_array_it::iterate( begin ); + } +}; + + /** * @class IndexBounds * @brief A class representing multiple (N) index ranges. @@ -301,18 +382,14 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; public: - using index_bounds = typename Data::index_bounds; - using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; - using fieldIndexStart = typename Data::fieldIndexStart; - /** * @fn indexBounds * @brief Returns the IndexBounds<> object of the VertexFunction. */ - static const index_bounds &indexBounds() { - return index_bounds(); + static constexpr decltype(Data::index_bounds) indexBounds() { + return Data::index_bounds; } /** @@ -325,11 +402,13 @@ public: * and starts at 0. */ template - static std::vector fieldIndices(const indices_type &indices) + static + std::array + fieldIndices(const Data::index_bounds::indices_type &indices) { - auto begin = indices.begin() + boost::mpl::at_c::type::value; - auto end = indices.begin() + boost::mpl::at_c::type::value; - return std::vector(begin, end); + constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; + auto begin = indices.begin() + Data::fieldIndexStart[fieldIndex]; + return utils::make_array::iterate(begin); } /** From 5cee44b8af57bccdcd986936450aea2927fee271 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 18:25:58 +0100 Subject: [PATCH 037/158] Small fixes --- meta/EDM.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 01edab1d4..9859ba285 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -472,7 +472,6 @@ If you add new kinds of vertices (e.g for new diagram types): cachedContributingDiagrams = ({#, Union @ (Sequence @@ Cases[diagrams, {#, diags_List} -> diags])} &) /@ edmFields; - Return[cachedContributingDiagrams]; ]; @@ -494,6 +493,6 @@ If you add new kinds of vertices (e.g for new diagram types): ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; -End[]; +(* TODO: End[]; *) EndPackage[]; From 4ee083b47c65aac14cda79fe9587be3a6797b2a3 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 20:59:14 +0100 Subject: [PATCH 038/158] Implemented ContributingDiagrams[] --- meta/EDM.m | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/meta/EDM.m b/meta/EDM.m index 9859ba285..c6bc96fa6 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -209,7 +209,141 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +<<<<<<< 379db5394ffb4373e1ea0bcc6a72e5a0ce7ee357 (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) +======= +(************************ Begin helper routines *******************************) + +(* Return the name of the SARAH particle family containing the muon *) +GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, + SARAH`Electron, + Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], + {p_, {Description -> "Muon", ___}} -> p, 1][[1]] + ]; +(* If the muon has a generation index, return it, otherwise return Null. + e.g. CMSSMNoFV has no muon generation index *) +GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; + +GetPhoton[] := SARAH`Photon; + +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; +SetAttributes[StripLorentzIndices, {Listable}]; + +(* Takes a SARAH particle and returns its antiparticle *) +AntiParticle[SARAH`bar[p_]] := p; +AntiParticle[Susyno`LieGroups`conj[p_]] := p; +AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, + If[IsScalar[pNoIndices] || IsVector[pNoIndices], + Susyno`LieGroups`conj[p], + SARAH`bar[p]]]; +SetAttributes[AntiParticle, {Listable}]; + +(* Return a string corresponding to the c++ class name of the particle. + Note that "bar" and "conj" get turned into anti<...>::type! *) +ParticleToCXXName[p_] := SymbolName[p]; +ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; + +(* Return a string corresponding to the name of the particle. + Note that "bar" and "conj" are left as they are! *) +ParticleToSARAHString[p_] := SymbolName[p]; +ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; +ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; + +(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) +ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], + Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; + +(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) +IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := + ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); + +(* Returns the rules that are needed to change order of a prticle list. + i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} + For some reason SARAH expects the indices to always be in that order... *) +IndexReplacementRulesForParticleReordering[particles_List, ordering_] := +Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, + Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; + +(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) +OrderParticles[particles_List, ordering_] := Module[{indexRules}, + indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; + Return[particles[[ordering]] /. indexRules]; + ]; + +(* Essentially the same as above, but using the obtained rules, + transform a whole vertex expression, as returned by SARAH`Vertex[] *) +OrderVertex[vertex_, ordering_] := + Module[{indexRules, particles, expr, newVertex}, + indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; + + particles = vertex[[1]][[ordering]]; + expr = vertex[[2;;]]; + + newVertex = (Join[{particles}, expr] /. indexRules); + Return[newVertex]; + ]; + +(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) +(* MemoizingVertex[] only works when __no__ indices are specified!!! *) +(* Use of memoization gives ~30% speedup for the MSSM! *) +memoizedVertices = {}; +MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := + Module[{memo, ordering, orderedParticles}, + (* First we sort the particles *) + ordering = Ordering[particles]; + orderedParticles = particles[[ordering]]; + + memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; + If[memo =!= {}, memo = memo[[1]], + (* Create a new entry *) + memo = SARAH`Vertex[orderedParticles, options]; + AppendTo[memoizedVertices, memo];]; + + (* Now return the particles to their original order *) + memo = OrderVertex[memo, Ordering[ordering]]; + Return[memo]]; + +MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; + +(* Test whether a SARAH Vertex[] result is nonzero (exact) *) +IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; + +(* Returns the name of the coupling function that FlexibleSUSY generates for + a specific vertex in a canonical order! *) +NameOfCouplingFunction[particles_List] := +((* FIXME: Not upwards compatible if naming conventions change *) + "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); + +(********************** End helper routines **************************) + +(* The different vertex types that are supported. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; + +(* The different diagram types that should be taken into consideration *) +(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) +(* There is no bounds check done on the integers, so they have to fit + into a standard c++ unsigned (!) int *) +contributingDiagramTypes = { + OneLoopDiagram[0], + OneLoopDiagram[1] +}; + +(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +>>>>>>> Implemented ContributingDiagrams[] (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, From 5d80ca4cbd49db47eeffb59e99b693ee9dcc3639 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 21:08:51 +0100 Subject: [PATCH 039/158] Fixed bug in ContributingDiagramsOfType[] --- meta/EDM.m | 134 ----------------------------------------------------- 1 file changed, 134 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index c6bc96fa6..9859ba285 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -209,141 +209,7 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -<<<<<<< 379db5394ffb4373e1ea0bcc6a72e5a0ce7ee357 (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) -======= -(************************ Begin helper routines *******************************) - -(* Return the name of the SARAH particle family containing the muon *) -GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, - SARAH`Electron, - Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], - {p_, {Description -> "Muon", ___}} -> p, 1][[1]] - ]; -(* If the muon has a generation index, return it, otherwise return Null. - e.g. CMSSMNoFV has no muon generation index *) -GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; - -GetPhoton[] := SARAH`Photon; - -IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; - -StripLorentzIndices[p_Symbol] := p; -StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; -StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; -StripLorentzIndices[p_] := Module[{remainingIndices}, - remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; - If[Length[remainingIndices] === 0, Head[p], - Head[p][remainingIndices]] - ]; -SetAttributes[StripLorentzIndices, {Listable}]; - -(* Takes a SARAH particle and returns its antiparticle *) -AntiParticle[SARAH`bar[p_]] := p; -AntiParticle[Susyno`LieGroups`conj[p_]] := p; -AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, - If[IsScalar[pNoIndices] || IsVector[pNoIndices], - Susyno`LieGroups`conj[p], - SARAH`bar[p]]]; -SetAttributes[AntiParticle, {Listable}]; - -(* Return a string corresponding to the c++ class name of the particle. - Note that "bar" and "conj" get turned into anti<...>::type! *) -ParticleToCXXName[p_] := SymbolName[p]; -ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; - -(* Return a string corresponding to the name of the particle. - Note that "bar" and "conj" are left as they are! *) -ParticleToSARAHString[p_] := SymbolName[p]; -ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; -ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; - -(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) -ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], - Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; - -(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) -IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := - ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); - -(* Returns the rules that are needed to change order of a prticle list. - i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} - For some reason SARAH expects the indices to always be in that order... *) -IndexReplacementRulesForParticleReordering[particles_List, ordering_] := -Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, - Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; - -(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) -OrderParticles[particles_List, ordering_] := Module[{indexRules}, - indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; - Return[particles[[ordering]] /. indexRules]; - ]; - -(* Essentially the same as above, but using the obtained rules, - transform a whole vertex expression, as returned by SARAH`Vertex[] *) -OrderVertex[vertex_, ordering_] := - Module[{indexRules, particles, expr, newVertex}, - indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; - - particles = vertex[[1]][[ordering]]; - expr = vertex[[2;;]]; - - newVertex = (Join[{particles}, expr] /. indexRules); - Return[newVertex]; - ]; - -(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) -(* MemoizingVertex[] only works when __no__ indices are specified!!! *) -(* Use of memoization gives ~30% speedup for the MSSM! *) -memoizedVertices = {}; -MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := - Module[{memo, ordering, orderedParticles}, - (* First we sort the particles *) - ordering = Ordering[particles]; - orderedParticles = particles[[ordering]]; - - memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; - If[memo =!= {}, memo = memo[[1]], - (* Create a new entry *) - memo = SARAH`Vertex[orderedParticles, options]; - AppendTo[memoizedVertices, memo];]; - - (* Now return the particles to their original order *) - memo = OrderVertex[memo, Ordering[ordering]]; - Return[memo]]; - -MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; - -(* Test whether a SARAH Vertex[] result is nonzero (exact) *) -IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; - -(* Returns the name of the coupling function that FlexibleSUSY generates for - a specific vertex in a canonical order! *) -NameOfCouplingFunction[particles_List] := -((* FIXME: Not upwards compatible if naming conventions change *) - "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); - -(********************** End helper routines **************************) - -(* The different vertex types that are supported. - They have the same names as their c++ counterparts. *) -vertexTypes = { - SingleComponentedVertex, - LeftAndRightComponentedVertex -}; - -(* The different diagram types that should be taken into consideration *) -(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) -(* There is no bounds check done on the integers, so they have to fit - into a standard c++ unsigned (!) int *) -contributingDiagramTypes = { - OneLoopDiagram[0], - OneLoopDiagram[1] -}; - -(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) ->>>>>>> Implemented ContributingDiagrams[] (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, From 0cb3bc8a0edb14699935638896c1dc8cc2d4fc3e Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 19:49:14 +0100 Subject: [PATCH 040/158] Fixed lots of problems in CachedVertex[]. --- meta/EDM.m | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 9859ba285..209b64f82 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -181,20 +181,6 @@ If you add new kinds of vertices (e.g for new diagram types): CXXNameOfField[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; CXXNameOfField[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -(**************** Other Functions ***************) - -AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; -AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; -AddIndexPattern[field_] := SARAH`getFull[SARAH`getBlank[field]] /. subIndexPattern; - -CachedVertex[fields_List] := -Module[{ - vertexPattern = Alternatives @@ ({#, ___} &) /@ - Permutations[AddIndexPattern /@ fields], - vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[fields]]}, - FirstCase[vertexList, vertexPattern] - ]; - CreateEvaluationContextSpecializations[] := Module[{fields, code}, fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; @@ -255,8 +241,6 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - - (* TODO: Add every permutation of the above vertices *) {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); From 321cb4fb0b54a763b526b0b5a3f5646942f263f6 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:04:16 +0100 Subject: [PATCH 041/158] Rewrote CreateVertexFunction[] --- meta/EDM.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta/EDM.m b/meta/EDM.m index 209b64f82..3d3bda93a 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -241,6 +241,8 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; + + (* TODO: Add every permutation of the above vertices *) {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); From 53f377a3f6b49b03b1f2686396715e3db6a96f5d Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:13:02 +0100 Subject: [PATCH 042/158] First steps towards integrating the EDM module. --- meta/FlexibleSUSY.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 5e7af59bf..c408fe0d6 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1451,7 +1451,6 @@ corresponding tadpole is real or imaginary (only in models with CP EDM`SetEDMFields[edmParticles]; fields = EDM`CreateFields[]; - chargeGetters = EDM`CreateChargeGetters[]; diagrams = EDM`CreateDiagrams[]; @@ -2024,6 +2023,9 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; +(* Get all nPointFunctions that EDM needs *) +PrepareEDM[] := EDM`NPointFunctions[]; + PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2171,7 +2173,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, + gmm2Vertices = {}, edmVertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2218,6 +2220,8 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; + (* EDM vertices *) + edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; From 189ec9c59353efad7d5319b8e4eb07f28a2cb3b4 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 7 Nov 2016 16:31:07 +0100 Subject: [PATCH 043/158] Some small fixes --- meta/EDM.m | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 3d3bda93a..960ef478d 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -93,6 +93,7 @@ If you add new kinds of vertices (e.g for new diagram types): "\n\n"] CreateDiagrams[] := +<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc Module[{diagramSubIndices, diagramTypeHeads, code}, code = StringJoin @ Riffle[(Module[{diagramType = #}, @@ -115,6 +116,21 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +======= + Module[{diagramTypes, diagramTypeHeads, code}, + diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); + + code = "// The different diagram types that contribute to the muon magnetic moment\n"; + code = (code <> + StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) + /@ diagramHeads, "\n"] <> + "\n\n"); + + code = (code <> "// Indexed diagram types\n" <> + StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> + "<" <> ToString @ #[[1]] <> "> {};" &) + /@ contributingDiagramTypes, "\n"]); +>>>>>>> Some small fixes CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; @@ -195,7 +211,75 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) +======= +(************************ Begin helper routines *******************************) + +GetPhoton[] := SARAH`Photon; + +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; +SetAttributes[StripLorentzIndices, {Listable}]; + +(* Return a string corresponding to the c++ class name of the particle. + Note that "bar" and "conj" get turned into anti<...>::type! *) +ParticleToCXXName[p_] := SymbolName[p]; +ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; + +(* Return a string corresponding to the name of the particle. + Note that "bar" and "conj" are left as they are! *) +ParticleToSARAHString[p_] := SymbolName[p]; +ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; +ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; + +subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); +AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; +AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; +AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; + +CachedVertex[particles_List] := + Module[{ + vertexPattern = Alternatives @@ ({#, ___} &) /@ + Permutations[AddIndexPattern /@ particles], + vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, + FirstCase[vertexList, vertexPattern] + ]; + +(* Returns the name of the coupling function that FlexibleSUSY generates for + a specific vertex in a canonical order! *) +NameOfCouplingFunction[particles_List] := +((* FIXME: Not upwards compatible if naming conventions change *) + "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); + +(********************** End helper routines **************************) + +(* The different vertex types that are supported. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; + +(* The different diagram types that should be taken into consideration *) +(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) +(* There is no bounds check done on the integers, so they have to fit + into a standard c++ unsigned (!) int *) +contributingDiagramTypes = { + OneLoopDiagram[0] +}; + +(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +>>>>>>> Some small fixes (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, @@ -282,7 +366,6 @@ If you add new kinds of vertices (e.g for new diagram types): CouplingsForFields[fields_List] := Module[{vertexType, couplings}, vertexType = VertexTypeForFields[fields]; - couplings = {SARAH`Cp @@ fields}; Switch[vertexType, From 7bf39f8349b0ed234ad7f470905f1f86a90a14f0 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 14 Nov 2016 22:13:09 +0100 Subject: [PATCH 044/158] Too much to describe... --- meta/EDM.m | 90 +----------------------------------------------------- 1 file changed, 1 insertion(+), 89 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 960ef478d..e25ff961d 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -5,7 +5,6 @@ Initialize::usage="Initialize the EDM module."; SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; - CreateFields::usage="Returns the c++ code that contains all field fields"; CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM fields."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; @@ -93,9 +92,7 @@ If you add new kinds of vertices (e.g for new diagram types): "\n\n"] CreateDiagrams[] := -<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc -Module[{diagramSubIndices, diagramTypeHeads, code}, - +Module[{code}, code = StringJoin @ Riffle[(Module[{diagramType = #}, "template class " <> SymbolName[diagramType] <> ";\n" <> StringJoin @ Riffle[("template<> class " <> SymbolName[diagramType] <> @@ -116,21 +113,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -======= - Module[{diagramTypes, diagramTypeHeads, code}, - diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); - - code = "// The different diagram types that contribute to the muon magnetic moment\n"; - code = (code <> - StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) - /@ diagramHeads, "\n"] <> - "\n\n"); - - code = (code <> "// Indexed diagram types\n" <> - StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> - "<" <> ToString @ #[[1]] <> "> {};" &) - /@ contributingDiagramTypes, "\n"]); ->>>>>>> Some small fixes CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; @@ -211,75 +193,7 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) -======= -(************************ Begin helper routines *******************************) - -GetPhoton[] := SARAH`Photon; - -IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; - -StripLorentzIndices[p_Symbol] := p; -StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; -StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; -StripLorentzIndices[p_] := Module[{remainingIndices}, - remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; - If[Length[remainingIndices] === 0, Head[p], - Head[p][remainingIndices]] - ]; -SetAttributes[StripLorentzIndices, {Listable}]; - -(* Return a string corresponding to the c++ class name of the particle. - Note that "bar" and "conj" get turned into anti<...>::type! *) -ParticleToCXXName[p_] := SymbolName[p]; -ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; - -(* Return a string corresponding to the name of the particle. - Note that "bar" and "conj" are left as they are! *) -ParticleToSARAHString[p_] := SymbolName[p]; -ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; -ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; - -subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); -AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; -AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; -AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; - -CachedVertex[particles_List] := - Module[{ - vertexPattern = Alternatives @@ ({#, ___} &) /@ - Permutations[AddIndexPattern /@ particles], - vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, - FirstCase[vertexList, vertexPattern] - ]; - -(* Returns the name of the coupling function that FlexibleSUSY generates for - a specific vertex in a canonical order! *) -NameOfCouplingFunction[particles_List] := -((* FIXME: Not upwards compatible if naming conventions change *) - "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); - -(********************** End helper routines **************************) - -(* The different vertex types that are supported. - They have the same names as their c++ counterparts. *) -vertexTypes = { - SingleComponentedVertex, - LeftAndRightComponentedVertex -}; - -(* The different diagram types that should be taken into consideration *) -(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) -(* There is no bounds check done on the integers, so they have to fit - into a standard c++ unsigned (!) int *) -contributingDiagramTypes = { - OneLoopDiagram[0] -}; - -(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) ->>>>>>> Some small fixes (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, @@ -374,8 +288,6 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (* Creates the actual c++ code for a vertex with given fields. - If the c++ for the field list has already been created, two - empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) CreateVertexFunction[fields_List, vertexRules_List] := From 1e0a87a07eb884bed8f2a90b342d8f975aaf85cf Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:58:04 +0100 Subject: [PATCH 045/158] Preparing for first run. --- meta/FlexibleSUSY.m | 2 +- templates/edm.cpp.in | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index c408fe0d6..6f40f96db 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,7 +2024,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := EDM`NPointFunctions[]; +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 52670ec48..f4111b3c0 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -123,7 +123,6 @@ struct make_array } }; - /** * @class IndexBounds * @brief A class representing multiple (N) index ranges. From 49f3be8b122600ca3dba640fc7b4b39216b8051e Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:02:39 +0100 Subject: [PATCH 046/158] Fixed Typo --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index e25ff961d..54145e591 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -461,7 +461,7 @@ If you add new kinds of vertices (e.g for new diagram types): If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, SA`CurrentStates = FlexibleSUSY`FSEigenstates; SARAH`InitVertexCalculation[FlexibleSUSY`FSEigenstates, False]; - SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; + SARAH`ReadVertexList[FlexibleSUSY`FSEigenstates, False, False, True]; SARAH`MakeCouplingLists; ]; ]; From 82f1c455910fbf14d073306a38d37dca233fb7d9 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:43:59 +0100 Subject: [PATCH 047/158] Added edm as build template. Lots of small codegen fixes. --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 6f40f96db..22e744aac 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,7 +2024,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, From 6f0bfb1c9982bcfbd248cc14d89c5bb975727ddb Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:57:55 +0100 Subject: [PATCH 048/158] Fixed a dependency on a SARAH symbol that is only available after SARAH`Start[]. --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 22e744aac..23c2d725d 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,7 +2024,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); +PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, From 51cd45082acbee7c60f271beff4b1531dcbf4a0f Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 15:34:31 +0100 Subject: [PATCH 049/158] Fixed scoping issues. --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 54145e591..c7f190326 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -474,6 +474,6 @@ If you add new kinds of vertices (e.g for new diagram types): ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; -(* TODO: End[]; *) +End[]; EndPackage[]; From f417bd3cd01be0197f83587a0597ee0b3afe0d04 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:44:50 +0100 Subject: [PATCH 050/158] Moved Vertex logic to a place where the vertex files definitely exist. --- meta/FlexibleSUSY.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 23c2d725d..18b06f3c4 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2023,9 +2023,6 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; -(* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); - PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2173,7 +2170,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, edmVertices = {}, + gmm2Vertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2220,8 +2217,6 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; - (* EDM vertices *) - edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; @@ -2731,10 +2726,17 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; +<<<<<<< 367d2fb1e47420799045d314a2f65870790d20ee Put[vertexRules = Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; +======= + Put[vertexRules = + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], + vertexRuleFileName], + vertexRules = Get[vertexRuleFileName]; +>>>>>>> Moved Vertex logic to a place where the vertex files definitely exist. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; From 6ecdcf3a6fda924dba558b009e21e125208ae98d Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:45:19 +0100 Subject: [PATCH 051/158] Fixed typos. --- templates/edm.cpp.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index f4111b3c0..14ab68121 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -381,6 +381,8 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; public: + using index_bounds = typename Data::index_bounds; + using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; /** From f7365c6e5e6b968f8064553a92b218919b2214a5 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 22 Nov 2016 15:46:58 +0100 Subject: [PATCH 052/158] Some simplifications due to better c++11 support (constexpr). --- templates/edm.cpp.in | 2 -- 1 file changed, 2 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 14ab68121..f4111b3c0 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -381,8 +381,6 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; public: - using index_bounds = typename Data::index_bounds; - using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; /** From c72000c66c0df8127eb5b79ad8dd2e0919323aec Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 16:32:26 +0100 Subject: [PATCH 053/158] Implemented EDM calculation function. --- templates/edm.cpp.in | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index f4111b3c0..b50c38d48 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -43,6 +43,8 @@ using namespace flexiblesusy; namespace { +static constexpr oneOver16PiSquared = 0.0063325739776461107152; + /** \brief Helper template for utils::make_array */ template @@ -556,6 +558,7 @@ double OneLoopFunctionF2N(double x) @EDM_Definitions@ +// PhotonEmitter is the fermion template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField @@ -563,10 +566,45 @@ double DiagramEvaluator, { double res = 0.0; + using FermionVertex = VertexFunction< + EDMField, + typename anti::type, + typename anti::type + >; + + for( auto indexIt = FermionVertex::indexBounds().begin(), + indexIt != FermionVertex::indexBounds().end(); + ++indexIt ) + { + constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); + constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); + auto &vertex = FermionVertex::vertex(*indexIt, context); + + auto photonEmitterMass = context.mass( photonEmitterIndices ); + auto exchangeFieldMass = context.mass( exchangeFieldIndices ); + + constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + + constexpr double numericFactor = oneOver16PiSquared; + double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); + double couplingFactor = (std::conj( vertex.right() ) * vertex.left()).imag(); + + double massRatioSquared = photonEmitterMass/exchangeFieldMass; + massRatioSquared *= massRatioSquared; + + double loopFactor = (photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ) + + exchangeFieldChargeCount * OneLoopFunctionB( massRatioSquared )); + + double contribution = numericFactor * massFactor * couplingFactor * loopFactor; + + res += contribution; + } return res; } +// ExchangeField is fermion template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField @@ -574,7 +612,40 @@ double DiagramEvaluator, { double res = 0.0; + using FermionVertex = VertexFunction< + EDMField, + typename anti::type, + typename anti::type + >; + + for( auto indexIt = FermionVertex::indexBounds().begin(), + indexIt != FermionVertex::indexBounds().end(); + ++indexIt ) + { + constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); + constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); + auto &vertex = FermionVertex::vertex(*indexIt, context); + + auto photonEmitterMass = context.mass( photonEmitterIndices ); + auto exchangeFieldMass = context.mass( exchangeFieldIndices ); + + constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + constexpr double numericFactor = oneOver16PiSquared; + double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); + double couplingFactor = (std::conj( vertex.right() ) * vertex.left()).imag(); + + double massRatioSquared = exchangeFieldMass / photonEmitterMass; + massRatioSquared *= massRatioSquared; + + double loopFactor = (exchangeFieldChargeCount * OneLoopFunctionA( massRatioSquared ) + + photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared )); + + double contribution = numericFactor * massFactor * couplingFactor * loopFactor; + + res += contribution; + } return res; } From 696935ba51137e0f2ef9a5440faf39f6e8bd23e8 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 16:53:47 +0100 Subject: [PATCH 054/158] Implemented One Loop Functions --- templates/edm.cpp.in | 147 ++++++++++++------------------------------- 1 file changed, 41 insertions(+), 106 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index b50c38d48..c3bc27c73 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -437,125 +437,60 @@ double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstate namespace { /** * @defgroup LoopFunctions -* @brief The loop functions necessary for \f$a_\mu\f$ one-loop calculations. +* @brief The loop functions necessary for edm one-loop calculations. * -* These are OneLoopFunctionF1C(), OneLoopFunctionF2C(), -* OneLoopFunctionF1N() and OneLoopFunctionF2N() -* as specified in arXiv:1311.1775 +* These are OneLoopFunctionA(), OneLoopFunctionB() +* as specified in arXiv:0808.1819 */ -double OneLoopFunctionF1C(double x) +constexpr double OneLoopFunctionA(double r) { - if (is_zero(x)) - return 4.0; - - // error around x=1 is <= 10^-12 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.21) { - return (1.0000000000000000000 - - 0.60000000000000000000 * y + - 0.40000000000000000000 * y * y - - 0.28571428571428571429 * y * y * y + - 0.21428571428571428571 * y * y * y * y - - 0.16666666666666666667 * y * y * y * y * y + - 0.13333333333333333333 * y * y * y * y * y * y - - 0.10909090909090909091 * y * y * y * y * y * y * y + - 0.090909090909090909091 * y * y * y * y * y * y * y * y - - 0.076923076923076923077 * y * y * y * y * y * y * y * y * y + - 0.065934065934065934066 * y * y * y * y * y * y * y * y * y * y - - 0.057142857142857142857 * y * y * y * y * y * y * y * y * y * y * y + - 0.050000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.044117647058823529412 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.039215686274509803922 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.035087719298245614035 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + if( is_zero(r) ) + return std::numeric_limits::infinity(); + + const double d = r - 1.0; + + if( std::abs(d) < 0.15 ) { + return (-0.33333333333333333333 + + 0.25000000000000000000 * d - + 0.20000000000000000000 * d * d + + 0.16666666666666666667 * d * d * d - + 0.14285714285714285714 * d * d * d * d + + 0.12500000000000000000 * d * d * d * d * d - + 0.11111111111111111111 * d * d * d * d * d * d + + 0.10000000000000000000 * d * d * d * d * d * d * d - + 0.090909090909090909091 * d * d * d * d * d * d * d * d + + 0.083333333333333333333 * d * d * d * d * d * d * d * d * d - + 0.076923076923076923077 * d * d * d * d * d * d * d * d * d * d ); } - return 2.0 / (y * y * y * y) * (2.0 + 3.0 * x - 6.0 * x * x + x * x * x + 6.0 * x * std::log(x)); + return 1.0 / (2.0 * d * d) * (3.0 - r + 2.0 * std::log(r) / d); } -double OneLoopFunctionF2C(double x) +double OneLoopFunctionB(double x) { - // error around x=1 is <= 10^-13 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.155) - return (1.0 - 0.75 * y + 0.6 * y * y - - 0.50000000000000000000 * y * y * y + - 0.4285714285714285714 * y * y * y * y - - 0.37500000000000000000 * y * y * y * y * y + - 0.33333333333333333333 * y * y * y * y * y * y - - 0.3000000000000000000 * y * y * y * y * y * y * y + - 0.2727272727272727273 * y * y * y * y * y * y * y * y - - 0.2500000000000000000 * y * y * y * y * y * y * y * y * y + - 0.23076923076923076923 * y * y * y * y * y * y * y * y * y * y - - 0.21428571428571428571 * y * y * y * y * y * y * y * y * y * y * y + - 0.2000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.1875000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.1764705882352941176 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.16666666666666666667 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + if( is_zero(r) ) + return 1.0/2.0; + + const double d = r - 1.0; + + if( std::abs(y) < 0.15 ) + return (0.16666666666666666667 - + 0.083333333333333333333 * d + + 0.050000000000000000000 * d * d - + 0.033333333333333333333 * d * d * d + + 0.023809523809523809524 * d * d * d * d - + 0.017857142857142857143 * d * d * d * d * d + + 0.013888888888888888889 * d * d * d * d * d * d - + 0.011111111111111111111 * d * d * d * d * d * d * d + + 0.0090909090909090909091 * d * d * d * d * d * d * d * d - + 0.0075757575757575757576 * d * d * d * d * d * d * d * d * d + + 0.0064102564102564102564 * d * d * d * d * d * d * d * d * d * d ); +); return -3.0 / (2.0 * y * y * y) * (-3.0 + 4.0 * x - x * x - 2.0 * std::log(x)); } -double OneLoopFunctionF1N(double x) -{ - if (is_zero(x)) - return 2.0; - - // error around x=1 is <= 10^-12 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.23) - return (1.0000000000000000000 - - 0.4000000000000000000 * y + - 0.2000000000000000000 * y * y - - 0.11428571428571428571 * y * y * y + - 0.07142857142857142857 * y * y * y * y - - 0.04761904761904761905 * y * y * y * y * y + - 0.03333333333333333333 * y * y * y * y * y * y - - 0.02424242424242424242 * y * y * y * y * y * y * y + - 0.0181818181818181818 * y * y * y * y * y * y * y * y - - 0.01398601398601398601 * y * y * y * y * y * y * y * y * y + - 0.01098901098901098901 * y * y * y * y * y * y * y * y * y * y - - 0.0087912087912087912 * y * y * y * y * y * y * y * y * y * y * y + - 0.00714285714285714286 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.0058823529411764706 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.0049019607843137255 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.0041279669762641899 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); - - return 2.0 / (y * y * y * y) * (1.0 - 6.0 * x + 3.0 * x * x + 2.0 * x * x * x - 6.0 * x * x * std::log(x)); -} - -double OneLoopFunctionF2N(double x) -{ - if (is_zero(x)) - return 3.0; - - // error around x=1 is <= 10^-13 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.185) - return (1.0000000000000000000 - - 0.50000000000000000000 * y + - 0.30000000000000000000 * y * y - - 0.2000000000000000000 * y * y * y + - 0.14285714285714285714 * y * y * y * y - - 0.10714285714285714286 * y * y * y * y * y + - 0.08333333333333333333 * y * y * y * y * y * y - - 0.06666666666666666667 * y * y * y * y * y * y * y + - 0.05454545454545454545 * y * y * y * y * y * y * y * y - - 0.0454545454545454545 * y * y * y * y * y * y * y * y * y + - 0.0384615384615384615 * y * y * y * y * y * y * y * y * y * y - - 0.03296703296703296703 * y * y * y * y * y * y * y * y * y * y * y + - 0.0285714285714285714 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.02500000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.0220588235294117647 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.0196078431372549020 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); - - return -3.0 / (y * y * y) * (1.0 - x * x + 2.0 * x * std::log(x)); -} - @EDM_Definitions@ // PhotonEmitter is the fermion From 5e985ce84dad8366d6409796196b72e447b48f68 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 18:27:47 +0100 Subject: [PATCH 055/158] Implemented charge getters. --- meta/EDM.m | 105 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 29 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index c7f190326..c89350722 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -62,34 +62,72 @@ If you add new kinds of vertices (e.g for new diagram types): "anti<" <> CXXNameOfField[#] <> ">" <> " { using type = " <> CXXNameOfField[#] <> "; };" &) /@ Select[fields, (# == SARAH`AntiField[#] &)], - "\n"] + "\n"] <> "\n\n" <> + + "template struct field_indices;\n\n" <> + + StringJoin @ Riffle[("template<> struct field_indices<" <> + CXXNameOfField[#] <> ">\n" <> + "{\n" <> + IndentText @ + ("using type = std::array + ToString @ Length @ CleanFieldInfo[#][[5]] <> + ">;\n" + ) <> + "};\n" &) /@ fields, "\n"] ); Return[code]; ]; -CreateChargeGetters[] := -"template\n" <> -"double charge( EvaluationContext & );\n\n" <> -"template\n" <> -"double charge( unsigned, EvaluationContext & );\n\n" <> -StringJoin @ Riffle[(Module[{photonVertexFields, fieldDim = TreeMasses`GetDimension[#]}, - photonVertexFields = {SARAH`Photon, #, SARAH`AntiField[#]}; - "template<>\n" <> - "double charge<" <> CXXNameOfField[#] <> ">" <> - If[fieldDim === 1, "( ", - "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> - IndentText["using VF = VertexFunction<" <> - StringJoin @ Riffle[CXXNameOfField /@ photonVertexFields, ", "] <> - ">;\n" <> - If[fieldDim === 1, - "constexpr std::array indices{};\n", - "const std::array indices{ index, index };\n" - ] <> - "return VF::vertex(indices, context).left().real();" - ] <> "\n}" - ] &) /@ edmFields, - "\n\n"] +CreateChargeCountGetters[] := +Module[{contributingDiagrams, photonEmitters, + electronDimension = TreeMasses`GetDimension[SARAH`Electron]}, + contributingDiagrams = ContributingDiagrams[]; + photonEmitters = Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; + + "double electronCharge( EvaluationContext &context )\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> + ">;\n" <> + If[electronDimension === 1, + "constexpr std::array indices{};\n", + "constexpr std::array indices{" <> + ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" + ] <> + "return PhotonVertex::vertex( indices, context ).left().real();\n" + ) <> + "}\n\n" <> + "template\n" <> + "double chargeCount( const typename field_indices::type &, EvaluationContext & );\n\n" <> + StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], + photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], + numberOfIndices}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; + fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; + + numberOfIndices = Length @ fieldInfo[[5]]; + + "template<>\n" <> + "double chargeCount<" <> CXXNameOfField[#] <> + ">( const std::array ToString @ numberOfIndices <> + "> &indices, EvaluationContext &context )\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> + ">;\n\n" <> + "double fieldCharge = PhotonVertex::vertex( concat( indices, indices ), context )" <> + If[photonVertexType === SingleComponentedVertex, + ".value().real();\n", + ".left().real();\n"] <> + "double electronCharge = electronCharge( context );\n\n" <> + "return fieldCharge / electronCharge;\n" + ) <> + "}"] &) /@ photonEmitters, "\n\n"] + ]; CreateDiagrams[] := Module[{code}, @@ -179,6 +217,16 @@ If you add new kinds of vertices (e.g for new diagram types): CXXNameOfField[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; CXXNameOfField[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +(**************** Other Functions ***************) + +GetElectronIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 1, Null]; + +CleanFieldInfo[field_] := Module[{fieldInfo = FirstCase[SARAH`Particles[FlexibleSUSY`FSEigenstates], + {SARAH`getParticleName @ field, ___}]}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {2}]; + DeleteCases[fieldInfo, {SARAH`lorentz, _}, {2}] + ]; + CreateEvaluationContextSpecializations[] := Module[{fields, code}, fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; @@ -251,9 +299,10 @@ If you add new kinds of vertices (e.g for new diagram types): (* Returns the vertices that are present in the specified diagram. This function should be overloaded for future diagram types. *) VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmField_, photonEmitter_, exchangeField_]] := - Module[{edmVertex}, + Module[{edmVertex, photonVertex}, edmVertex = {edmField, SARAH`AntiField[photonEmitter], SARAH`AntiField[exchangeField]}; - Return[{edmVertex}]; + photonVertex = {SARAH`Photon, photonEmitter, SARAH`AntiField[photonEmitter]}; + Return[{edmVertex, photonVertex}]; ]; (* Returns the vertex type for a vertex with a given list of fields *) @@ -370,7 +419,7 @@ If you add new kinds of vertices (e.g for new diagram types): ParseVertex[fields_List, vertexRules_List] := Module[{indexedFields, numberOfIndices, declareIndices, parsedVertex, vertexClassName, vertexFunctionBody, - sarahFields, fieldInfo, trIndexBounds, indexBounds, + fieldInfo, trIndexBounds, indexBounds, expr, exprL, exprR}, indexedFields = MapIndexed[(Module[{field = #1, index = #2[[1]]}, @@ -404,9 +453,7 @@ If you add new kinds of vertices (e.g for new diagram types): Parameters`ExpressionToString[exprR] <> ";\n\n" <> "return vertex_type(left, right);"]; - sarahFields = SARAH`getParticleName /@ fields; - fieldInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ - sarahFields, 1]; + fieldInfo = CleanFieldInfo /@ fields; trIndexBounds = Cases[Flatten[(With[{fieldIndex = #}, (If[#[[1]] === SARAH`generation, From fb25bf9297d1b8e93786d6284a45abceea3be011 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 18:28:45 +0100 Subject: [PATCH 056/158] Renamed function --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 18b06f3c4..d75dd09c1 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1451,7 +1451,7 @@ corresponding tadpole is real or imaginary (only in models with CP EDM`SetEDMFields[edmParticles]; fields = EDM`CreateFields[]; - chargeGetters = EDM`CreateChargeGetters[]; + chargeGetters = EDM`CreateChargeCountGetters[]; diagrams = EDM`CreateDiagrams[]; vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; From a3557bfd671a4d6d155cc955e38e9130a7875a70 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 5 Dec 2016 13:01:58 +0100 Subject: [PATCH 057/158] Things should work now! --- meta/EDM.m | 143 +++++++++++++++++++++++-------------------- meta/FlexibleSUSY.m | 11 +--- templates/edm.cpp.in | 104 +++++++++++++++++++------------ 3 files changed, 143 insertions(+), 115 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index c89350722..a5f29f7f5 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -6,7 +6,6 @@ SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; CreateFields::usage="Returns the c++ code that contains all field fields"; -CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM fields."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; CreateDefinitions::usage="Returns the c++ that contains all function definitions" @@ -80,55 +79,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateChargeCountGetters[] := -Module[{contributingDiagrams, photonEmitters, - electronDimension = TreeMasses`GetDimension[SARAH`Electron]}, - contributingDiagrams = ContributingDiagrams[]; - photonEmitters = Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; - - "double electronCharge( EvaluationContext &context )\n" <> - "{\n" <> - IndentText @ - ("using PhotonVertex = VertexFunction - CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> - ">;\n" <> - If[electronDimension === 1, - "constexpr std::array indices{};\n", - "constexpr std::array indices{" <> - ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" - ] <> - "return PhotonVertex::vertex( indices, context ).left().real();\n" - ) <> - "}\n\n" <> - "template\n" <> - "double chargeCount( const typename field_indices::type &, EvaluationContext & );\n\n" <> - StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], - photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], - numberOfIndices}, - fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; - fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; - - numberOfIndices = Length @ fieldInfo[[5]]; - - "template<>\n" <> - "double chargeCount<" <> CXXNameOfField[#] <> - ">( const std::array ToString @ numberOfIndices <> - "> &indices, EvaluationContext &context )\n" <> - "{\n" <> - IndentText @ - ("using PhotonVertex = VertexFunction - CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> - ">;\n\n" <> - "double fieldCharge = PhotonVertex::vertex( concat( indices, indices ), context )" <> - If[photonVertexType === SingleComponentedVertex, - ".value().real();\n", - ".left().real();\n"] <> - "double electronCharge = electronCharge( context );\n\n" <> - "return fieldCharge / electronCharge;\n" - ) <> - "}"] &) /@ photonEmitters, "\n\n"] - ]; - CreateDiagrams[] := Module[{code}, code = StringJoin @ Riffle[(Module[{diagramType = #}, @@ -155,8 +105,8 @@ If you add new kinds of vertices (e.g for new diagram types): CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; CreateDefinitions[vertexRules_List] := -(CreateEvaluationContextSpecializations[] <> "\n\n" <> - CreateVertices[vertexRules][[2]]); +(CreateVertices[vertexRules][[2]] <> "\n\n" <> + CreateEvaluationContextSpecializations[]); CreateCalculation[] := Module[{code, evaluators}, @@ -221,6 +171,17 @@ If you add new kinds of vertices (e.g for new diagram types): GetElectronIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 1, Null]; +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; + CleanFieldInfo[field_] := Module[{fieldInfo = FirstCase[SARAH`Particles[FlexibleSUSY`FSEigenstates], {SARAH`getParticleName @ field, ___}]}, fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {2}]; @@ -228,17 +189,65 @@ If you add new kinds of vertices (e.g for new diagram types): ]; CreateEvaluationContextSpecializations[] := -Module[{fields, code}, +Module[{fields, contributingDiagrams, photonEmitters, + electronDimension = TreeMasses`GetDimension[SARAH`Electron]}, fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; + + contributingDiagrams = ContributingDiagrams[]; + photonEmitters = DeleteDuplicates @ Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; - code = (StringJoin @ - Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> - If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> - "{ return model.get_M" <> CXXNameOfField[#] <> - If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" - &) /@ fields, "\n\n"]); - - Return[code]; + StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], numberOfIndices}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; + fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; + + numberOfIndices = Length @ fieldInfo[[5]]; + + "template<> double EvaluationContext::mass<" <> ToString[#] <> + ">( const std::array ToString @ numberOfIndices <> + "> &indices ) const\n" <> + "{ return model.get_M" <> CXXNameOfField[#] <> + If[TreeMasses`GetDimension[#] === 1, "()", "( indices[0] )"] <> "; }" + ] &) /@ fields, "\n\n"] <> "\n\n" <> + + "double EvaluationContext::electronCharge( void ) const\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> + ">;\n" <> + If[electronDimension === 1, + "constexpr std::array indices{};\n", + "constexpr std::array indices{" <> + ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" + ] <> + "return PhotonVertex::vertex( indices, *this ).left().real();\n" + ) <> + "}\n\n" <> + + StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], + photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], + numberOfIndices}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; + fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; + + numberOfIndices = Length @ fieldInfo[[5]]; + + "template<>\n" <> + "double EvaluationContext::chargeCount<" <> CXXNameOfField[#] <> + ">( const std::array ToString @ numberOfIndices <> + "> &indices ) const\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> + ">;\n\n" <> + "double fieldCharge = PhotonVertex::vertex( concatenate( indices, indices ), *this )" <> + If[photonVertexType === SingleComponentedVertex, + ".value().real();\n", + ".left().real();\n"] <> + "return fieldCharge / electronCharge();\n" + ) <> + "}"] &) /@ photonEmitters, "\n\n"] ]; (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) @@ -359,7 +368,7 @@ If you add new kinds of vertices (e.g for new diagram types): prototype = ("template<> struct " <> dataClassName <> "\n" <> "{\n" <> IndentText @ - ("constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> + ("static constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds" <> If[NumberOfIndices[parsedVertex] =!= 0, "= { " <> @@ -368,15 +377,15 @@ If you add new kinds of vertices (e.g for new diagram types): , ";/n" ] <> - "constexpr std::array ToString @ Length[fieldIndexStart] <> - "> fieldIndexStart = { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> - " };\n" <> + "static constexpr std::array ToString @ Length[fieldIndexStart] <> + "> fieldIndexStart = { { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + " } };\n" <> "using vertex_type = " <> VertexClassName[parsedVertex] <> ";\n" ) <> "};"); definition = ("template<> " <> functionClassName <> "::vertex_type\n" <> - functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> + functionClassName <> "::vertex(const indices_type &indices, const EvaluationContext &context)\n" <> "{\n" <> IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); @@ -425,6 +434,8 @@ If you add new kinds of vertices (e.g for new diagram types): index = #2[[1]]}, SARAH`getFull[#1] /. SARAH`subGC[index] /. SARAH`subIndFinal[index,index] ] &), fields]; + indexedFields = StripLorentzIndices /@ indexedFields; + numberOfIndices = ((Length @ Vertices`FieldIndexList[#] &) /@ indexedFields); declareIndices = DeclareIndices[indexedFields, "indices"]; diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index d75dd09c1..7a0edde97 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1445,13 +1445,12 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the EDM c++ files *) WriteEDMClass[vertexRules_List, files_List] := -Module[{fields, edmFields, chargeGetters, diagrams, vertexFunctionData, +Module[{fields, edmFields, diagrams, vertexFunctionData, definitions, calculationCode}, edmFields = {SARAH`Electron}; EDM`SetEDMFields[edmParticles]; fields = EDM`CreateFields[]; - chargeGetters = EDM`CreateChargeCountGetters[]; diagrams = EDM`CreateDiagrams[]; vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; @@ -1460,7 +1459,6 @@ corresponding tadpole is real or imaginary (only in models with CP WriteOut`ReplaceInFiles[files, { "@EDM_Fields@" -> fields, - "@EDM_ChargeGetters@" -> chargeGetters, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, @@ -2726,17 +2724,10 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; -<<<<<<< 367d2fb1e47420799045d314a2f65870790d20ee Put[vertexRules = Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; -======= - Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], - vertexRuleFileName], - vertexRules = Get[vertexRuleFileName]; ->>>>>>> Moved Vertex logic to a place where the vertex files definitely exist. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index c3bc27c73..ee524582f 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -33,8 +33,7 @@ #include #include -#include -#include +#include #define INPUTPARAMETER(p) context.model.get_input().p #define MODELPARAMETER(p) context.model.get_##p() @@ -43,9 +42,9 @@ using namespace flexiblesusy; namespace { -static constexpr oneOver16PiSquared = 0.0063325739776461107152; +static constexpr double oneOver16PiSquared = 0.0063325739776461107152; -/** \brief Helper template for utils::make_array +/** \brief Helper template for make_array */ template struct make_array_it @@ -80,12 +79,13 @@ struct make_array_it } }; -/** \brief Specialized helper template for utils::make_array */ +/** \brief Specialized helper template for make_array */ template struct make_array_it { template static auto iterate( ForwardIterator begin, Args &&...args ) + -> std::array { return std::array{ std::forward( args )... }; } @@ -114,6 +114,11 @@ struct make_array */ template static auto iterate( ForwardIterator begin ) + -> std::array::value, + typename std::iterator_traits::value_type, + T + >::type, N> { using value_type = typename std::conditional< std::is_void::value, @@ -121,10 +126,34 @@ struct make_array T >::type; - return detail::make_array_it::iterate( begin ); + return make_array_it::iterate( begin ); } }; +template +auto concatenate( const Array1 &a1, const Array2 &a2 ) +-> std::array< + typename std::common_type< + typename Array1::value_type, + typename Array1::value_type + >::type, + std::tuple_size::value + std::tuple_size::value> +{ + using value_type = typename std::common_type< + typename Array1::value_type, + typename Array1::value_type + >::type; + constexpr auto size = std::tuple_size::value + std::tuple_size::value; + + auto range1 = boost::make_iterator_range( boost::begin(a1), + boost::end(a1) ); + auto range2 = boost::make_iterator_range( boost::begin(a2), + boost::end(a2) ); + auto joined = boost::join( range1, range2 ); + + return make_array::iterate( boost::begin( joined ) ); +} + /** * @class IndexBounds * @brief A class representing multiple (N) index ranges. @@ -229,17 +258,16 @@ template struct IndexBounds { }; template<> struct IndexBounds<0> { - typedef const std::array indices_type; - typedef indices_type * const_iterator; + using indices_type = const std::array; + using const_iterator = indices_type *; - static const indices_type dummyIndex; + static constexpr indices_type dummyIndex{}; const_iterator begin() const { return &dummyIndex; } const_iterator end() const { return (begin()+1); } }; -IndexBounds<0>::indices_type IndexBounds<0>::dummyIndex{}; @EDM_Fields@ @@ -258,16 +286,16 @@ struct EvaluationContext { @ModelName@_mass_eigenstates& model; ///< The model object. /** - * @fn mass + * @fn mass * @brief Returns the mass of a field. */ - template double mass() const { - return mass::type>(); - } + template + double mass( const typename field_indices::type & ) const; - template double mass(unsigned index) const { - return mass::type>(index); - } + double electronCharge( void ) const; + + template + double chargeCount( const typename field_indices::type & ) const; }; /** @@ -289,8 +317,6 @@ double OneLoopFunctionF2C(double); double OneLoopFunctionF1N(double); double OneLoopFunctionF2N(double); -@EDM_ChargeGetters@ - @EDM_Diagrams@ /** @@ -384,6 +410,7 @@ template class VertexFunction { using Data = VertexFunctionData; public: using vertex_type = typename Data::vertex_type; + using indices_type = typename decltype(Data::index_bounds)::indices_type; /** * @fn indexBounds @@ -405,11 +432,11 @@ public: template static std::array - fieldIndices(const Data::index_bounds::indices_type &indices) + fieldIndices(const indices_type &indices) { constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; auto begin = indices.begin() + Data::fieldIndexStart[fieldIndex]; - return utils::make_array::iterate(begin); + return make_array::iterate(begin); } /** @@ -418,7 +445,7 @@ public: * @param indices The field indices * @param context The evaluation context */ - static vertex_type vertex(const indices_type &indices, EvaluationContext &context); + static vertex_type vertex(const indices_type &indices, const EvaluationContext &context); }; @EDM_VertexFunctionData@ @@ -443,7 +470,7 @@ namespace { * as specified in arXiv:0808.1819 */ -constexpr double OneLoopFunctionA(double r) +double OneLoopFunctionA(double r) { if( is_zero(r) ) return std::numeric_limits::infinity(); @@ -467,14 +494,14 @@ constexpr double OneLoopFunctionA(double r) return 1.0 / (2.0 * d * d) * (3.0 - r + 2.0 * std::log(r) / d); } -double OneLoopFunctionB(double x) +double OneLoopFunctionB(double r) { if( is_zero(r) ) return 1.0/2.0; const double d = r - 1.0; - if( std::abs(y) < 0.15 ) + if( std::abs(d) < 0.15 ) return (0.16666666666666666667 - 0.083333333333333333333 * d + 0.050000000000000000000 * d * d - @@ -486,9 +513,8 @@ double OneLoopFunctionB(double x) 0.0090909090909090909091 * d * d * d * d * d * d * d * d - 0.0075757575757575757576 * d * d * d * d * d * d * d * d * d + 0.0064102564102564102564 * d * d * d * d * d * d * d * d * d * d ); -); - return -3.0 / (2.0 * y * y * y) * (-3.0 + 4.0 * x - x * x - 2.0 * std::log(x)); + return 1.0 / (2.0 * d * d) * (1.0 + r + 2.0 * r * std::log(r) / d); } @EDM_Definitions@ @@ -507,19 +533,19 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(), + for( auto indexIt = FermionVertex::indexBounds().begin(); indexIt != FermionVertex::indexBounds().end(); ++indexIt ) { - constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); - constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); - auto &vertex = FermionVertex::vertex(*indexIt, context); + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); + auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); + auto vertex = FermionVertex::vertex(*indexIt, context); auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -553,19 +579,19 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(), + for( auto indexIt = FermionVertex::indexBounds().begin(); indexIt != FermionVertex::indexBounds().end(); ++indexIt ) { - constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); - constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); - auto &vertex = FermionVertex::vertex(*indexIt, context); + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); + auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); + auto vertex = FermionVertex::vertex(*indexIt, context); auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); From e188a413659c2373d643f8295fa7026b64ba04ac Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 5 Dec 2016 13:32:48 +0100 Subject: [PATCH 058/158] Fixed scope issue --- templates/edm.cpp.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index ee524582f..0eef688f9 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -544,8 +544,8 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -590,8 +590,8 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); From 8ebd75aef614d5785fcc29600a1fdef014c479d0 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 6 Dec 2016 15:14:22 +0100 Subject: [PATCH 059/158] Fixed overcounting and linking issues. --- meta/EDM.m | 13 ++++++----- meta/FlexibleSUSY.m | 6 +++++ templates/edm.cpp.in | 53 +++++++++++++++++++++++--------------------- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index a5f29f7f5..e11971a20 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -95,7 +95,7 @@ If you add new kinds of vertices (e.g for new diagram types): "struct DiagramEvaluator<" <> SymbolName[diagramType] <> "<" <> ToString @ # <> ">, EDMField, PhotonEmitter, ExchangeField>\n" <> - "{ static double value(EvaluationContext& context); };" + "{ static double value(const typename field_indices::type &indices, EvaluationContext& context); };" &) /@ diagramSubTypes[diagramType], "\n\n"]] &) /@ diagramTypes, "\n\n"] ); @@ -112,15 +112,18 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{code, evaluators}, evaluators = ConcreteDiagramEvaluators[]; - code = "template double edm( CMSSM_mass_eigenstates& model );\n\n"; + code = "template double edm( const typename field_indices::type &indices, CMSSM_mass_eigenstates& model );\n\n"; code = (code <> StringJoin @ Riffle[Module[{field = #[[1]], fieldEvaluators = #[[2]]}, - "template<> double edm<" <> CXXNameOfField[field] <> ">( CMSSM_mass_eigenstates& model )\n" <> + "template<> double edm<" <> CXXNameOfField[field] <> + ">( const std::array ToString @ Length @ CleanFieldInfo[field][[5]] <> + "> &indices, CMSSM_mass_eigenstates& model )\n" <> "{\n" <> IndentText["EvaluationContext context{ model };\n" <> "double val = 0.0;\n\n" <> - StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(context);" &) /@ fieldEvaluators, "\n"] <> "\n\n" <> + StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(indices, context);" &) /@ fieldEvaluators, "\n"] <> + "\n\n" <> "return val;" ] <> "\n}"] & /@ evaluators, "\n\n"]); @@ -371,7 +374,7 @@ If you add new kinds of vertices (e.g for new diagram types): ("static constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds" <> If[NumberOfIndices[parsedVertex] =!= 0, - "= { " <> + " = { " <> "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };\n" , diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 7a0edde97..e66f5e2a1 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1457,12 +1457,18 @@ corresponding tadpole is real or imaginary (only in models with CP definitions = EDM`CreateDefinitions[vertexRules]; calculationCode = EDM`CreateCalculation[]; + declareElectronIndices = If[electronDimension === 1, + "constexpr std::array electronIndices{};", + "constexpr std::array electronIndices{1};" + ]; + WriteOut`ReplaceInFiles[files, { "@EDM_Fields@" -> fields, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, "@EDM_Calculation@" -> calculationCode, + "@EDM_DeclareElectronIndices@" -> declareElectronIndices, Sequence @@ GeneralReplacementRules[] } ]; ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 0eef688f9..995940145 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -408,17 +408,14 @@ template struct VertexFunctionData; */ template class VertexFunction { using Data = VertexFunctionData; + using bounds_type = typename std::decay::type; + using fieldIndexStart_type = decltype(Data::fieldIndexStart); public: using vertex_type = typename Data::vertex_type; using indices_type = typename decltype(Data::index_bounds)::indices_type; - /** - * @fn indexBounds - * @brief Returns the IndexBounds<> object of the VertexFunction. - */ - static constexpr decltype(Data::index_bounds) indexBounds() { - return Data::index_bounds; - } + static constexpr bounds_type index_bounds = Data::index_bounds; + static constexpr fieldIndexStart_type fieldIndexStart = Data::fieldIndexStart; /** * @fn fieldIndices @@ -431,11 +428,11 @@ public: */ template static - std::array + std::array fieldIndices(const indices_type &indices) { - constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; - auto begin = indices.begin() + Data::fieldIndexStart[fieldIndex]; + constexpr auto length = fieldIndexStart[fieldIndex+1] - fieldIndexStart[fieldIndex]; + auto begin = indices.begin() + fieldIndexStart[fieldIndex]; return make_array::iterate(begin); } @@ -458,7 +455,9 @@ double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstate // make copy since model is modified via call to calculate_MFe_pole() @ModelName@_mass_eigenstates model(model_); - return edm( model ); + @EDM_DeclareElectronIndices@ + + return edm( electronIndices, model ); } namespace { @@ -523,7 +522,7 @@ double OneLoopFunctionB(double r) template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField ->::value(EvaluationContext &context) +>::value(const typename field_indices::type &indices, EvaluationContext &context) { double res = 0.0; @@ -533,10 +532,14 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(); - indexIt != FermionVertex::indexBounds().end(); - ++indexIt ) + constexpr auto indexBounds = FermionVertex::index_bounds; + for( auto indexIt = indexBounds.begin(); indexIt != indexBounds.end(); ++indexIt ) { + auto edmFieldIndices = FermionVertex::template fieldIndices<0>(*indexIt); + + if( edmFieldIndices != indices ) + continue; + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); auto vertex = FermionVertex::vertex(*indexIt, context); @@ -545,7 +548,6 @@ double DiagramEvaluator, auto exchangeFieldMass = context.mass( exchangeFieldIndices ); double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -554,8 +556,7 @@ double DiagramEvaluator, double massRatioSquared = photonEmitterMass/exchangeFieldMass; massRatioSquared *= massRatioSquared; - double loopFactor = (photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ) + - exchangeFieldChargeCount * OneLoopFunctionB( massRatioSquared )); + double loopFactor = photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; @@ -569,7 +570,7 @@ double DiagramEvaluator, template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField ->::value(EvaluationContext &context) +>::value(const typename field_indices::type &indices, EvaluationContext &context) { double res = 0.0; @@ -579,10 +580,14 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(); - indexIt != FermionVertex::indexBounds().end(); - ++indexIt ) + constexpr auto indexBounds = FermionVertex::index_bounds; + for( auto indexIt = indexBounds.begin(); indexIt != indexBounds.end(); ++indexIt ) { + auto edmFieldIndices = FermionVertex::template fieldIndices<0>(*indexIt); + + if( edmFieldIndices != indices ) + continue; + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); auto vertex = FermionVertex::vertex(*indexIt, context); @@ -591,7 +596,6 @@ double DiagramEvaluator, auto exchangeFieldMass = context.mass( exchangeFieldIndices ); double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); @@ -600,8 +604,7 @@ double DiagramEvaluator, double massRatioSquared = exchangeFieldMass / photonEmitterMass; massRatioSquared *= massRatioSquared; - double loopFactor = (exchangeFieldChargeCount * OneLoopFunctionA( massRatioSquared ) + - photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared )); + double loopFactor = photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; From 195d7278c5eb4d01974c139de861c05b8744ad25 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 13 Dec 2016 14:46:25 +0100 Subject: [PATCH 060/158] Fixed typo --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index e66f5e2a1..3789bbf51 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1448,7 +1448,7 @@ corresponding tadpole is real or imaginary (only in models with CP Module[{fields, edmFields, diagrams, vertexFunctionData, definitions, calculationCode}, edmFields = {SARAH`Electron}; - EDM`SetEDMFields[edmParticles]; + EDM`SetEDMFields[edmFields]; fields = EDM`CreateFields[]; diagrams = EDM`CreateDiagrams[]; From b555e1e66f2a168fea9246df0c38c5215fb9fbab Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 13 Dec 2016 15:03:40 +0100 Subject: [PATCH 061/158] Removed confusing and unused code. --- meta/FlexibleSUSY.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 3789bbf51..0657293ed 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1447,9 +1447,6 @@ corresponding tadpole is real or imaginary (only in models with CP WriteEDMClass[vertexRules_List, files_List] := Module[{fields, edmFields, diagrams, vertexFunctionData, definitions, calculationCode}, - edmFields = {SARAH`Electron}; - EDM`SetEDMFields[edmFields]; - fields = EDM`CreateFields[]; diagrams = EDM`CreateDiagrams[]; From c8d96ba6c77c7f49462d1a3aee5e808f4dcc1f3d Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 20 Dec 2016 14:24:36 +0100 Subject: [PATCH 062/158] Changed the c++ EDM interface. --- meta/EDM.m | 90 ++++++++++++++++++++++++++++---------------- meta/FlexibleSUSY.m | 15 +++----- templates/edm.cpp.in | 12 +----- templates/edm.hpp.in | 8 +--- 4 files changed, 65 insertions(+), 60 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index e11971a20..ff304fac2 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -7,9 +7,9 @@ SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; CreateFields::usage="Returns the c++ code that contains all field fields"; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; +CreateInterfaceFunctions::usage="Returns the c++ code containing the interface functions {prototypeCode, definitionCode}." CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; CreateDefinitions::usage="Returns the c++ that contains all function definitions" -CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; @@ -102,35 +102,69 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +CreateInterfaceFunctions[] := +Module[{prototypes, definitions, evaluators}, + evaluators = ConcreteDiagramEvaluators[]; + + prototypes = ("namespace " <> FlexibleSUSY`FSModelName <> "_edm {\n" <> + StringJoin @ Riffle[("double calculate_edm_" <> CXXNameOfField[#] <> + "(" <> + If[TreeMasses`GetDimension[#] =!= 1, + " unsigned generationIndex, ", + " "] <> + "const " <> FlexibleSUSY`FSModelName <> "_mass_eigenstates& model );" + &) /@ edmFields, "\n"] <> + "\n}"); + + definitions = StringJoin @ Riffle[ + Module[{field = #[[1]], fieldEvaluators = #[[2]], + numberOfIndices}, + numberOfIndices = Length @ CleanFieldInfo[field][[5]]; + + "double " <> FlexibleSUSY`FSModelName <> "_edm::calculate_edm_" <> CXXNameOfField[field] <> + "(" <> + If[TreeMasses`GetDimension[field] =!= 1, + " unsigned generationIndex, ", + " "] <> + "const " <> FlexibleSUSY`FSModelName <> "_mass_eigenstates& model )\n" <> + "{\n" <> + IndentText @ + ("CMSSM_mass_eigenstates model_ = model;\n" <> + "EvaluationContext context{ model_ };\n" <> + "std::array + ToString @ numberOfIndices <> + "> indices = {" <> + If[TreeMasses`GetDimension[field] =!= 1, + " generationIndex" <> + If[numberOfIndices =!= 1, + StringJoin @ Table[", 1", {numberOfIndices-1}], + "" + ] <> " ", + If[numberOfIndices =!= 0, + StringJoin @ Riffle[Table[" 1", {numberOfIndices}], ","] <> " ", + "" + ] + ] <> + "};\n\n" <> + + "double val = 0.0;\n\n" <> + StringJoin @ Riffle[("val += " <> ToString @ # <> + "::value(indices, context);" + &) /@ fieldEvaluators, "\n"] <> + "\n\n" <> + "return val;" + ) <> + "\n}"] & /@ evaluators, "\n\n"]; + + Return[{prototypes, definitions}]; + ]; + CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; CreateDefinitions[vertexRules_List] := (CreateVertices[vertexRules][[2]] <> "\n\n" <> CreateEvaluationContextSpecializations[]); -CreateCalculation[] := -Module[{code, evaluators}, - evaluators = ConcreteDiagramEvaluators[]; - - code = "template double edm( const typename field_indices::type &indices, CMSSM_mass_eigenstates& model );\n\n"; - code = (code <> - StringJoin @ Riffle[Module[{field = #[[1]], - fieldEvaluators = #[[2]]}, - "template<> double edm<" <> CXXNameOfField[field] <> - ">( const std::array ToString @ Length @ CleanFieldInfo[field][[5]] <> - "> &indices, CMSSM_mass_eigenstates& model )\n" <> - "{\n" <> - IndentText["EvaluationContext context{ model };\n" <> - "double val = 0.0;\n\n" <> - StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(indices, context);" &) /@ fieldEvaluators, "\n"] <> - "\n\n" <> - "return val;" - ] <> - "\n}"] & /@ evaluators, "\n\n"]); - - Return[code]; - ]; - NPointFunctions[] := Module[{contributingDiagrams, vertices}, contributingDiagrams = ContributingDiagrams[]; @@ -200,9 +234,6 @@ If you add new kinds of vertices (e.g for new diagram types): photonEmitters = DeleteDuplicates @ Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], numberOfIndices}, - fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; - fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; - numberOfIndices = Length @ fieldInfo[[5]]; "template<> double EvaluationContext::mass<" <> ToString[#] <> @@ -230,9 +261,6 @@ If you add new kinds of vertices (e.g for new diagram types): StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], numberOfIndices}, - fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; - fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; - numberOfIndices = Length @ fieldInfo[[5]]; "template<>\n" <> @@ -300,8 +328,6 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - (* TODO: Add every permutation of the above vertices *) - {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 0657293ed..7505855b3 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1445,27 +1445,22 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the EDM c++ files *) WriteEDMClass[vertexRules_List, files_List] := -Module[{fields, edmFields, diagrams, vertexFunctionData, - definitions, calculationCode}, +Module[{fields, diagrams, interfaceFunctions, + vertexFunctionData, definitions}, fields = EDM`CreateFields[]; diagrams = EDM`CreateDiagrams[]; + interfaceFunctions = EDM`CreateInterfaceFunctions[]; vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; definitions = EDM`CreateDefinitions[vertexRules]; - calculationCode = EDM`CreateCalculation[]; - - declareElectronIndices = If[electronDimension === 1, - "constexpr std::array electronIndices{};", - "constexpr std::array electronIndices{1};" - ]; WriteOut`ReplaceInFiles[files, { "@EDM_Fields@" -> fields, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, - "@EDM_Calculation@" -> calculationCode, - "@EDM_DeclareElectronIndices@" -> declareElectronIndices, + "@EDM_InterfaceFunctionPrototypes@" -> interfaceFunctions[[1]], + "@EDM_InterfaceFunctionDefinitions@" -> interfaceFunctions[[2]], Sequence @@ GeneralReplacementRules[] } ]; ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 995940145..9254b5e9f 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -448,17 +448,7 @@ public: @EDM_VertexFunctionData@ } -@EDM_Calculation@ - -double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstates& model_) -{ - // make copy since model is modified via call to calculate_MFe_pole() - @ModelName@_mass_eigenstates model(model_); - - @EDM_DeclareElectronIndices@ - - return edm( electronIndices, model ); -} +@EDM_InterfaceFunctionDefinitions@ namespace { /** diff --git a/templates/edm.hpp.in b/templates/edm.hpp.in index 880373086..65712b80f 100644 --- a/templates/edm.hpp.in +++ b/templates/edm.hpp.in @@ -31,13 +31,7 @@ namespace flexiblesusy { class @ModelName@_mass_eigenstates; -namespace @ModelName@_edm { -/** -* @fn calculate_edm_electron -* @brief Calculates the electromagnetic dipole moment of the electron. -*/ -double calculate_edm_electron(const @ModelName@_mass_eigenstates& model); -} // namespace @ModelName@_edm +@EDM_InterfaceFunctionPrototypes@ } // namespace flexiblesusy #endif From a8ca854f7560cec63910fd797c4e315aa2a59374 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 2 Jan 2017 18:32:21 +0100 Subject: [PATCH 063/158] Changed edm units. --- meta/EDM.m | 19 ++----------------- templates/edm.cpp.in | 12 +++++------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index ff304fac2..eab0d91c4 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -243,28 +243,13 @@ If you add new kinds of vertices (e.g for new diagram types): If[TreeMasses`GetDimension[#] === 1, "()", "( indices[0] )"] <> "; }" ] &) /@ fields, "\n\n"] <> "\n\n" <> - "double EvaluationContext::electronCharge( void ) const\n" <> - "{\n" <> - IndentText @ - ("using PhotonVertex = VertexFunction - CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> - ">;\n" <> - If[electronDimension === 1, - "constexpr std::array indices{};\n", - "constexpr std::array indices{" <> - ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" - ] <> - "return PhotonVertex::vertex( indices, *this ).left().real();\n" - ) <> - "}\n\n" <> - StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], numberOfIndices}, numberOfIndices = Length @ fieldInfo[[5]]; "template<>\n" <> - "double EvaluationContext::chargeCount<" <> CXXNameOfField[#] <> + "double EvaluationContext::charge<" <> CXXNameOfField[#] <> ">( const std::array ToString @ numberOfIndices <> "> &indices ) const\n" <> "{\n" <> @@ -276,7 +261,7 @@ If you add new kinds of vertices (e.g for new diagram types): If[photonVertexType === SingleComponentedVertex, ".value().real();\n", ".left().real();\n"] <> - "return fieldCharge / electronCharge();\n" + "return fieldCharge;\n" ) <> "}"] &) /@ photonEmitters, "\n\n"] ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 9254b5e9f..ee62847ef 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -292,10 +292,8 @@ struct EvaluationContext { template double mass( const typename field_indices::type & ) const; - double electronCharge( void ) const; - template - double chargeCount( const typename field_indices::type & ) const; + double charge( const typename field_indices::type & ) const; }; /** @@ -537,7 +535,7 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double photonEmitterCharge = context.charge( photonEmitterIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -546,7 +544,7 @@ double DiagramEvaluator, double massRatioSquared = photonEmitterMass/exchangeFieldMass; massRatioSquared *= massRatioSquared; - double loopFactor = photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ); + double loopFactor = photonEmitterCharge * OneLoopFunctionA( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; @@ -585,7 +583,7 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double photonEmitterCharge = context.charge( photonEmitterIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); @@ -594,7 +592,7 @@ double DiagramEvaluator, double massRatioSquared = exchangeFieldMass / photonEmitterMass; massRatioSquared *= massRatioSquared; - double loopFactor = photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared ); + double loopFactor = photonEmitterCharge * OneLoopFunctionB( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; From 83d1d5c30e34505ace966f2cb9779a84e660893e Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 11 Jan 2017 21:49:16 +0100 Subject: [PATCH 064/158] Fixed clang++ c++11 compatibility issues. --- meta/EDM.m | 13 ++++++------- templates/edm.cpp.in | 9 ++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index eab0d91c4..2dfb27aa2 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -129,7 +129,7 @@ If you add new kinds of vertices (e.g for new diagram types): "const " <> FlexibleSUSY`FSModelName <> "_mass_eigenstates& model )\n" <> "{\n" <> IndentText @ - ("CMSSM_mass_eigenstates model_ = model;\n" <> + (FlexibleSUSY`FSModelName <> "_mass_eigenstates model_ = model;\n" <> "EvaluationContext context{ model_ };\n" <> "std::array ToString @ numberOfIndices <> @@ -257,11 +257,10 @@ If you add new kinds of vertices (e.g for new diagram types): ("using PhotonVertex = VertexFunction CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> ">;\n\n" <> - "double fieldCharge = PhotonVertex::vertex( concatenate( indices, indices ), *this )" <> + "return PhotonVertex::vertex( concatenate( indices, indices ), *this )" <> If[photonVertexType === SingleComponentedVertex, ".value().real();\n", - ".left().real();\n"] <> - "return fieldCharge;\n" + ".left().real();\n"] ) <> "}"] &) /@ photonEmitters, "\n\n"] ]; @@ -391,9 +390,9 @@ If you add new kinds of vertices (e.g for new diagram types): , ";/n" ] <> - "static constexpr std::array ToString @ Length[fieldIndexStart] <> - "> fieldIndexStart = { { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> - " } };\n" <> + "static constexpr unsigned fieldIndexStart[" <> ToString @ Length[fieldIndexStart] <> + "] = { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + " };\n" <> "using vertex_type = " <> VertexClassName[parsedVertex] <> ";\n" ) <> "};"); diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index ee62847ef..2c83a009b 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -407,13 +407,11 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; using bounds_type = typename std::decay::type; - using fieldIndexStart_type = decltype(Data::fieldIndexStart); public: using vertex_type = typename Data::vertex_type; using indices_type = typename decltype(Data::index_bounds)::indices_type; static constexpr bounds_type index_bounds = Data::index_bounds; - static constexpr fieldIndexStart_type fieldIndexStart = Data::fieldIndexStart; /** * @fn fieldIndices @@ -426,11 +424,12 @@ public: */ template static - std::array + std::array fieldIndices(const indices_type &indices) { - constexpr auto length = fieldIndexStart[fieldIndex+1] - fieldIndexStart[fieldIndex]; - auto begin = indices.begin() + fieldIndexStart[fieldIndex]; + constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; + constexpr auto offset = Data::fieldIndexStart[fieldIndex]; + auto begin = indices.begin() + offset; return make_array::iterate(begin); } From 2771c60898c9aa259f7fa943e8c5d263aaaeeff4 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sun, 22 Jan 2017 16:39:53 +0100 Subject: [PATCH 065/158] Fixed sign mistake in loop functions. --- templates/edm.cpp.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 2c83a009b..1a13bc8af 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -477,7 +477,7 @@ double OneLoopFunctionA(double r) 0.076923076923076923077 * d * d * d * d * d * d * d * d * d * d ); } - return 1.0 / (2.0 * d * d) * (3.0 - r + 2.0 * std::log(r) / d); + return 1.0 / (2.0 * d * d) * (3.0 - r - 2.0 * std::log(r) / d); } double OneLoopFunctionB(double r) @@ -500,7 +500,7 @@ double OneLoopFunctionB(double r) 0.0075757575757575757576 * d * d * d * d * d * d * d * d * d + 0.0064102564102564102564 * d * d * d * d * d * d * d * d * d * d ); - return 1.0 / (2.0 * d * d) * (1.0 + r + 2.0 * r * std::log(r) / d); + return 1.0 / (2.0 * d * d) * (1.0 + r - 2.0 * r * std::log(r) / d); } @EDM_Definitions@ From e3d8168a8295f34336ebab9d6f9e0816e1754a18 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 1 Nov 2016 20:43:15 +0100 Subject: [PATCH 066/158] Implemented CreateChargeGetters[] --- meta/EDM.m | 696 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 696 insertions(+) create mode 100644 meta/EDM.m diff --git a/meta/EDM.m b/meta/EDM.m new file mode 100644 index 000000000..8379254e8 --- /dev/null +++ b/meta/EDM.m @@ -0,0 +1,696 @@ +BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "LoopMasses`", "Vertices`"}]; + +Test::usage=""; + +SetEDMParticles::usage="Set the particles for which the EDMs shall be calculated."; + +CreateParticles::usage="Returns the c++ code that contains all particle classes"; +CreateEDMParticleFunctions::usage="Returns the c++ code that contains all EDM particle functions"; +CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; +CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; + +CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; + +CreateDefinitions::usage="Returns the c++ that contains all function definitions" + +NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; + +(******** IMPORTANT NOTES: + If you add new kinds of vertices (e.g for new diagram types): + - Add the new types to vertexTypes + - Expand CouplingsForParticles[] and VertexTypeForParticles[] accordingly + - Write the c++ class for the new vertex type + + When adding support for new diagram types, do the following: + - Add the new types to contributingFeynmanDiagramTypes + - Write new overloads for CreateDiagramEvaluatorClass[], ContributingDiagramsOfType[] and VerticesForDiagram[] + - Write the necessary c++ code: loop functions, DiagramEvaluator<> specialisations + **********) + +Test[] := Print["blablabla" <> ToString @ SARAH`InsFields[{{C[Fe, SARAH`FieldToInsert[1], VP]}}]]; + +Begin["`Private`"]; + +(************* Begin public interface *******************) + +edmParticles = Null; +SetEDMParticles[particles_List] := (edmParticles = particles); + +IsSMParticle[particle_] := + SARAH`SMQ[particle] || TreeMasses`IsSMGoldstone[particle]; + +CreateSMParticleFlags[particle_] := + Module[{result = "", i, + numberOfGenerations = TreeMasses`GetDimension[particle]}, + For[i = 1, i <= numberOfGenerations, i++, + If[i > 1, result = result <> ", ";]; + If[IsSMParticle[particle[i]] === True || + IsSMParticle[particle] === True, + result = result <> "true";, + result = result <> "false"; + ]; + ]; + "{ " <> result <> " }" + ]; + +(* Create c++ classes for all particles *) +CreateParticles[] := + Module[{particles, code}, + (* Get a list of all particles *) + particles = TreeMasses`GetParticles[]; + + code = ("// Particles (SARAH-style)\n" <> + "struct Particle {};\n\n" <> + + StringJoin @ Riffle[("struct " <> ParticleToCXXName[#] <> + ": public Particle {\n" <> + TextFormatting`IndentText[ + "static const unsigned numberOfGenerations = " <> + ToString @ TreeMasses`GetDimension[#] <> ";\n" <> + "static const bool is_sm_particle[numberOfGenerations];" + ] <> "\n};\n" <> + "const bool " <> ParticleToCXXName[#] <> "::is_sm_particle[" <> + ParticleToCXXName[#] <> "::numberOfGenerations] = " <> + CreateSMParticleFlags[#] <> ";\n" + &) /@ particles, "\n"] <> "\n\n" <> + "// Special particle families\n" <> + "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> + "typedef " <> ParticleToCXXName @ GetMuonFamily[] <> " MuonFamily;\n\n" <> + + "// AntiParticles\n" <> + "template struct anti : public Particle\n" <> + "{\n" <> + IndentText @ + ("static const unsigned numberOfGenerations = P::numberOfGenerations;\n" <> + "typedef anti

type;\n") <> + "};\n" <> + "template struct anti> { typedef P type; };\n\n" <> + + "// Particles that are their own antiparticles\n" <> + StringJoin @ Riffle[("template<> struct " <> + "anti<" <> ParticleToCXXName[#] <> ">" <> + " { typedef " <> ParticleToCXXName[#] <> " type; };" + &) /@ Select[particles, (# == AntiParticle[#] &)], + "\n"] + ); + + Return[code]; + ]; + +CreateChargeGetters[particles_List] := + StringJoin @ Riffle[ + Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, + photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; + "template<>\n" <> + "double charge<" <> ParticleToCXXName[#] <> + If[particleDim === 1, "(", + "( unsigned index, "] <> "EvaluationContext& context)\n{\n" <> + IndentText[ + "typedef VertexFunction<" <> + StringJoin @ Riffle[ParticleToCXXName /@ photonVertexParticles, ", "] <> + "> VF;\n" <> + If[particleDim === 1, + "const std::array indices{};\n", + "const std::array indices{ index, index };\n" + ] <> + "return VF::vertex(indices, context).left().real();" + ] <> "\n}" + ], + "\n\n"] + +CreateDiagrams[] := + Module[{diagramTypes, diagramTypeHeads, code}, + diagrams = contributingFeynmanDiagramTypes; + diagramHeads = DeleteDuplicates @ (Head /@ diagrams); + + code = "// The different diagram types that contribute to the muon magnetic moment\n"; + code = (code <> + StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) + /@ diagramHeads, "\n"] <> + "\n\n"); + + code = (code <> "// Indexed diagram types\n" <> + StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> + "<" <> ToString @ #[[1]] <> "> {};" &) + /@ diagrams, "\n"]); + + code = (code <> "\n\n" <> + StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingFeynmanDiagramTypes, "\n\n"]); + + Return[code]; + ]; + +CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; + +CreateDiagramEvaluatorClass[type_OneLoopDiagram] := + ("template\n" <> + "struct DiagramEvaluator + ToString @ type[[1]] <> + ">, PhotonEmitter, ExchangeParticle>\n" <> + "{ static double value(EvaluationContext& context); };"); + +calculationCode = Null; +CreateCalculation[] := + Module[{code}, + (* If we have been here before return the old result *) + If[calculationCode =!= Null, Return[calculationCode]]; + + code = "/********** GMuonMinus2.m generated calculation code **********/\n\n"; + + (* Generate code that simply adds up all contributions *) + code = (code <> + "EvaluationContext context{ model };\n" <> + "double val = 0.0;\n\n" <> + StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ ConcreteDiagramEvaluators[], + "\n"] <> "\n\n" <> + "return val;" + ); + + calculationCode = code; + Return[code]; + ]; + +CreateDefinitions[vertexRules_List] := + (CreateEvaluationContextSpecializations[] <> "\n\n" <> + CreateMuonFunctions[vertexRules][[2]] <> "\n\n" <> + CreateVertices[vertexRules][[2]]); + +nPointFunctions = Null; +NPointFunctions[] := + Module[{contributingDiagrams, vertices}, + If[nPointFunctions =!= Null, Return[nPointFunctions]]; + + contributingDiagrams = ContributingDiagrams[]; + + vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; + AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; + vertices = DeleteDuplicates[vertices]; + + vertices = (OrderParticles[#, Ordering[(Vertices`StripFieldIndices /@ #)]] &) /@ vertices; + vertices = DeleteDuplicates[vertices, + (Vertices`StripFieldIndices[#1] === Vertices`StripFieldIndices[#2] &)]; + + nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertices)]; + Return[nPointFunctions]; + ]; + + +(**************** End public interface *****************) + +(* Effectively generate all mass calculation functions *) +CreateEvaluationContextSpecializations[] := +Module[{particles, code}, + particles = TreeMasses`GetParticles[]; + particles = Select[particles, (! TreeMasses`IsGhost[#] &)]; + + code = (StringJoin @ + Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> + If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> + "{ return model.get_M" <> ParticleToCXXName[#] <> + If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" + &) /@ particles, "\n\n"]); + + Return[code]; + ]; + +(************************ Begin helper routines *******************************) + +(* Return the name of the SARAH particle family containing the muon *) +GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, + SARAH`Electron, + Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], + {p_, {Description -> "Muon", ___}} -> p, 1][[1]] + ]; +(* If the muon has a generation index, return it, otherwise return Null. + e.g. CMSSMNoFV has no muon generation index *) +GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; + +GetPhoton[] := SARAH`Photon; + +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; +SetAttributes[StripLorentzIndices, {Listable}]; + +(* Takes a SARAH particle and returns its antiparticle *) +AntiParticle[SARAH`bar[p_]] := p; +AntiParticle[Susyno`LieGroups`conj[p_]] := p; +AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, + If[IsScalar[pNoIndices] || IsVector[pNoIndices], + Susyno`LieGroups`conj[p], + SARAH`bar[p]]]; +SetAttributes[AntiParticle, {Listable}]; + +(* Return a string corresponding to the c++ class name of the particle. + Note that "bar" and "conj" get turned into anti<...>::type! *) +ParticleToCXXName[p_] := SymbolName[p]; +ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; + +(* Return a string corresponding to the name of the particle. + Note that "bar" and "conj" are left as they are! *) +ParticleToSARAHString[p_] := SymbolName[p]; +ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; +ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; + +(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) +ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], + Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; + +(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) +IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := + ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); + +(* Returns the rules that are needed to change order of a prticle list. + i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} + For some reason SARAH expects the indices to always be in that order... *) +IndexReplacementRulesForParticleReordering[particles_List, ordering_] := +Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, + Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; + +(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) +OrderParticles[particles_List, ordering_] := Module[{indexRules}, + indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; + Return[particles[[ordering]] /. indexRules]; + ]; + +(* Essentially the same as above, but using the obtained rules, + transform a whole vertex expression, as returned by SARAH`Vertex[] *) +OrderVertex[vertex_, ordering_] := + Module[{indexRules, particles, expr, newVertex}, + indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; + + particles = vertex[[1]][[ordering]]; + expr = vertex[[2;;]]; + + newVertex = (Join[{particles}, expr] /. indexRules); + Return[newVertex]; + ]; + +(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) +(* MemoizingVertex[] only works when __no__ indices are specified!!! *) +(* Use of memoization gives ~30% speedup for the MSSM! *) +memoizedVertices = {}; +MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := + Module[{memo, ordering, orderedParticles}, + (* First we sort the particles *) + ordering = Ordering[particles]; + orderedParticles = particles[[ordering]]; + + memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; + If[memo =!= {}, memo = memo[[1]], + (* Create a new entry *) + memo = SARAH`Vertex[orderedParticles, options]; + AppendTo[memoizedVertices, memo];]; + + (* Now return the particles to their original order *) + memo = OrderVertex[memo, Ordering[ordering]]; + Return[memo]]; + +MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; + +(* Test whether a SARAH Vertex[] result is nonzero (exact) *) +IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; + +(* Returns the name of the coupling function that FlexibleSUSY generates for + a specific vertex in a canonical order! *) +NameOfCouplingFunction[particles_List] := +((* FIXME: Not upwards compatible if naming conventions change *) + "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); + +(********************** End helper routines **************************) + +(* The different vertex types that are supported. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; + +(* The different diagram types that should be taken into consideration *) +(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) +(* There is no bounds check done on the integers, so they have to fit + into a standard c++ unsigned (!) int *) +contributingFeynmanDiagramTypes = { + OneLoopDiagram[3], (* Photon is emitted by a fermion, exchange particle is a scalar *) + OneLoopDiagram[4] (* Photon is emitted by a scalar, exchange particle is a fermion *) +}; + +(* IMPORTANT: If you want to add support for type 1 and 2 diagrams, hardly any + changes are necessary here. Just add the diagram types to contributingFeynmanDiagramTypes, + write corresponding helper lines as below and have ContributingDiagramsOfType[] + operate on type 1 and 2 diagrams as well. + You should not have to modify the actual code in ContributingDiagramsOfType[] + unless you are adding type 5 and 6 diagrams or completely other diagram types. *) + +(* This is just a convenient way to help ContributingDiagramsOfType[] *) +OneLoopDiagram[3][fermions_, scalars_, vectors_] := {fermions, scalars}; +OneLoopDiagram[4][fermions_, scalars_, vectors_] := {scalars, fermions}; + +(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +(* For now only LoopDiagrams 3 through 4 (see further above) are supported. + If you are adding more diagram types, you should probably make a new overload + of ContributingDiagramsOfType[] instead of extending this one. *) +(* IMPORTANT: Return value should be a list of Diagram[DIAGRAMTYPENAME[_Integer], Particles___] + This is important for the c++ conversion that assumes every argument after the type + is a particle and uses ParticleToCXXName for conversion *) + +ContributingDiagramsOfType[type : (OneLoopDiagram[3] | OneLoopDiagram[4]), fermions_, scalars_, vectors_] := + Module[{photonEmitters, exchangeParticles, photonVertices, muonVertices, test}, + (* Get the photon emitter and the exchange particle categories corresponding to the + diagram type *) + {photonEmitters, exchangeParticles} = type[fermions, scalars, vectors]; + + (* For every potential photon emitter, check whether it actually can emit a photon *) + photonVertices = (MemoizingVertex[{GetPhoton[], #, AntiParticle[#]}, + SARAH`UseDependences -> True, + SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &) /@ photonEmitters; + photonVertices = Select[photonVertices, IsNonZeroVertex]; + + (* From SARAH's more or less cryptically formatted result extract the particles' names *) + photonEmitters = (Vertices`StripFieldIndices /@ photonVertices)[[All, 1]][[All, 2]]; + + (* Since we do not know anything about the particles, we have to include their + corresponding antiparticles as well *) + photonEmitters = Union[photonEmitters, AntiParticle[photonEmitters]]; + exchangeParticles = Union[exchangeParticles, AntiParticle[exchangeParticles]]; + + (* Now we check which of the photon emitting particles actually can interact with + a muon in the way we want. *) + muonVertices = Outer[(MemoizingVertex[{GetMuonFamily[], #1, #2}, + SARAH`UseDependences -> True, + SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &), + photonEmitters, exchangeParticles]; + muonVertices = Select[#, IsNonZeroVertex] & /@ muonVertices; + muonVertices = Cases[muonVertices, Except[{}]]; + + (* We return the antiparticles of the particles we just found to *) + (* This is just a convention and nothing serious. The returned + particles are the decay products of the muon: + i.e. if muon ---> p1 + p2 + Then p1 and p2 are returned *) + test = (Diagram[type, AntiParticle[#[[1]]], AntiParticle[#[[2]]]] &) /@ + (Vertices`StripFieldIndices /@ # &) /@ Flatten[muonVertices[[All, All, 1, 2 ;;]], 1] + ]; + +(* Returns the necessary c++ code corresponding to the vertices that need to be calculated. + The returned value is a list {prototypes, definitions}. *) +createdVertices = Null; +CreateVertices[vertexRules_List] := + Module[{contributingDiagrams, vertices, + vertexClassesPrototypes, vertexClassesDefinitions}, + If[createdVertices =!= Null, Return[createdVertices]]; + contributingDiagrams = ContributingDiagrams[]; + + vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; + AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; + vertices = DeleteDuplicates[vertices]; + + {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); + vertexClassesPrototypes = Cases[vertexClassesPrototypes, Except[""]]; + vertexClassesDefinitions = Cases[vertexClassesDefinitions, Except[""]]; + + createdVertices = {vertexClassesPrototypes, vertexClassesDefinitions}; + createdVertices = (StringJoin @ Riffle[#, "\n\n"] &) /@ createdVertices; + + Return[createdVertices]; + ]; + +(* Returns the vertices that are present in the specified diagram. + This function should be overloaded for future diagram types. + IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) +VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, photonEmitter_, exchangeParticle_]] := + Module[{photonVertex, muonVertex}, + photonVertex = MemoizingVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; + muonVertex = MemoizingVertex[{GetMuonFamily[], AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; + + photonVertex = StripLorentzIndices @ photonVertex[[1]]; + muonVertex = StripLorentzIndices @ muonVertex[[1]]; + + Return[{photonVertex, muonVertex}]; + ]; + +(* Returns the vertex type for a vertex with a given list of particles *) +VertexTypeForParticles[particles_List] := + Module[{strippedParticles, scalars, vectors, fermions, scalarCount, vectorCount, fermionCount}, + strippedParticles = Vertices`StripFieldIndices /@ particles; + + scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiParticle[#]] &)]; + vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiParticle[#]] &)]; + fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiParticle[#]] &)]; + + scalarCount = Length[scalars]; + vectorCount = Length[vectors]; + fermionCount = Length[fermions]; + + If[fermionCount === 2 && scalarCount === 1 && vectorCount === 0, + Return[LeftAndRightComponentedVertex]]; + If[fermionCount === 2 && scalarCount === 0 && vectorCount === 1, + If[fermions[[1]] === AntiParticle[fermions[[2]]], + Return[LeftAndRightComponentedVertex]]]; + If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, + Return[SingleComponentedVertex]]; + + Return[Null]; + ]; + +(* Returns the different SARAH`Cp coupling parts for a vertex with a given list of particles *) +CouplingsForParticles[particles_List] := + Module[{vertexType, couplings}, + vertexType = VertexTypeForParticles[particles]; + couplings = {ReplacePart[particles, 0 -> SARAH`Cp]}; + + couplings = Switch[vertexType, + SingleComponentedVertex, couplings, + LeftAndRightComponentedVertex, {couplings[[1]][SARAH`PL], couplings[[1]][SARAH`PR]}]; + Return[couplings]; + ]; + +(* Creates the actual c++ code for a vertex with given particles. + This involves creating the VertexFunctionData<> code as well as + the VertexFunction<> code. You should never need to change this code! *) +vertexFunctions = {}; +CreateVertexFunction[indexedParticles_List, vertexRules_List] := + Module[{prototypes, definitions = "", ordering, particles, orderedParticles, + orderedIndexedParticles, addSpacing = True}, + particles = Vertices`StripFieldIndices /@ indexedParticles; + If[MemberQ[vertexFunctions, particles], Return[{"",""}]]; + + ordering = Ordering[particles]; + orderedParticles = particles[[ordering]]; + orderedIndexedParticles = OrderParticles[indexedParticles, ordering]; + + If[MemberQ[vertexFunctions, orderedParticles] === True, + (* There is already an entry *) + prototypes = ""; + addSpacing = False, + (* There is no entry yet, create it *) + {prototypes, definitions} = CreateOrderedVertexFunction[orderedIndexedParticles, vertexRules]; + AppendTo[vertexFunctions, orderedParticles]; + ]; + + If[ordering === Table[i, {i, 1, Length[ordering]}], + Return[{prototypes, definitions}]]; + + orderedVertexFunction = ("VertexFunction<" <> + StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> + ">"); + + prototypes = (prototypes <> If[addSpacing, "\n\n", ""] <> + "template<> struct VertexFunctionData<" <> + StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> + ">\n" <> + "{\n" <> + IndentText @ + ("static const bool is_permutation = true;\n" <> + "typedef " <> orderedVertexFunction <> " orig_type;\n" <> + "typedef boost::mpl::vector_c + StringJoin @ Riffle[ToString /@ (Ordering[ordering] - 1), ", "] <> + "> particlePermutation;\n" + ) <> + "};"); + + AppendTo[vertexFunctions, particles]; + Return[{prototypes, definitions}]; + ]; + +(* Creates local declarations of field indices, whose values are taken + from the elements of `arrayName'. + *) +DeclareIndices[indexedParticles_List, arrayName_String] := + Module[{p, total = 0, fieldIndexList, decl = ""}, + DeclareIndex[idx_, num_Integer, an_String] := ( + "const unsigned " <> CConversion`ToValidCSymbolString[idx] <> + " = " <> an <> "[" <> ToString[num] <> "];\n"); + For[p = 1, p <= Length[indexedParticles], p++, + fieldIndexList = FieldIndexList[indexedParticles[[p]]]; + decl = decl <> StringJoin[DeclareIndex[#, total++, arrayName]& /@ fieldIndexList]; + ]; + Assert[total == Total[Length[FieldIndexList[#]]& /@ indexedParticles]]; + decl + ]; + +(* ParsedVertex structure: + ParsedVertex[ + {numP1Indices, numP2Indices, ...}, + {{minIndex1, minIndex2, ...}, {maxIndex1+1, maxIndex2+1, ...}}, + VertexClassName, + VertexFunctionBody + ] + + Getters are available! Given below ParseVertex[] + *) + +(* The heart of the algorithm! From the particle content, determine all + necessary information. *) +ParseVertex[indexedParticles_List, vertexRules_List] := + Module[{particles, numberOfIndices, declareIndices, + parsedVertex, vertexClassName, vertexFunctionBody, + sarahParticles, particleInfo, indexBounds, expr, exprL, exprR}, + numberOfIndices = ((Length @ FieldIndexList[#] &) /@ indexedParticles); + particles = Vertices`StripFieldIndices /@ indexedParticles; + declareIndices = DeclareIndices[indexedParticles, "indices"]; + + vertexClassName = SymbolName[VertexTypeForParticles[particles]]; + vertexFunctionBody = Switch[vertexClassName, + "SingleComponentedVertex", + expr = (SARAH`Cp @@ indexedParticles) /. vertexRules; + expr = TreeMasses`ReplaceDependenciesReverse[expr]; + "std::complex result;\n\n" <> + declareIndices <> + Parameters`CreateLocalConstRefs[expr] <> "\n" <> + TreeMasses`ExpressionToString[expr, "result"] <> "\n" <> + "return vertex_type(result);", + + "LeftAndRightComponentedVertex", + exprL = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PL] /. vertexRules; + exprR = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PR] /. vertexRules; + exprL = TreeMasses`ReplaceDependenciesReverse[exprL]; + exprR = TreeMasses`ReplaceDependenciesReverse[exprR]; + "std::complex left, right;\n\n" <> + declareIndices <> + Parameters`CreateLocalConstRefs[exprL + exprR] <> "\n" <> + TreeMasses`ExpressionToString[exprL, "left"] <> "\n" <> + TreeMasses`ExpressionToString[exprR, "right"] <> "\n" <> + "return vertex_type(left, right);"]; + + sarahParticles = SARAH`getParticleName /@ particles; + particleInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ + sarahParticles, 1]; + + (* INFO: I do not think this ever occurs... *) + particleInfo = DeleteCases[particleInfo, {SARAH`generation, 1}, {3}]; + particleInfo = DeleteCases[particleInfo, {SARAH`lorentz, _}, {3}]; + + indexBounds = (With[{particleIndex = #}, + (If[#[[1]] === SARAH`generation, + {particleInfo[[particleIndex, 2]]-1, particleInfo[[particleIndex, 3]]}, + {1, #[[2]]}] + &) /@ particleInfo[[particleIndex, 5]]] + &) /@ Table[i, {i, Length[particles]}]; + indexBounds = Cases[Flatten[indexBounds, 1], Except[{}]]; + + If[indexBounds === {}, + indexBounds = {{},{}}, + indexBounds = Transpose @ indexBounds]; + + parsedVertex = ParsedVertex[numberOfIndices, + indexBounds, + vertexClassName, + vertexFunctionBody]; + + Return[parsedVertex]; + ]; + +(** Getters to the ParsedVertex structure **) +NumberOfIndices[parsedVertex_ParsedVertex] := Total[parsedVertex[[1]]]; +NumberOfIndices[parsedVertex_ParsedVertex, pIndex_Integer] := parsedVertex[[1, pIndex]]; + +IndexBounds[parsedVertex_ParsedVertex] := parsedVertex[[2]]; + +VertexClassName[parsedVertex_ParsedVertex] := parsedVertex[[3]]; +VertexFunctionBody[parsedVertex_ParsedVertex] := parsedVertex[[4]]; +(** End getters **) + +(* Create the c++ code for a canonically ordered vertex *) +CreateOrderedVertexFunction[orderedIndexedParticles_List, vertexRules_List] := + Module[{prototype, definition, orderedParticles, dataClassName, functionClassName, + parsedVertex, particleIndexStartF, particleIndexStart, indexBounds}, + orderedParticles = Vertices`StripFieldIndices /@ orderedIndexedParticles; + parsedVertex = ParseVertex[orderedIndexedParticles, vertexRules]; + dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; + functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; + + particleIndexStartF[1] = 0; + particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; + particleIndexStartF[Length[orderedParticles]+1] = NumberOfIndices[parsedVertex]; + + particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[orderedParticles] + 1}]; + + prototype = ("template<> struct " <> dataClassName <> "\n" <> + "{\n" <> + IndentText @ + ("static const bool is_permutation = false;\n" <> + "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> + "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> + "typedef boost::mpl::vector_c + StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> + "> particleIndexStart;\n" <> + "static const index_bounds indexB;\n" + ) <> + "};"); + + indexBounds = IndexBounds[parsedVertex]; + + If[NumberOfIndices[parsedVertex] =!= 0, + prototype = (prototype <> "\n" <> + "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" + );]; + definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> + functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> + "{\n" <> + IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> + "}"); + + Return[{prototype, definition}]; + ]; + +(* Find all contributing diagrams *) +cachedContributingDiagrams = Null; +ContributingDiagrams[] := + Module[{particles, fermions, scalars, vectors}, + If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; + + particles = TreeMasses`GetParticles[]; + fermions = Select[particles, TreeMasses`IsFermion]; + scalars = Select[particles, TreeMasses`IsScalar]; + vectors = Select[particles, TreeMasses`IsVector]; + + cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#, fermions, scalars, vectors] &) + /@ contributingFeynmanDiagramTypes + , 1]; + Return[cachedContributingDiagrams]; + ]; + +(* Returns a list of all concrete diagram evaluators (as strings) + e.g. "DiagramEvaluator, Fe, VP>" + that need to be invoked in our calculation *) +ConcreteDiagramEvaluators[] := + (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> + ToString @ #[[1,1]] <> ">, " <> + StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> + ">" &) + /@ ContributingDiagrams[]); + +End[]; + +EndPackage[]; From ac68037435c574fbc0dad630b43cd2b2f947df56 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 1 Nov 2016 21:00:11 +0100 Subject: [PATCH 067/158] Ported ConcreteDiagramEvaluators[] --- meta/EDM.m | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 8379254e8..1a2c834fc 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -143,10 +143,10 @@ If you add new kinds of vertices (e.g for new diagram types): CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; CreateDiagramEvaluatorClass[type_OneLoopDiagram] := - ("template\n" <> + ("template\n" <> "struct DiagramEvaluator ToString @ type[[1]] <> - ">, PhotonEmitter, ExchangeParticle>\n" <> + ">, EDMParticle, PhotonEmitter, ExchangeParticle>\n" <> "{ static double value(EvaluationContext& context); };"); calculationCode = Null; @@ -155,7 +155,7 @@ If you add new kinds of vertices (e.g for new diagram types): (* If we have been here before return the old result *) If[calculationCode =!= Null, Return[calculationCode]]; - code = "/********** GMuonMinus2.m generated calculation code **********/\n\n"; + code = "/********** EDM.m generated calculation code **********/\n\n"; (* Generate code that simply adds up all contributions *) code = (code <> @@ -681,15 +681,18 @@ If you add new kinds of vertices (e.g for new diagram types): Return[cachedContributingDiagrams]; ]; -(* Returns a list of all concrete diagram evaluators (as strings) - e.g. "DiagramEvaluator, Fe, VP>" +(* Returns a list of all concrete diagram evaluators + format: {{edmParticle1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, + {edmParticle2, {"...", ... }}, + ...} that need to be invoked in our calculation *) ConcreteDiagramEvaluators[] := - (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> - ToString @ #[[1,1]] <> ">, " <> - StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> - ">" &) - /@ ContributingDiagrams[]); + ({#[[1]], + (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> + ToString @ #[[1,1]] <> ">, " <> + StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> + ">" &) + /@ #[[2]]) &) /@ ContributingDiagrams[]); End[]; From 4ab4ffaf621a9811adfe6cebbc4d55880bb15699 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 18:25:58 +0100 Subject: [PATCH 068/158] Small fixes --- meta/EDM.m | 70 ++++++++++-------------------------------------------- 1 file changed, 13 insertions(+), 57 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 1a2c834fc..51fd028fe 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -22,14 +22,12 @@ If you add new kinds of vertices (e.g for new diagram types): - Write the c++ class for the new vertex type When adding support for new diagram types, do the following: - - Add the new types to contributingFeynmanDiagramTypes + - Add the new types to contributingDiagramTypes - Write new overloads for CreateDiagramEvaluatorClass[], ContributingDiagramsOfType[] and VerticesForDiagram[] - Write the necessary c++ code: loop functions, DiagramEvaluator<> specialisations **********) -Test[] := Print["blablabla" <> ToString @ SARAH`InsFields[{{C[Fe, SARAH`FieldToInsert[1], VP]}}]]; - -Begin["`Private`"]; +(* TODO: privatize interface again Begin["`Private`"]; *) (************* Begin public interface *******************) @@ -120,7 +118,7 @@ If you add new kinds of vertices (e.g for new diagram types): CreateDiagrams[] := Module[{diagramTypes, diagramTypeHeads, code}, - diagrams = contributingFeynmanDiagramTypes; + diagrams = contributingDiagramTypes; diagramHeads = DeleteDuplicates @ (Head /@ diagrams); code = "// The different diagram types that contribute to the muon magnetic moment\n"; @@ -135,7 +133,7 @@ If you add new kinds of vertices (e.g for new diagram types): /@ diagrams, "\n"]); code = (code <> "\n\n" <> - StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingFeynmanDiagramTypes, "\n\n"]); + StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingDiagramTypes, "\n\n"]); Return[code]; ]; @@ -338,67 +336,25 @@ If you add new kinds of vertices (e.g for new diagram types): (* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) -contributingFeynmanDiagramTypes = { +contributingDiagramTypes = { OneLoopDiagram[3], (* Photon is emitted by a fermion, exchange particle is a scalar *) OneLoopDiagram[4] (* Photon is emitted by a scalar, exchange particle is a fermion *) }; -(* IMPORTANT: If you want to add support for type 1 and 2 diagrams, hardly any - changes are necessary here. Just add the diagram types to contributingFeynmanDiagramTypes, - write corresponding helper lines as below and have ContributingDiagramsOfType[] - operate on type 1 and 2 diagrams as well. - You should not have to modify the actual code in ContributingDiagramsOfType[] - unless you are adding type 5 and 6 diagrams or completely other diagram types. *) - (* This is just a convenient way to help ContributingDiagramsOfType[] *) OneLoopDiagram[3][fermions_, scalars_, vectors_] := {fermions, scalars}; OneLoopDiagram[4][fermions_, scalars_, vectors_] := {scalars, fermions}; (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) -(* For now only LoopDiagrams 3 through 4 (see further above) are supported. - If you are adding more diagram types, you should probably make a new overload - of ContributingDiagramsOfType[] instead of extending this one. *) -(* IMPORTANT: Return value should be a list of Diagram[DIAGRAMTYPENAME[_Integer], Particles___] +(* IMPORTANT: Return value should have the format + {{edmParticle1, {Diagram[DIAGRAMTYPENAME[_Integer], Particles___], Diagram[...], ...}}, + {edmParticle2, {...}}, + ...} This is important for the c++ conversion that assumes every argument after the type is a particle and uses ParticleToCXXName for conversion *) ContributingDiagramsOfType[type : (OneLoopDiagram[3] | OneLoopDiagram[4]), fermions_, scalars_, vectors_] := - Module[{photonEmitters, exchangeParticles, photonVertices, muonVertices, test}, - (* Get the photon emitter and the exchange particle categories corresponding to the - diagram type *) - {photonEmitters, exchangeParticles} = type[fermions, scalars, vectors]; - - (* For every potential photon emitter, check whether it actually can emit a photon *) - photonVertices = (MemoizingVertex[{GetPhoton[], #, AntiParticle[#]}, - SARAH`UseDependences -> True, - SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &) /@ photonEmitters; - photonVertices = Select[photonVertices, IsNonZeroVertex]; - - (* From SARAH's more or less cryptically formatted result extract the particles' names *) - photonEmitters = (Vertices`StripFieldIndices /@ photonVertices)[[All, 1]][[All, 2]]; - - (* Since we do not know anything about the particles, we have to include their - corresponding antiparticles as well *) - photonEmitters = Union[photonEmitters, AntiParticle[photonEmitters]]; - exchangeParticles = Union[exchangeParticles, AntiParticle[exchangeParticles]]; - - (* Now we check which of the photon emitting particles actually can interact with - a muon in the way we want. *) - muonVertices = Outer[(MemoizingVertex[{GetMuonFamily[], #1, #2}, - SARAH`UseDependences -> True, - SARAH`Eigenstates -> FlexibleSUSY`FSEigenstates] &), - photonEmitters, exchangeParticles]; - muonVertices = Select[#, IsNonZeroVertex] & /@ muonVertices; - muonVertices = Cases[muonVertices, Except[{}]]; - - (* We return the antiparticles of the particles we just found to *) - (* This is just a convention and nothing serious. The returned - particles are the decay products of the muon: - i.e. if muon ---> p1 + p2 - Then p1 and p2 are returned *) - test = (Diagram[type, AntiParticle[#[[1]]], AntiParticle[#[[2]]]] &) /@ - (Vertices`StripFieldIndices /@ # &) /@ Flatten[muonVertices[[All, All, 1, 2 ;;]], 1] - ]; + Module[]; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. The returned value is a list {prototypes, definitions}. *) @@ -676,7 +632,7 @@ If you add new kinds of vertices (e.g for new diagram types): vectors = Select[particles, TreeMasses`IsVector]; cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#, fermions, scalars, vectors] &) - /@ contributingFeynmanDiagramTypes + /@ contributingDiagramTypes , 1]; Return[cachedContributingDiagrams]; ]; @@ -692,8 +648,8 @@ If you add new kinds of vertices (e.g for new diagram types): ToString @ #[[1,1]] <> ">, " <> StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> ">" &) - /@ #[[2]]) &) /@ ContributingDiagrams[]); + /@ #[[2]]) } &) /@ ContributingDiagrams[]; -End[]; +(* TODO: End[]; *) EndPackage[]; From a1a9bef38cf0478bebd5be4bd303015f97265e86 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 18:32:26 +0100 Subject: [PATCH 069/158] Fixed CreateChargeGetters[] --- meta/EDM.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 51fd028fe..055cf85bd 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -97,10 +97,10 @@ If you add new kinds of vertices (e.g for new diagram types): CreateChargeGetters[particles_List] := StringJoin @ Riffle[ - Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, + (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; "template<>\n" <> - "double charge<" <> ParticleToCXXName[#] <> + "double charge<" <> ParticleToCXXName[#] <> ">" <> If[particleDim === 1, "(", "( unsigned index, "] <> "EvaluationContext& context)\n{\n" <> IndentText[ @@ -113,7 +113,7 @@ If you add new kinds of vertices (e.g for new diagram types): ] <> "return VF::vertex(indices, context).left().real();" ] <> "\n}" - ], + ] &) /@ particles, "\n\n"] CreateDiagrams[] := From 0e351e6bf8df6f13b8aa98165e705a05813a0d3c Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 19:00:32 +0100 Subject: [PATCH 070/158] Fixed CreateChargeGetters[] for real --- meta/EDM.m | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 055cf85bd..66455e483 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -32,7 +32,7 @@ If you add new kinds of vertices (e.g for new diagram types): (************* Begin public interface *******************) edmParticles = Null; -SetEDMParticles[particles_List] := (edmParticles = particles); +SetEDMParticles[particles_List] := (edmParticles = particles;) IsSMParticle[particle_] := SARAH`SMQ[particle] || TreeMasses`IsSMGoldstone[particle]; @@ -95,14 +95,18 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateChargeGetters[particles_List] := +CreateChargeGetters[] := + "template\n" <> + "double charge( EvaluationContext & );\n\n" <> + "template\n" <> + "double charge( unsigned, EvaluationContext & );\n\n" <> StringJoin @ Riffle[ (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; "template<>\n" <> "double charge<" <> ParticleToCXXName[#] <> ">" <> - If[particleDim === 1, "(", - "( unsigned index, "] <> "EvaluationContext& context)\n{\n" <> + If[particleDim === 1, "( ", + "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> IndentText[ "typedef VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ photonVertexParticles, ", "] <> @@ -113,7 +117,7 @@ If you add new kinds of vertices (e.g for new diagram types): ] <> "return VF::vertex(indices, context).left().real();" ] <> "\n}" - ] &) /@ particles, + ] &) /@ edmParticles, "\n\n"] CreateDiagrams[] := @@ -170,7 +174,6 @@ If you add new kinds of vertices (e.g for new diagram types): CreateDefinitions[vertexRules_List] := (CreateEvaluationContextSpecializations[] <> "\n\n" <> - CreateMuonFunctions[vertexRules][[2]] <> "\n\n" <> CreateVertices[vertexRules][[2]]); nPointFunctions = Null; From 722086b319b746613873bb636181271bc5f22b62 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 19:32:44 +0100 Subject: [PATCH 071/158] Rewrote CreateCalculation[] to match ConcreteDiagramEvaluators[]'s new output format. --- meta/EDM.m | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 66455e483..158544799 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -142,8 +142,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; - CreateDiagramEvaluatorClass[type_OneLoopDiagram] := ("template\n" <> "struct DiagramEvaluator @@ -151,22 +149,30 @@ If you add new kinds of vertices (e.g for new diagram types): ">, EDMParticle, PhotonEmitter, ExchangeParticle>\n" <> "{ static double value(EvaluationContext& context); };"); +CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; + calculationCode = Null; CreateCalculation[] := - Module[{code}, + Module[{code, evaluators}, (* If we have been here before return the old result *) If[calculationCode =!= Null, Return[calculationCode]]; - - code = "/********** EDM.m generated calculation code **********/\n\n"; - - (* Generate code that simply adds up all contributions *) - code = (code <> - "EvaluationContext context{ model };\n" <> - "double val = 0.0;\n\n" <> - StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ ConcreteDiagramEvaluators[], - "\n"] <> "\n\n" <> - "return val;" - ); + + evaluators = ConcreteDiagramEvaluators[]; + + code = "/********** EDM.m generated calculation code **********/\n\n" <> + "template double edm( void );\n\n"; + + code = code <> StringJoin @ Riffle[ + Module[{pEvaluators = Cases[evaluators, {#, ev_List} -> ev]}, + "template<> double edm<" <> ParticleToCXXName[#] <> ">( void )\n" <> + "{\n" <> + IndentText["EvaluationContext context{ model };\n" <> + "double val = 0.0\n\n;" <> + StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ pEvaluators, + "\n"] <> "\n\n" <> + "return val;" + ] <> + "}"] & /@ evaluators, "\n\n"]; calculationCode = code; Return[code]; From 58454cf003c44c8a297b5629e2e54d168fb09d6c Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 20:33:42 +0100 Subject: [PATCH 072/158] Implemented ContributingDiagramsOfType[OneLoopDiagram[0]] --- meta/EDM.m | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 158544799..bd66b0795 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -346,24 +346,27 @@ If you add new kinds of vertices (e.g for new diagram types): (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) contributingDiagramTypes = { - OneLoopDiagram[3], (* Photon is emitted by a fermion, exchange particle is a scalar *) - OneLoopDiagram[4] (* Photon is emitted by a scalar, exchange particle is a fermion *) + OneLoopDiagram[0] }; -(* This is just a convenient way to help ContributingDiagramsOfType[] *) -OneLoopDiagram[3][fermions_, scalars_, vectors_] := {fermions, scalars}; -OneLoopDiagram[4][fermions_, scalars_, vectors_] := {scalars, fermions}; - (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) (* IMPORTANT: Return value should have the format {{edmParticle1, {Diagram[DIAGRAMTYPENAME[_Integer], Particles___], Diagram[...], ...}}, {edmParticle2, {...}}, - ...} - This is important for the c++ conversion that assumes every argument after the type - is a particle and uses ParticleToCXXName for conversion *) - -ContributingDiagramsOfType[type : (OneLoopDiagram[3] | OneLoopDiagram[4]), fermions_, scalars_, vectors_] := - Module[]; + ...} *) + +ContributingDiagramsOfType[OneLoopDiagram[0]] := + Module[{edmParticle = #, diagrams = SARAH`InsFields[ + {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], + SARAH`AntiField[SARAH`FieldToInsert[2]]], + C[SARAH`FieldToInsert[1], GetPhoton[], + SARAH`AntiField[SARAH`FieldToInsert[1]]], + C[SARAH`FieldToInsert[1], SARAH`FieldToInsert[2], + SARAH`AntiField[#]]}}]}, + {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[1,3,1]], + exchangeParticle = #[[1,3,2]]}, + Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] + &) /@ diagrams]}] & /@ edmParticles; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. The returned value is a list {prototypes, definitions}. *) From 65ea7f6cf14c0f953610c75084ace7af4c29d3eb Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 20:59:14 +0100 Subject: [PATCH 073/158] Implemented ContributingDiagrams[] --- meta/EDM.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index bd66b0795..32f8c1020 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -346,7 +346,8 @@ If you add new kinds of vertices (e.g for new diagram types): (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) contributingDiagramTypes = { - OneLoopDiagram[0] + OneLoopDiagram[0], + OneLoopDiagram[1] }; (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) @@ -355,7 +356,7 @@ If you add new kinds of vertices (e.g for new diagram types): {edmParticle2, {...}}, ...} *) -ContributingDiagramsOfType[OneLoopDiagram[0]] := +ContributingDiagramsOfType[type : (OneLoopDiagram[0] | OneLoopDiagram[1])] := Module[{edmParticle = #, diagrams = SARAH`InsFields[ {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], SARAH`AntiField[SARAH`FieldToInsert[2]]], @@ -365,7 +366,7 @@ If you add new kinds of vertices (e.g for new diagram types): SARAH`AntiField[#]]}}]}, {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[1,3,1]], exchangeParticle = #[[1,3,2]]}, - Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] + Diagram[type, edmParticle, photonEmitter, exchangeParticle]] &) /@ diagrams]}] & /@ edmParticles; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. @@ -635,17 +636,16 @@ If you add new kinds of vertices (e.g for new diagram types): (* Find all contributing diagrams *) cachedContributingDiagrams = Null; ContributingDiagrams[] := - Module[{particles, fermions, scalars, vectors}, + Module[{diagrams}, If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; - particles = TreeMasses`GetParticles[]; - fermions = Select[particles, TreeMasses`IsFermion]; - scalars = Select[particles, TreeMasses`IsScalar]; - vectors = Select[particles, TreeMasses`IsVector]; - - cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#, fermions, scalars, vectors] &) + cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#] &) /@ contributingDiagramTypes , 1]; + cachedContributingDiagrams = ({#, Union @ + ReplacePart[Cases[cachedContributingDiagrams, + {#, diagrams_List} -> diagrams], 0 -> Sequence]} &) /@ edmParticles; + Return[cachedContributingDiagrams]; ]; From 4349e69aa1f0fc685ea77761b15766ce5ded2ef1 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 21:08:51 +0100 Subject: [PATCH 074/158] Fixed bug in ContributingDiagramsOfType[] --- meta/EDM.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 32f8c1020..ac70ca348 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -346,8 +346,7 @@ If you add new kinds of vertices (e.g for new diagram types): (* There is no bounds check done on the integers, so they have to fit into a standard c++ unsigned (!) int *) contributingDiagramTypes = { - OneLoopDiagram[0], - OneLoopDiagram[1] + OneLoopDiagram[0] }; (* Find all diagrams of the type type_, testing all corresponding combinations of particles *) @@ -356,17 +355,18 @@ If you add new kinds of vertices (e.g for new diagram types): {edmParticle2, {...}}, ...} *) -ContributingDiagramsOfType[type : (OneLoopDiagram[0] | OneLoopDiagram[1])] := +ContributingDiagramsOfType[OneLoopDiagram[0]] := Module[{edmParticle = #, diagrams = SARAH`InsFields[ {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], SARAH`AntiField[SARAH`FieldToInsert[2]]], C[SARAH`FieldToInsert[1], GetPhoton[], SARAH`AntiField[SARAH`FieldToInsert[1]]], C[SARAH`FieldToInsert[1], SARAH`FieldToInsert[2], - SARAH`AntiField[#]]}}]}, - {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[1,3,1]], - exchangeParticle = #[[1,3,2]]}, - Diagram[type, edmParticle, photonEmitter, exchangeParticle]] + SARAH`AntiField[#]]}, + {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}]}, + {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[2,1]], + exchangeParticle = #[[2,2]]}, + Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] &) /@ diagrams]}] & /@ edmParticles; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. From d8f6770c725f1fee4ff383d3fd1a3c0362ade633 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 17:48:44 +0100 Subject: [PATCH 075/158] Rewrote VerticesForDiagram[], next up MemoizingVertex[] -> CachedVertices[] --- meta/EDM.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index ac70ca348..94b09031f 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -395,15 +395,17 @@ If you add new kinds of vertices (e.g for new diagram types): (* Returns the vertices that are present in the specified diagram. This function should be overloaded for future diagram types. IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) -VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, photonEmitter_, exchangeParticle_]] := - Module[{photonVertex, muonVertex}, - photonVertex = MemoizingVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; - muonVertex = MemoizingVertex[{GetMuonFamily[], AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; +VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := + Module[{edmVertex1, photonVertex, edmVertex2}, + edmVertex1 = CachedVertex[{edmParticle, AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; + photonVertex = CachedVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; + edmVertex2 = CachedVertex[{AntiParticle[edmParticle], photonEmitter, exchangeParticle}]; + edmVertex1 = StripLorentzIndices @ edmVertex1[[1]]; photonVertex = StripLorentzIndices @ photonVertex[[1]]; - muonVertex = StripLorentzIndices @ muonVertex[[1]]; + edmVertex2 = StripLorentzIndices @ edmVertex2[[1]]; - Return[{photonVertex, muonVertex}]; + Return[{edmVertex1, photonVertex, edmVertex2}]; ]; (* Returns the vertex type for a vertex with a given list of particles *) From e6f905a90d49b19112981d0babcfd614716e7ae3 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 18:07:24 +0100 Subject: [PATCH 076/158] Implemented CachedVertices[] --- meta/EDM.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/meta/EDM.m b/meta/EDM.m index 94b09031f..ca3f86f86 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -301,6 +301,14 @@ If you add new kinds of vertices (e.g for new diagram types): Return[newVertex]; ]; +CachedVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := + Module[{vertexPattern = ReplacePart[({#, ___} &) /@ + Permutations[(#[___] &) /@ particles], + 0 -> Alternatives], + vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, + FirstCase[vertexList, vertexPattern]; + ]; + (* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) (* MemoizingVertex[] only works when __no__ indices are specified!!! *) (* Use of memoization gives ~30% speedup for the MSSM! *) From fe3d1c9182b0e74a4f7c79b0334b449e78328255 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 18:08:54 +0100 Subject: [PATCH 077/158] Removed MemoizingVertex[] and friends. --- meta/EDM.m | 59 ------------------------------------------------------ 1 file changed, 59 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index ca3f86f86..1017243f3 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -267,40 +267,6 @@ If you add new kinds of vertices (e.g for new diagram types): ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; -(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) -ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], - Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; - -(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) -IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := - ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); - -(* Returns the rules that are needed to change order of a prticle list. - i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} - For some reason SARAH expects the indices to always be in that order... *) -IndexReplacementRulesForParticleReordering[particles_List, ordering_] := -Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, - Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; - -(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) -OrderParticles[particles_List, ordering_] := Module[{indexRules}, - indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; - Return[particles[[ordering]] /. indexRules]; - ]; - -(* Essentially the same as above, but using the obtained rules, - transform a whole vertex expression, as returned by SARAH`Vertex[] *) -OrderVertex[vertex_, ordering_] := - Module[{indexRules, particles, expr, newVertex}, - indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; - - particles = vertex[[1]][[ordering]]; - expr = vertex[[2;;]]; - - newVertex = (Join[{particles}, expr] /. indexRules); - Return[newVertex]; - ]; - CachedVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := Module[{vertexPattern = ReplacePart[({#, ___} &) /@ Permutations[(#[___] &) /@ particles], @@ -309,31 +275,6 @@ If you add new kinds of vertices (e.g for new diagram types): FirstCase[vertexList, vertexPattern]; ]; -(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) -(* MemoizingVertex[] only works when __no__ indices are specified!!! *) -(* Use of memoization gives ~30% speedup for the MSSM! *) -memoizedVertices = {}; -MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := - Module[{memo, ordering, orderedParticles}, - (* First we sort the particles *) - ordering = Ordering[particles]; - orderedParticles = particles[[ordering]]; - - memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; - If[memo =!= {}, memo = memo[[1]], - (* Create a new entry *) - memo = SARAH`Vertex[orderedParticles, options]; - AppendTo[memoizedVertices, memo];]; - - (* Now return the particles to their original order *) - memo = OrderVertex[memo, Ordering[ordering]]; - Return[memo]]; - -MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; - -(* Test whether a SARAH Vertex[] result is nonzero (exact) *) -IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; - (* Returns the name of the coupling function that FlexibleSUSY generates for a specific vertex in a canonical order! *) NameOfCouplingFunction[particles_List] := From 7f4cf453b706d98dacb7d6f79c083ebb883fef74 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 19:49:14 +0100 Subject: [PATCH 078/158] Fixed lots of problems in CachedVertex[]. --- meta/EDM.m | 66 +++++++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 1017243f3..0154d2425 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -75,7 +75,7 @@ If you add new kinds of vertices (e.g for new diagram types): "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> "typedef " <> ParticleToCXXName @ GetMuonFamily[] <> " MuonFamily;\n\n" <> - "// AntiParticles\n" <> + "// AntiFields\n" <> "template struct anti : public Particle\n" <> "{\n" <> IndentText @ @@ -84,11 +84,11 @@ If you add new kinds of vertices (e.g for new diagram types): "};\n" <> "template struct anti> { typedef P type; };\n\n" <> - "// Particles that are their own antiparticles\n" <> + "// Particles that are their own AntiFields\n" <> StringJoin @ Riffle[("template<> struct " <> "anti<" <> ParticleToCXXName[#] <> ">" <> " { typedef " <> ParticleToCXXName[#] <> " type; };" - &) /@ Select[particles, (# == AntiParticle[#] &)], + &) /@ Select[particles, (# == AntiField[#] &)], "\n"] ); @@ -102,7 +102,7 @@ If you add new kinds of vertices (e.g for new diagram types): "double charge( unsigned, EvaluationContext & );\n\n" <> StringJoin @ Riffle[ (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, - photonVertexParticles = {GetPhoton[], #, AntiParticle[#]}; + photonVertexParticles = {GetPhoton[], #, AntiField[#]}; "template<>\n" <> "double charge<" <> ParticleToCXXName[#] <> ">" <> If[particleDim === 1, "( ", @@ -201,7 +201,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[nPointFunctions]; ]; - (**************** End public interface *****************) (* Effectively generate all mass calculation functions *) @@ -222,16 +221,6 @@ If you add new kinds of vertices (e.g for new diagram types): (************************ Begin helper routines *******************************) -(* Return the name of the SARAH particle family containing the muon *) -GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, - SARAH`Electron, - Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], - {p_, {Description -> "Muon", ___}} -> p, 1][[1]] - ]; -(* If the muon has a generation index, return it, otherwise return Null. - e.g. CMSSMNoFV has no muon generation index *) -GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; - GetPhoton[] := SARAH`Photon; IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; @@ -246,15 +235,6 @@ If you add new kinds of vertices (e.g for new diagram types): ]; SetAttributes[StripLorentzIndices, {Listable}]; -(* Takes a SARAH particle and returns its antiparticle *) -AntiParticle[SARAH`bar[p_]] := p; -AntiParticle[Susyno`LieGroups`conj[p_]] := p; -AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, - If[IsScalar[pNoIndices] || IsVector[pNoIndices], - Susyno`LieGroups`conj[p], - SARAH`bar[p]]]; -SetAttributes[AntiParticle, {Listable}]; - (* Return a string corresponding to the c++ class name of the particle. Note that "bar" and "conj" get turned into anti<...>::type! *) ParticleToCXXName[p_] := SymbolName[p]; @@ -267,12 +247,18 @@ If you add new kinds of vertices (e.g for new diagram types): ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; -CachedVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := - Module[{vertexPattern = ReplacePart[({#, ___} &) /@ - Permutations[(#[___] &) /@ particles], +subIndexPattern = (ReplacePart[SARAH`subIndizes[[All, 1]], 0 -> Alternatives] -> ___); +AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; +AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; +AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; + +CachedVertex[particles_List] := + Module[{ + vertexPattern = ReplacePart[({#, ___} &) /@ + Permutations[AddIndexPattern /@ particles], 0 -> Alternatives], vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, - FirstCase[vertexList, vertexPattern]; + FirstCase[vertexList, vertexPattern] ]; (* Returns the name of the coupling function that FlexibleSUSY generates for @@ -327,11 +313,11 @@ If you add new kinds of vertices (e.g for new diagram types): If[createdVertices =!= Null, Return[createdVertices]]; contributingDiagrams = ContributingDiagrams[]; - vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; - AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; - vertices = DeleteDuplicates[vertices]; + vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ + Flatten @ contributingDiagrams[[All, 2]], 1]; - {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); + {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ + ((CreateVertexFunction[#, vertexRules] &) /@ vertices); vertexClassesPrototypes = Cases[vertexClassesPrototypes, Except[""]]; vertexClassesDefinitions = Cases[vertexClassesDefinitions, Except[""]]; @@ -346,10 +332,10 @@ If you add new kinds of vertices (e.g for new diagram types): IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := Module[{edmVertex1, photonVertex, edmVertex2}, - edmVertex1 = CachedVertex[{edmParticle, AntiParticle[photonEmitter], AntiParticle[exchangeParticle]}]; - photonVertex = CachedVertex[{GetPhoton[], photonEmitter, AntiParticle[photonEmitter]}]; - edmVertex2 = CachedVertex[{AntiParticle[edmParticle], photonEmitter, exchangeParticle}]; - + edmVertex1 = CachedVertex[{edmParticle, AntiField[photonEmitter], AntiField[exchangeParticle]}]; + photonVertex = CachedVertex[{photonEmitter, GetPhoton[], AntiField[photonEmitter]}]; + edmVertex2 = CachedVertex[{photonEmitter, exchangeParticle, AntiField[edmParticle]}]; + edmVertex1 = StripLorentzIndices @ edmVertex1[[1]]; photonVertex = StripLorentzIndices @ photonVertex[[1]]; edmVertex2 = StripLorentzIndices @ edmVertex2[[1]]; @@ -362,9 +348,9 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{strippedParticles, scalars, vectors, fermions, scalarCount, vectorCount, fermionCount}, strippedParticles = Vertices`StripFieldIndices /@ particles; - scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiParticle[#]] &)]; - vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiParticle[#]] &)]; - fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiParticle[#]] &)]; + scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiField[#]] &)]; + vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiField[#]] &)]; + fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiField[#]] &)]; scalarCount = Length[scalars]; vectorCount = Length[vectors]; @@ -373,7 +359,7 @@ If you add new kinds of vertices (e.g for new diagram types): If[fermionCount === 2 && scalarCount === 1 && vectorCount === 0, Return[LeftAndRightComponentedVertex]]; If[fermionCount === 2 && scalarCount === 0 && vectorCount === 1, - If[fermions[[1]] === AntiParticle[fermions[[2]]], + If[fermions[[1]] === AntiField[fermions[[2]]], Return[LeftAndRightComponentedVertex]]]; If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, Return[SingleComponentedVertex]]; From 26c7f0144267d12d432b8e0f77cf121203b0bf99 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:04:16 +0100 Subject: [PATCH 079/158] Rewrote CreateVertexFunction[] --- meta/EDM.m | 143 +++++++++++++++++++---------------------------------- 1 file changed, 50 insertions(+), 93 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 0154d2425..f2de5cca9 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -315,6 +315,8 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; + + (* TODO: Add every permutation of the above vertices *) {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); @@ -328,17 +330,12 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (* Returns the vertices that are present in the specified diagram. - This function should be overloaded for future diagram types. - IMPORTANT: Lorentz indices have to be stripped away (They are unnecessary anyway) *) + This function should be overloaded for future diagram types. *) VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := Module[{edmVertex1, photonVertex, edmVertex2}, edmVertex1 = CachedVertex[{edmParticle, AntiField[photonEmitter], AntiField[exchangeParticle]}]; photonVertex = CachedVertex[{photonEmitter, GetPhoton[], AntiField[photonEmitter]}]; edmVertex2 = CachedVertex[{photonEmitter, exchangeParticle, AntiField[edmParticle]}]; - - edmVertex1 = StripLorentzIndices @ edmVertex1[[1]]; - photonVertex = StripLorentzIndices @ photonVertex[[1]]; - edmVertex2 = StripLorentzIndices @ edmVertex2[[1]]; Return[{edmVertex1, photonVertex, edmVertex2}]; ]; @@ -380,51 +377,56 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (* Creates the actual c++ code for a vertex with given particles. + If the c++ for the particle list has already been created, two + empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) -vertexFunctions = {}; +createdVertexFunctions = {}; CreateVertexFunction[indexedParticles_List, vertexRules_List] := - Module[{prototypes, definitions = "", ordering, particles, orderedParticles, - orderedIndexedParticles, addSpacing = True}, - particles = Vertices`StripFieldIndices /@ indexedParticles; - If[MemberQ[vertexFunctions, particles], Return[{"",""}]]; - - ordering = Ordering[particles]; - orderedParticles = particles[[ordering]]; - orderedIndexedParticles = OrderParticles[indexedParticles, ordering]; - - If[MemberQ[vertexFunctions, orderedParticles] === True, - (* There is already an entry *) - prototypes = ""; - addSpacing = False, - (* There is no entry yet, create it *) - {prototypes, definitions} = CreateOrderedVertexFunction[orderedIndexedParticles, vertexRules]; - AppendTo[vertexFunctions, orderedParticles]; - ]; - - If[ordering === Table[i, {i, 1, Length[ordering]}], - Return[{prototypes, definitions}]]; - - orderedVertexFunction = ("VertexFunction<" <> - StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> - ">"); - - prototypes = (prototypes <> If[addSpacing, "\n\n", ""] <> - "template<> struct VertexFunctionData<" <> - StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> - ">\n" <> - "{\n" <> - IndentText @ - ("static const bool is_permutation = true;\n" <> - "typedef " <> orderedVertexFunction <> " orig_type;\n" <> - "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ (Ordering[ordering] - 1), ", "] <> - "> particlePermutation;\n" - ) <> - "};"); - - AppendTo[vertexFunctions, particles]; - Return[{prototypes, definitions}]; + Module[{prototype, definition, + particles = Vertices`StripFieldIndices /@ indexedParticles, + parsedVertex, dataClassName, functionClassName, particleIndexStartF, + particleIndexStart, indexBounds}, + If[MemberQ[createdVertexFunctions, particles], Return[{"",""}]]; + + parsedVertex = ParseVertex[indexedParticles, vertexRules]; + dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; + functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; + + particleIndexStartF[1] = 0; + particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; + particleIndexStartF[Length[particles]+1] = NumberOfIndices[parsedVertex]; + + particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[particles] + 1}]; + + prototype = ("template<> struct " <> dataClassName <> "\n" <> + "{\n" <> + IndentText @ + ("static const bool is_permutation = false;\n" <> + "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> + "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> + "typedef boost::mpl::vector_c + StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> + "> particleIndexStart;\n" <> + "static const index_bounds indexB;\n" + ) <> + "};"); + + indexBounds = IndexBounds[parsedVertex]; + + If[NumberOfIndices[parsedVertex] =!= 0, + prototype = (prototype <> "\n" <> + "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" + );]; + definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> + functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> + "{\n" <> + IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> + "}"); + + AppendTo[vertexFunctions, particles]; ]; (* Creates local declarations of field indices, whose values are taken @@ -525,51 +527,6 @@ If you add new kinds of vertices (e.g for new diagram types): VertexFunctionBody[parsedVertex_ParsedVertex] := parsedVertex[[4]]; (** End getters **) -(* Create the c++ code for a canonically ordered vertex *) -CreateOrderedVertexFunction[orderedIndexedParticles_List, vertexRules_List] := - Module[{prototype, definition, orderedParticles, dataClassName, functionClassName, - parsedVertex, particleIndexStartF, particleIndexStart, indexBounds}, - orderedParticles = Vertices`StripFieldIndices /@ orderedIndexedParticles; - parsedVertex = ParseVertex[orderedIndexedParticles, vertexRules]; - dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; - functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ orderedParticles, ", "] <> ">"; - - particleIndexStartF[1] = 0; - particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; - particleIndexStartF[Length[orderedParticles]+1] = NumberOfIndices[parsedVertex]; - - particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[orderedParticles] + 1}]; - - prototype = ("template<> struct " <> dataClassName <> "\n" <> - "{\n" <> - IndentText @ - ("static const bool is_permutation = false;\n" <> - "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> - "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> - "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> - "> particleIndexStart;\n" <> - "static const index_bounds indexB;\n" - ) <> - "};"); - - indexBounds = IndexBounds[parsedVertex]; - - If[NumberOfIndices[parsedVertex] =!= 0, - prototype = (prototype <> "\n" <> - "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" - );]; - definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> - functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> - "{\n" <> - IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> - "}"); - - Return[{prototype, definition}]; - ]; - (* Find all contributing diagrams *) cachedContributingDiagrams = Null; ContributingDiagrams[] := From 099298a4ac3028ff5af993bccda43be7ba0de69d Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:04:44 +0100 Subject: [PATCH 080/158] Fixed typo --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index f2de5cca9..e404e519c 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -426,7 +426,7 @@ If you add new kinds of vertices (e.g for new diagram types): IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); - AppendTo[vertexFunctions, particles]; + AppendTo[createdVertexFunctions, particles]; ]; (* Creates local declarations of field indices, whose values are taken From 079ac6f58ea424635a6a7a684b73292b205aabd4 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:13:02 +0100 Subject: [PATCH 081/158] First steps towards integrating the EDM module. --- meta/FlexibleSUSY.m | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index fd71aa57a..d50b9a0d2 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1443,6 +1443,35 @@ corresponding tadpole is real or imaginary (only in models with CP } ]; ]; +(* Write the EDM c++ files *) +WriteEDMClass[vertexRules_List, files_List] := +Module[{edmParticles, particles, chargeGetters, diagrams, vertexFunctionData, + definitions, calculationCode}, + edmParticles = {SARAH`Electron}; + + SetEDMParticles[edmParticles]; + + Print[EDM`CreateVertices[vertexRules]]; + (* + particles = EDM`CreateParticles[]; + chargeGetters = EDM`CreateChargeGetters[]; + diagrams = EDM`CreateDiagrams[]; + + vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; + definitions = EDM`CreateDefinitions[vertexRules]; + calculationCode = EDM`CreateCalculation[]; + + WriteOut`ReplaceInFiles[files, + { "@EDM_Particles@" -> particles, + "@EDM_ChargeGetters@" -> chargeGetters, + "@EDM_Diagrams@" -> diagrams, + "@EDM_VertexFunctionData@" -> vertexFunctionData, + "@EDM_Definitions@" -> definitions, + "@EDM_Calculation@" -> IndentText[calculationCode], + Sequence @@ GeneralReplacementRules[] + } ];*) + ]; + EnableForBVPSolver[solver_, statements_String] := Module[{result = "#ifdef "}, Switch[solver, @@ -1997,6 +2026,9 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; +(* Get all nPointFunctions that EDM needs *) +PrepareEDM[] := EDM`NPointFunctions[]; + PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2144,7 +2176,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, + gmm2Vertices = {}, edmVertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2191,6 +2223,8 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; + (* EDM vertices *) + edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; @@ -2700,10 +2734,17 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; +<<<<<<< 2f6a3062c3ce3b875f83065972915e93fa9ee0fd Put[vertexRules = Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; +======= + Put[vertexRules = + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], + vertexRuleFileName], + vertexRules = Get[vertexRuleFileName]; +>>>>>>> First steps towards integrating the EDM module. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; From 004f7dc5af1bab3735428c4dd5def4d6fd351bc5 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:14:11 +0100 Subject: [PATCH 082/158] First attempt at running EDM. --- meta/FlexibleSUSY.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index d50b9a0d2..3e4d565d4 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2945,7 +2945,11 @@ corresponding tadpole is real or imaginary (only in models with CP {{FileNameJoin[{$flexiblesusyTemplateDir, "a_muon.hpp.in"}], FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.hpp"}]}, {FileNameJoin[{$flexiblesusyTemplateDir, "a_muon.cpp.in"}], - FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; + + Print["Creating class EDM"]; + WriteGMuonMinus2Class[vertexRules, + {}]; PrintHeadline["Creating Mathematica interface"]; Print["Creating LibraryLink ", FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> ".mx"}], " ..."]; From 5f6f03e19fff3bcbd97cca2c1b63e02b43c6c7d4 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:18:37 +0100 Subject: [PATCH 083/158] rewrote NPointFunctions[]. --- meta/EDM.m | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index e404e519c..2233ed3c7 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -189,13 +189,8 @@ If you add new kinds of vertices (e.g for new diagram types): contributingDiagrams = ContributingDiagrams[]; - vertices = Flatten[VerticesForDiagram /@ contributingDiagrams, 1]; - AppendTo[vertices, StripLorentzIndices @ MemoizingVertex[{GetPhoton[], GetMuonFamily[], SARAH`bar[GetMuonFamily[]]}][[1]]]; - vertices = DeleteDuplicates[vertices]; - - vertices = (OrderParticles[#, Ordering[(Vertices`StripFieldIndices /@ #)]] &) /@ vertices; - vertices = DeleteDuplicates[vertices, - (Vertices`StripFieldIndices[#1] === Vertices`StripFieldIndices[#2] &)]; + vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ + Flatten @ contributingDiagrams[[All, 2]], 1]; nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertices)]; Return[nPointFunctions]; From 6a99c1ad214816552e2875d9445df00b62cff0ef Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:52:23 +0100 Subject: [PATCH 084/158] Fixed NPointFunctions[]. Added next TODO. --- meta/EDM.m | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 2233ed3c7..f2a43abbb 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -184,15 +184,16 @@ If you add new kinds of vertices (e.g for new diagram types): nPointFunctions = Null; NPointFunctions[] := - Module[{contributingDiagrams, vertices}, + Module[{contributingDiagrams, vertices, vertexParticles}, If[nPointFunctions =!= Null, Return[nPointFunctions]]; contributingDiagrams = ContributingDiagrams[]; vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - - nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertices)]; + vertexParticles = vertices[[All, 1]]; + + nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertexParticles)]; Return[nPointFunctions]; ]; @@ -355,7 +356,12 @@ If you add new kinds of vertices (e.g for new diagram types): Return[LeftAndRightComponentedVertex]]]; If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, Return[SingleComponentedVertex]]; - + + (* TODO: Add support for 1 scalar, two vector vertices *) + + Print[particles]; + Print[fermionCount, scalarCount, vectorCount]; + Return[Null]; ]; From c100d948b76b49ab00995cbbc10e884af94ff9da Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 7 Nov 2016 16:31:07 +0100 Subject: [PATCH 085/158] Some small fixes --- meta/EDM.m | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index f2a43abbb..48d01c176 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -5,7 +5,7 @@ SetEDMParticles::usage="Set the particles for which the EDMs shall be calculated."; CreateParticles::usage="Returns the c++ code that contains all particle classes"; -CreateEDMParticleFunctions::usage="Returns the c++ code that contains all EDM particle functions"; +CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM particles."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; @@ -73,7 +73,6 @@ If you add new kinds of vertices (e.g for new diagram types): &) /@ particles, "\n"] <> "\n\n" <> "// Special particle families\n" <> "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> - "typedef " <> ParticleToCXXName @ GetMuonFamily[] <> " MuonFamily;\n\n" <> "// AntiFields\n" <> "template struct anti : public Particle\n" <> @@ -122,8 +121,7 @@ If you add new kinds of vertices (e.g for new diagram types): CreateDiagrams[] := Module[{diagramTypes, diagramTypeHeads, code}, - diagrams = contributingDiagramTypes; - diagramHeads = DeleteDuplicates @ (Head /@ diagrams); + diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); code = "// The different diagram types that contribute to the muon magnetic moment\n"; code = (code <> @@ -134,7 +132,7 @@ If you add new kinds of vertices (e.g for new diagram types): code = (code <> "// Indexed diagram types\n" <> StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> "<" <> ToString @ #[[1]] <> "> {};" &) - /@ diagrams, "\n"]); + /@ contributingDiagramTypes, "\n"]); code = (code <> "\n\n" <> StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingDiagramTypes, "\n\n"]); @@ -243,16 +241,15 @@ If you add new kinds of vertices (e.g for new diagram types): ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; -subIndexPattern = (ReplacePart[SARAH`subIndizes[[All, 1]], 0 -> Alternatives] -> ___); +subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; CachedVertex[particles_List] := Module[{ - vertexPattern = ReplacePart[({#, ___} &) /@ + vertexPattern = Alternatives @@ ({#, ___} &) /@ Permutations[AddIndexPattern /@ particles], - 0 -> Alternatives], vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, FirstCase[vertexList, vertexPattern] ]; @@ -369,7 +366,7 @@ If you add new kinds of vertices (e.g for new diagram types): CouplingsForParticles[particles_List] := Module[{vertexType, couplings}, vertexType = VertexTypeForParticles[particles]; - couplings = {ReplacePart[particles, 0 -> SARAH`Cp]}; + couplings = {SARAH`Cp @@ particles}; couplings = Switch[vertexType, SingleComponentedVertex, couplings, @@ -538,8 +535,8 @@ If you add new kinds of vertices (e.g for new diagram types): /@ contributingDiagramTypes , 1]; cachedContributingDiagrams = ({#, Union @ - ReplacePart[Cases[cachedContributingDiagrams, - {#, diagrams_List} -> diagrams], 0 -> Sequence]} &) /@ edmParticles; + (Sequence @@ Cases[cachedContributingDiagrams, + {#, diagrams_List} -> diagrams])} &) /@ edmParticles; Return[cachedContributingDiagrams]; ]; @@ -553,7 +550,7 @@ If you add new kinds of vertices (e.g for new diagram types): ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> ToString @ #[[1,1]] <> ">, " <> - StringJoin @ (Riffle[ParticleToCXXName /@ ReplacePart[#[[2;;]], 0 -> List], ", "]) <> + StringJoin @ (Riffle[ParticleToCXXName /@ List @@ #[[2;;]], ", "]) <> ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; From 9b0f34eb1284a4963be9a497e4c98d9177bcd608 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 14 Nov 2016 22:13:09 +0100 Subject: [PATCH 086/158] Too much to describe... --- meta/EDM.m | 627 +++++++++++++++++++------------------------- meta/FlexibleSUSY.m | 29 +- 2 files changed, 297 insertions(+), 359 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 48d01c176..176671bbd 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -1,309 +1,249 @@ -BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "LoopMasses`", "Vertices`"}]; +BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "Vertices`"}]; -Test::usage=""; +(* This module generates c++ code that calculates electric dipole moments of fields *) -SetEDMParticles::usage="Set the particles for which the EDMs shall be calculated."; +SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; -CreateParticles::usage="Returns the c++ code that contains all particle classes"; -CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM particles."; +CreateFields::usage="Returns the c++ code that contains all field fields"; +CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM fields."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; - -CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; - CreateDefinitions::usage="Returns the c++ that contains all function definitions" +CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; -(******** IMPORTANT NOTES: +(******** TODO: IMPORTANT NOTES: If you add new kinds of vertices (e.g for new diagram types): - Add the new types to vertexTypes - - Expand CouplingsForParticles[] and VertexTypeForParticles[] accordingly + - Expand CouplingsForFields[] and VertexTypeForFields[] accordingly - Write the c++ class for the new vertex type - + When adding support for new diagram types, do the following: - - Add the new types to contributingDiagramTypes + - Add the new types to diagramTypes - Write new overloads for CreateDiagramEvaluatorClass[], ContributingDiagramsOfType[] and VerticesForDiagram[] - Write the necessary c++ code: loop functions, DiagramEvaluator<> specialisations **********) -(* TODO: privatize interface again Begin["`Private`"]; *) - (************* Begin public interface *******************) -edmParticles = Null; -SetEDMParticles[particles_List] := (edmParticles = particles;) - -IsSMParticle[particle_] := - SARAH`SMQ[particle] || TreeMasses`IsSMGoldstone[particle]; - -CreateSMParticleFlags[particle_] := - Module[{result = "", i, - numberOfGenerations = TreeMasses`GetDimension[particle]}, - For[i = 1, i <= numberOfGenerations, i++, - If[i > 1, result = result <> ", ";]; - If[IsSMParticle[particle[i]] === True || - IsSMParticle[particle] === True, - result = result <> "true";, - result = result <> "false"; - ]; - ]; - "{ " <> result <> " }" - ]; - -(* Create c++ classes for all particles *) -CreateParticles[] := - Module[{particles, code}, - (* Get a list of all particles *) - particles = TreeMasses`GetParticles[]; - - code = ("// Particles (SARAH-style)\n" <> - "struct Particle {};\n\n" <> - - StringJoin @ Riffle[("struct " <> ParticleToCXXName[#] <> - ": public Particle {\n" <> - TextFormatting`IndentText[ - "static const unsigned numberOfGenerations = " <> - ToString @ TreeMasses`GetDimension[#] <> ";\n" <> - "static const bool is_sm_particle[numberOfGenerations];" - ] <> "\n};\n" <> - "const bool " <> ParticleToCXXName[#] <> "::is_sm_particle[" <> - ParticleToCXXName[#] <> "::numberOfGenerations] = " <> - CreateSMParticleFlags[#] <> ";\n" - &) /@ particles, "\n"] <> "\n\n" <> - "// Special particle families\n" <> - "typedef " <> ParticleToCXXName @ GetPhoton[] <> " Photon;\n" <> - - "// AntiFields\n" <> - "template struct anti : public Particle\n" <> - "{\n" <> - IndentText @ - ("static const unsigned numberOfGenerations = P::numberOfGenerations;\n" <> - "typedef anti

type;\n") <> - "};\n" <> - "template struct anti> { typedef P type; };\n\n" <> - - "// Particles that are their own AntiFields\n" <> - StringJoin @ Riffle[("template<> struct " <> - "anti<" <> ParticleToCXXName[#] <> ">" <> - " { typedef " <> ParticleToCXXName[#] <> " type; };" - &) /@ Select[particles, (# == AntiField[#] &)], - "\n"] - ); - - Return[code]; - ]; +edmFields = Null; +SetEDMFields[fields_List] := (edmFields = fields;) + +CreateFields[] := +Module[{fields, code}, + fields = TreeMasses`GetParticles[]; + + code = ("struct Field {};\n\n" <> + + StringJoin @ Riffle[("struct " <> CXXNameOfField[#] <> + ": public Field {\n" <> + TextFormatting`IndentText["static const unsigned numberOfGenerations = " <> + ToString @ TreeMasses`GetDimension[#] <> ";\n"] <> + "};\n" &) /@ fields, "\n"] <> "\n\n" <> + "// Special field families\n" <> + "using Photon = " <> CXXNameOfField @ SARAH`Photon <> ";\n" <> + + "// Anti fields\n" <> + "template struct anti : public Field\n" <> + "{\n" <> + IndentText @ + ("static const unsigned numberOfGenerations = P::numberOfGenerations;\n" <> + "using type = anti

;\n") <> + "};\n" <> + "template struct anti> { using type = P; };\n\n" <> + + "// Fields that are their own anti fields\n" <> + StringJoin @ Riffle[("template<> struct " <> + "anti<" <> CXXNameOfField[#] <> ">" <> + " { using type = " <> CXXNameOfField[#] <> "; };" + &) /@ Select[fields, (# == SARAH`AntiField[#] &)], + "\n"] + ); + + Return[code]; + ]; CreateChargeGetters[] := - "template\n" <> - "double charge( EvaluationContext & );\n\n" <> - "template\n" <> - "double charge( unsigned, EvaluationContext & );\n\n" <> - StringJoin @ Riffle[ - (Module[{photonVertexParticles, particleDim = TreeMasses`GetDimension[#]}, - photonVertexParticles = {GetPhoton[], #, AntiField[#]}; - "template<>\n" <> - "double charge<" <> ParticleToCXXName[#] <> ">" <> - If[particleDim === 1, "( ", - "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> - IndentText[ - "typedef VertexFunction<" <> - StringJoin @ Riffle[ParticleToCXXName /@ photonVertexParticles, ", "] <> - "> VF;\n" <> - If[particleDim === 1, - "const std::array indices{};\n", - "const std::array indices{ index, index };\n" - ] <> - "return VF::vertex(indices, context).left().real();" - ] <> "\n}" - ] &) /@ edmParticles, - "\n\n"] +"template\n" <> +"double charge( EvaluationContext & );\n\n" <> +"template\n" <> +"double charge( unsigned, EvaluationContext & );\n\n" <> +StringJoin @ Riffle[(Module[{photonVertexFields, fieldDim = TreeMasses`GetDimension[#]}, + photonVertexFields = {SARAH`Photon, #, SARAH`AntiField[#]}; + "template<>\n" <> + "double charge<" <> CXXNameOfField[#] <> ">" <> + If[fieldDim === 1, "( ", + "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> + IndentText["using VF = VertexFunction<" <> + StringJoin @ Riffle[CXXNameOfField /@ photonVertexFields, ", "] <> + ">;\n" <> + If[fieldDim === 1, + "constexpr std::array indices{};\n", + "const std::array indices{ index, index };\n" + ] <> + "return VF::vertex(indices, context).left().real();" + ] <> "\n}" + ] &) /@ edmFields, + "\n\n"] CreateDiagrams[] := - Module[{diagramTypes, diagramTypeHeads, code}, - diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); - - code = "// The different diagram types that contribute to the muon magnetic moment\n"; - code = (code <> - StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) - /@ diagramHeads, "\n"] <> - "\n\n"); - - code = (code <> "// Indexed diagram types\n" <> - StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> - "<" <> ToString @ #[[1]] <> "> {};" &) - /@ contributingDiagramTypes, "\n"]); - - code = (code <> "\n\n" <> - StringJoin @ Riffle[CreateDiagramEvaluatorClass /@ contributingDiagramTypes, "\n\n"]); - - Return[code]; - ]; - -CreateDiagramEvaluatorClass[type_OneLoopDiagram] := - ("template\n" <> - "struct DiagramEvaluator - ToString @ type[[1]] <> - ">, EDMParticle, PhotonEmitter, ExchangeParticle>\n" <> - "{ static double value(EvaluationContext& context); };"); +Module[{diagramSubIndices, diagramTypeHeads, code}, + + code = StringJoin @ Riffle[(Module[{diagramType = #}, + "template class " <> SymbolName[diagramType] <> ";\n" <> + StringJoin @ Riffle[("template<> class " <> SymbolName[diagramType] <> + "<" <> ToString @ # <> "> {};" + &) /@ diagramSubTypes[diagramType], "\n"] + ] &) /@ diagramTypes, "\n\n"]; + + code = (code <> "\n\n" <> + StringJoin @ Riffle[(Module[{diagramType = #}, + StringJoin @ Riffle[ + ("template\n" <> + "struct DiagramEvaluator<" <> SymbolName[diagramType] <> + "<" <> ToString @ # <> + ">, EDMField, PhotonEmitter, ExchangeField>\n" <> + "{ static double value(EvaluationContext& context); };" + &) /@ diagramSubTypes[diagramType], "\n\n"]] &) /@ diagramTypes, "\n\n"] + ); + + Return[code]; + ]; CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; -calculationCode = Null; -CreateCalculation[] := - Module[{code, evaluators}, - (* If we have been here before return the old result *) - If[calculationCode =!= Null, Return[calculationCode]]; - - evaluators = ConcreteDiagramEvaluators[]; - - code = "/********** EDM.m generated calculation code **********/\n\n" <> - "template double edm( void );\n\n"; - - code = code <> StringJoin @ Riffle[ - Module[{pEvaluators = Cases[evaluators, {#, ev_List} -> ev]}, - "template<> double edm<" <> ParticleToCXXName[#] <> ">( void )\n" <> - "{\n" <> - IndentText["EvaluationContext context{ model };\n" <> - "double val = 0.0\n\n;" <> - StringJoin @ Riffle[("val += " <> # <> "::value(context);" &) /@ pEvaluators, - "\n"] <> "\n\n" <> - "return val;" - ] <> - "}"] & /@ evaluators, "\n\n"]; - - calculationCode = code; - Return[code]; - ]; - CreateDefinitions[vertexRules_List] := - (CreateEvaluationContextSpecializations[] <> "\n\n" <> - CreateVertices[vertexRules][[2]]); +(CreateEvaluationContextSpecializations[] <> "\n\n" <> + CreateVertices[vertexRules][[2]]); -nPointFunctions = Null; -NPointFunctions[] := - Module[{contributingDiagrams, vertices, vertexParticles}, - If[nPointFunctions =!= Null, Return[nPointFunctions]]; - - contributingDiagrams = ContributingDiagrams[]; +CreateCalculation[] := +Module[{code, evaluators}, + evaluators = ConcreteDiagramEvaluators[]; + + code = "template double edm( void );\n\n"; + code = (code <> + StringJoin @ Riffle[Module[{field = #[[1]], + fieldEvaluators = #[[2]]}, + "template<> double edm<" <> CXXNameOfField[field] <> ">( void )\n" <> + "{\n" <> + IndentText["EvaluationContext context{ model };\n" <> + "double val = 0.0;\n\n" <> + StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(context);" &) /@ fieldEvaluators, "\n"] <> "\n\n" <> + "return val;" + ] <> + "\n}"] & /@ evaluators, "\n\n"]); + + Return[code]; + ]; - vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ - Flatten @ contributingDiagrams[[All, 2]], 1]; - vertexParticles = vertices[[All, 1]]; - - nPointFunctions = Flatten[(Null[Null, #] &) /@ ((CouplingsForParticles[#] &) /@ vertexParticles)]; - Return[nPointFunctions]; - ]; +NPointFunctions[] := +Module[{contributingDiagrams, vertices}, + contributingDiagrams = ContributingDiagrams[]; + + vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ + Flatten @ contributingDiagrams[[All, 2]], 1]; + + Flatten[(Null[Null, #] &) /@ ((CouplingsForFields[#] &) /@ vertices)] + ]; (**************** End public interface *****************) +(* TODO: privatize interface again Begin["`Private`"]; *) -(* Effectively generate all mass calculation functions *) -CreateEvaluationContextSpecializations[] := -Module[{particles, code}, - particles = TreeMasses`GetParticles[]; - particles = Select[particles, (! TreeMasses`IsGhost[#] &)]; - - code = (StringJoin @ - Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> - If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> - "{ return model.get_M" <> ParticleToCXXName[#] <> - If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" - &) /@ particles, "\n\n"]); - - Return[code]; - ]; - -(************************ Begin helper routines *******************************) +(* The supported vertex types. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; -GetPhoton[] := SARAH`Photon; +(* The supported diagram types. + They have the same names as their c++ counterparts. *) +diagramTypes = { + OneLoopDiagram +}; -IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; +(* The supported diagram types. + Indexed by the diagram type, gives a set of (c++-compatible) unsigned integer indices. *) +diagramSubTypes[OneLoopDiagram] = { 0, 1 }; (* 0: fermion emits photon, exchange field is a scalar + 1: scalar emits photon, exchange field is a fermion *) -StripLorentzIndices[p_Symbol] := p; -StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; -StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; -StripLorentzIndices[p_] := Module[{remainingIndices}, - remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; - If[Length[remainingIndices] === 0, Head[p], - Head[p][remainingIndices]] - ]; -SetAttributes[StripLorentzIndices, {Listable}]; +(**************** CXX conversion routines ***************) -(* Return a string corresponding to the c++ class name of the particle. +(* Return a string corresponding to the c++ class name of the field. Note that "bar" and "conj" get turned into anti<...>::type! *) -ParticleToCXXName[p_] := SymbolName[p]; -ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +CXXNameOfField[p_] := SymbolName[p]; +CXXNameOfField[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +CXXNameOfField[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -(* Return a string corresponding to the name of the particle. - Note that "bar" and "conj" are left as they are! *) -ParticleToSARAHString[p_] := SymbolName[p]; -ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; -ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; +(**************** Other Functions ***************) subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; -AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; - -CachedVertex[particles_List] := - Module[{ - vertexPattern = Alternatives @@ ({#, ___} &) /@ - Permutations[AddIndexPattern /@ particles], - vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, - FirstCase[vertexList, vertexPattern] - ]; - -(* Returns the name of the coupling function that FlexibleSUSY generates for - a specific vertex in a canonical order! *) -NameOfCouplingFunction[particles_List] := -((* FIXME: Not upwards compatible if naming conventions change *) - "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); +AddIndexPattern[field_] := SARAH`getFull[SARAH`getBlank[field]] /. subIndexPattern; + +CachedVertex[fields_List] := +Module[{ + vertexPattern = Alternatives @@ ({#, ___} &) /@ + Permutations[AddIndexPattern /@ fields], + vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[fields]]}, + FirstCase[vertexList, vertexPattern] + ]; -(********************** End helper routines **************************) +CreateEvaluationContextSpecializations[] := +Module[{fields, code}, + fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; -(* The different vertex types that are supported. - They have the same names as their c++ counterparts. *) -vertexTypes = { - SingleComponentedVertex, - LeftAndRightComponentedVertex -}; + code = (StringJoin @ + Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> + If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> + "{ return model.get_M" <> CXXNameOfField[#] <> + If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" + &) /@ fields, "\n\n"]); -(* The different diagram types that should be taken into consideration *) -(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) -(* There is no bounds check done on the integers, so they have to fit - into a standard c++ unsigned (!) int *) -contributingDiagramTypes = { - OneLoopDiagram[0] -}; + Return[code]; + ]; -(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +(* Find all diagrams of the type type_, testing all corresponding combinations of fields *) (* IMPORTANT: Return value should have the format - {{edmParticle1, {Diagram[DIAGRAMTYPENAME[_Integer], Particles___], Diagram[...], ...}}, - {edmParticle2, {...}}, + {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, + {edmField2, {...}}, ...} *) - -ContributingDiagramsOfType[OneLoopDiagram[0]] := - Module[{edmParticle = #, diagrams = SARAH`InsFields[ +ContributingDiagramsOfType[OneLoopDiagram] := + Module[{edmField = #, diagrams = SARAH`InsFields[ {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], SARAH`AntiField[SARAH`FieldToInsert[2]]], - C[SARAH`FieldToInsert[1], GetPhoton[], + C[SARAH`FieldToInsert[1], SARAH`Photon, SARAH`AntiField[SARAH`FieldToInsert[1]]], C[SARAH`FieldToInsert[1], SARAH`FieldToInsert[2], SARAH`AntiField[#]]}, - {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}]}, - {edmParticle, DeleteDuplicates[(Module[{photonEmitter = #[[2,1]], - exchangeParticle = #[[2,2]]}, - Diagram[OneLoopDiagram[0], edmParticle, photonEmitter, exchangeParticle]] - &) /@ diagrams]}] & /@ edmParticles; + {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}], + subtypedDiagrams, uniqueDiagrams}, + + subtypedDiagrams = (Module[{photonEmitter = #[[2,1]], + exchangeField = #[[2,2]], + subType}, + subType = If[TreeMasses`IsFermion[photonEmitter] && + TreeMasses`IsScalar[exchangeField], + 0, + If[TreeMasses`IsScalar[photonEmitter] && + TreeMasses`IsFermion[exchangeField], + 1]]; + If[subType === Null, + Null, + Diagram[OneLoopDiagram[subType], edmField, photonEmitter, exchangeField]] + ] + &) /@ diagrams; + uniqueDiagrams = DeleteDuplicates @ Cases[subtypedDiagrams, Except[Null]]; + + {edmField, uniqueDiagrams}] & /@ edmFields; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. The returned value is a list {prototypes, definitions}. *) -createdVertices = Null; CreateVertices[vertexRules_List] := Module[{contributingDiagrams, vertices, vertexClassesPrototypes, vertexClassesDefinitions}, - If[createdVertices =!= Null, Return[createdVertices]]; contributingDiagrams = ContributingDiagrams[]; vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ @@ -313,99 +253,81 @@ If you add new kinds of vertices (e.g for new diagram types): {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); - vertexClassesPrototypes = Cases[vertexClassesPrototypes, Except[""]]; - vertexClassesDefinitions = Cases[vertexClassesDefinitions, Except[""]]; - - createdVertices = {vertexClassesPrototypes, vertexClassesDefinitions}; - createdVertices = (StringJoin @ Riffle[#, "\n\n"] &) /@ createdVertices; - Return[createdVertices]; + (StringJoin @ Riffle[#, "\n\n"] &) /@ {vertexClassesPrototypes, vertexClassesDefinitions} ]; (* Returns the vertices that are present in the specified diagram. This function should be overloaded for future diagram types. *) -VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmParticle_, photonEmitter_, exchangeParticle_]] := - Module[{edmVertex1, photonVertex, edmVertex2}, - edmVertex1 = CachedVertex[{edmParticle, AntiField[photonEmitter], AntiField[exchangeParticle]}]; - photonVertex = CachedVertex[{photonEmitter, GetPhoton[], AntiField[photonEmitter]}]; - edmVertex2 = CachedVertex[{photonEmitter, exchangeParticle, AntiField[edmParticle]}]; - - Return[{edmVertex1, photonVertex, edmVertex2}]; +VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmField_, photonEmitter_, exchangeField_]] := + Module[{edmVertex}, + edmVertex = {edmField, SARAH`AntiField[photonEmitter], SARAH`AntiField[exchangeField]}; + Return[{edmVertex}]; ]; -(* Returns the vertex type for a vertex with a given list of particles *) -VertexTypeForParticles[particles_List] := - Module[{strippedParticles, scalars, vectors, fermions, scalarCount, vectorCount, fermionCount}, - strippedParticles = Vertices`StripFieldIndices /@ particles; - - scalars = Select[strippedParticles, (TreeMasses`IsScalar[#] || TreeMasses`IsScalar[AntiField[#]] &)]; - vectors = Select[strippedParticles, (TreeMasses`IsVector[#] || TreeMasses`IsVector[AntiField[#]] &)]; - fermions = Select[strippedParticles, (TreeMasses`IsFermion[#] || TreeMasses`IsFermion[AntiField[#]] &)]; - - scalarCount = Length[scalars]; - vectorCount = Length[vectors]; - fermionCount = Length[fermions]; - +(* Returns the vertex type for a vertex with a given list of fields *) +VertexTypeForFields[fields_List] := + Module[{fermions, scalarCount, vectorCount, fermionCount}, + fermions = Select[fields, TreeMasses`IsFermion]; + + scalarCount = Length @ Select[fields, TreeMasses`IsScalar]; + vectorCount = Length @ Select[fields, TreeMasses`IsVector]; + fermionCount = Length @ fermions; + If[fermionCount === 2 && scalarCount === 1 && vectorCount === 0, Return[LeftAndRightComponentedVertex]]; If[fermionCount === 2 && scalarCount === 0 && vectorCount === 1, - If[fermions[[1]] === AntiField[fermions[[2]]], + If[fermions[[1]] === SARAH`AntiField[fermions[[2]]], Return[LeftAndRightComponentedVertex]]]; If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, Return[SingleComponentedVertex]]; - (* TODO: Add support for 1 scalar, two vector vertices *) - - Print[particles]; - Print[fermionCount, scalarCount, vectorCount]; - Return[Null]; ]; -(* Returns the different SARAH`Cp coupling parts for a vertex with a given list of particles *) -CouplingsForParticles[particles_List] := +(* Returns the different SARAH`Cp coupling parts for a vertex with a given list of fields *) +CouplingsForFields[fields_List] := Module[{vertexType, couplings}, - vertexType = VertexTypeForParticles[particles]; - couplings = {SARAH`Cp @@ particles}; + vertexType = VertexTypeForFields[fields]; + + couplings = {SARAH`Cp @@ fields}; - couplings = Switch[vertexType, - SingleComponentedVertex, couplings, - LeftAndRightComponentedVertex, {couplings[[1]][SARAH`PL], couplings[[1]][SARAH`PR]}]; - Return[couplings]; + Switch[vertexType, + SingleComponentedVertex, couplings, + LeftAndRightComponentedVertex, {couplings[[1]][SARAH`PL], couplings[[1]][SARAH`PR]}] ]; -(* Creates the actual c++ code for a vertex with given particles. - If the c++ for the particle list has already been created, two +(* Creates the actual c++ code for a vertex with given fields. + If the c++ for the field list has already been created, two empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) createdVertexFunctions = {}; -CreateVertexFunction[indexedParticles_List, vertexRules_List] := +CreateVertexFunction[fields_List, vertexRules_List] := Module[{prototype, definition, - particles = Vertices`StripFieldIndices /@ indexedParticles, - parsedVertex, dataClassName, functionClassName, particleIndexStartF, - particleIndexStart, indexBounds}, - If[MemberQ[createdVertexFunctions, particles], Return[{"",""}]]; - - parsedVertex = ParseVertex[indexedParticles, vertexRules]; - dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; - functionClassName = "VertexFunction<" <> StringJoin @ Riffle[ParticleToCXXName /@ particles, ", "] <> ">"; + parsedVertex, dataClassName, functionClassName, fieldIndexStartF, + fieldIndexStart, indexBounds}, + If[MemberQ[createdVertexFunctions, fields], Return[{"",""}]]; + + parsedVertex = ParseVertex[fields, vertexRules]; - particleIndexStartF[1] = 0; - particleIndexStartF[pIndex_] := particleIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; - particleIndexStartF[Length[particles]+1] = NumberOfIndices[parsedVertex]; + dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[CXXNameOfField /@ fields, ", "] <> ">"; + functionClassName = "VertexFunction<" <> StringJoin @ Riffle[CXXNameOfField /@ fields, ", "] <> ">"; - particleIndexStart = Table[particleIndexStartF[i], {i, 1, Length[particles] + 1}]; + fieldIndexStartF[1] = 0; + fieldIndexStartF[pIndex_] := fieldIndexStartF[pIndex-1] + NumberOfIndices[parsedVertex, pIndex-1]; + fieldIndexStartF[Length[fields]+1] = NumberOfIndices[parsedVertex]; + + fieldIndexStart = Table[fieldIndexStartF[i], {i, 1, Length[fields] + 1}]; prototype = ("template<> struct " <> dataClassName <> "\n" <> "{\n" <> IndentText @ - ("static const bool is_permutation = false;\n" <> - "typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> + ("typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ particleIndexStart, ", "] <> - "> particleIndexStart;\n" <> + StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + "> fieldIndexStart;\n" <> "static const index_bounds indexB;\n" ) <> "};"); @@ -424,22 +346,23 @@ If you add new kinds of vertices (e.g for new diagram types): IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); - AppendTo[createdVertexFunctions, particles]; + AppendTo[createdVertexFunctions, fields]; + Return[{prototype, definition}]; ]; (* Creates local declarations of field indices, whose values are taken from the elements of `arrayName'. *) -DeclareIndices[indexedParticles_List, arrayName_String] := +DeclareIndices[indexedFields_List, arrayName_String] := Module[{p, total = 0, fieldIndexList, decl = ""}, DeclareIndex[idx_, num_Integer, an_String] := ( "const unsigned " <> CConversion`ToValidCSymbolString[idx] <> " = " <> an <> "[" <> ToString[num] <> "];\n"); - For[p = 1, p <= Length[indexedParticles], p++, - fieldIndexList = FieldIndexList[indexedParticles[[p]]]; + For[p = 1, p <= Length[indexedFields], p++, + fieldIndexList = Vertices`FieldIndexList[indexedFields[[p]]]; decl = decl <> StringJoin[DeclareIndex[#, total++, arrayName]& /@ fieldIndexList]; ]; - Assert[total == Total[Length[FieldIndexList[#]]& /@ indexedParticles]]; + Assert[total == Total[Length[Vertices`FieldIndexList[#]]& /@ indexedFields]]; decl ]; @@ -454,20 +377,25 @@ If you add new kinds of vertices (e.g for new diagram types): Getters are available! Given below ParseVertex[] *) -(* The heart of the algorithm! From the particle content, determine all +(* The heart of the algorithm! From the field content, determine all necessary information. *) -ParseVertex[indexedParticles_List, vertexRules_List] := - Module[{particles, numberOfIndices, declareIndices, +ParseVertex[fields_List, vertexRules_List] := + Module[{indexedFields, numberOfIndices, declareIndices, parsedVertex, vertexClassName, vertexFunctionBody, - sarahParticles, particleInfo, indexBounds, expr, exprL, exprR}, - numberOfIndices = ((Length @ FieldIndexList[#] &) /@ indexedParticles); - particles = Vertices`StripFieldIndices /@ indexedParticles; - declareIndices = DeclareIndices[indexedParticles, "indices"]; - - vertexClassName = SymbolName[VertexTypeForParticles[particles]]; + sarahFields, fieldInfo, trIndexBounds, indexBounds, + expr, exprL, exprR}, + indexedFields = MapIndexed[(Module[{field = #1, + index = #2[[1]]}, + SARAH`getFull[#1] /.subGC[index] /. subIndFinal[index,index] + ] &), fields]; + + numberOfIndices = ((Length @ Vertices`FieldIndexList[#] &) /@ indexedFields); + declareIndices = DeclareIndices[indexedFields, "indices"]; + + vertexClassName = SymbolName[VertexTypeForFields[fields]]; vertexFunctionBody = Switch[vertexClassName, "SingleComponentedVertex", - expr = (SARAH`Cp @@ indexedParticles) /. vertexRules; + expr = (SARAH`Cp @@ fields) /. vertexRules; expr = TreeMasses`ReplaceDependenciesReverse[expr]; "std::complex result;\n\n" <> declareIndices <> @@ -476,8 +404,8 @@ If you add new kinds of vertices (e.g for new diagram types): "return vertex_type(result);", "LeftAndRightComponentedVertex", - exprL = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PL] /. vertexRules; - exprR = SARAH`Cp[Sequence @@ indexedParticles][SARAH`PR] /. vertexRules; + exprL = SARAH`Cp[Sequence @@ fields][SARAH`PL] /. vertexRules; + exprR = SARAH`Cp[Sequence @@ fields][SARAH`PR] /. vertexRules; exprL = TreeMasses`ReplaceDependenciesReverse[exprL]; exprR = TreeMasses`ReplaceDependenciesReverse[exprR]; "std::complex left, right;\n\n" <> @@ -487,25 +415,22 @@ If you add new kinds of vertices (e.g for new diagram types): TreeMasses`ExpressionToString[exprR, "right"] <> "\n" <> "return vertex_type(left, right);"]; - sarahParticles = SARAH`getParticleName /@ particles; - particleInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ - sarahParticles, 1]; - - (* INFO: I do not think this ever occurs... *) - particleInfo = DeleteCases[particleInfo, {SARAH`generation, 1}, {3}]; - particleInfo = DeleteCases[particleInfo, {SARAH`lorentz, _}, {3}]; - - indexBounds = (With[{particleIndex = #}, - (If[#[[1]] === SARAH`generation, - {particleInfo[[particleIndex, 2]]-1, particleInfo[[particleIndex, 3]]}, - {1, #[[2]]}] - &) /@ particleInfo[[particleIndex, 5]]] - &) /@ Table[i, {i, Length[particles]}]; - indexBounds = Cases[Flatten[indexBounds, 1], Except[{}]]; - - If[indexBounds === {}, + sarahFields = SARAH`getParticleName /@ fields; + fieldInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ + sarahFields, 1]; + + trIndexBounds = Cases[Flatten[(With[{fieldIndex = #}, + (If[#[[1]] === SARAH`generation, + {fieldInfo[[fieldIndex, 2]]-1, fieldInfo[[fieldIndex, 3]]}, + {1, #[[2]]}] + &) /@ fieldInfo[[fieldIndex, 5]]] + &) /@ Table[i, {i, Length[fields]}], + 1], + Except[{}]]; + + If[trIndexBounds === {}, indexBounds = {{},{}}, - indexBounds = Transpose @ indexBounds]; + indexBounds = Transpose @ trIndexBounds]; parsedVertex = ParsedVertex[numberOfIndices, indexBounds, @@ -516,7 +441,7 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (** Getters to the ParsedVertex structure **) -NumberOfIndices[parsedVertex_ParsedVertex] := Total[parsedVertex[[1]]]; +NumberOfIndices[parsedVertex_ParsedVertex] := Total @ parsedVertex[[1]]; NumberOfIndices[parsedVertex_ParsedVertex, pIndex_Integer] := parsedVertex[[1, pIndex]]; IndexBounds[parsedVertex_ParsedVertex] := parsedVertex[[2]]; @@ -531,26 +456,26 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{diagrams}, If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; - cachedContributingDiagrams = Flatten[(ContributingDiagramsOfType[#] &) - /@ contributingDiagramTypes - , 1]; + diagrams = Flatten[(ContributingDiagramsOfType[#] &) + /@ diagramTypes + , 1]; cachedContributingDiagrams = ({#, Union @ - (Sequence @@ Cases[cachedContributingDiagrams, - {#, diagrams_List} -> diagrams])} &) /@ edmParticles; - + (Sequence @@ Cases[diagrams, + {#, diags_List} -> diags])} &) /@ edmFields; + Return[cachedContributingDiagrams]; ]; (* Returns a list of all concrete diagram evaluators - format: {{edmParticle1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, - {edmParticle2, {"...", ... }}, + format: {{edmField1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, + {edmField2, {"...", ... }}, ...} that need to be invoked in our calculation *) ConcreteDiagramEvaluators[] := ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> ToString @ #[[1,1]] <> ">, " <> - StringJoin @ (Riffle[ParticleToCXXName /@ List @@ #[[2;;]], ", "]) <> + StringJoin @ (Riffle[CXXNameOfField /@ List @@ #[[2;;]], ", "]) <> ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 3e4d565d4..cdb33b0de 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1451,6 +1451,7 @@ corresponding tadpole is real or imaginary (only in models with CP SetEDMParticles[edmParticles]; +<<<<<<< f022a76758c5793154e4da8f864942d0900151ac Print[EDM`CreateVertices[vertexRules]]; (* particles = EDM`CreateParticles[]; @@ -1470,6 +1471,25 @@ corresponding tadpole is real or imaginary (only in models with CP "@EDM_Calculation@" -> IndentText[calculationCode], Sequence @@ GeneralReplacementRules[] } ];*) +======= + particles = EDM`CreateParticles[]; + chargeGetters = EDM`CreateChargeGetters[]; + diagrams = EDM`CreateDiagrams[]; + + vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; + definitions = EDM`CreateDefinitions[vertexRules]; + calculationCode = EDM`CreateCalculation[]; + + (*WriteOut`ReplaceInFiles[files, + { "@EDM_Particles@" -> particles, + "@EDM_ChargeGetters@" -> chargeGetters, + "@EDM_Diagrams@" -> diagrams, + "@EDM_VertexFunctionData@" -> vertexFunctionData, + "@EDM_Definitions@" -> definitions, + "@EDM_Calculation@" -> IndentText[calculationCode], + Sequence @@ GeneralReplacementRules[] + } ];*) +>>>>>>> Too much to describe... ]; EnableForBVPSolver[solver_, statements_String] := @@ -2734,17 +2754,10 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; -<<<<<<< 2f6a3062c3ce3b875f83065972915e93fa9ee0fd Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; -======= - Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], - vertexRuleFileName], - vertexRules = Get[vertexRuleFileName]; ->>>>>>> First steps towards integrating the EDM module. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; From 1f25afcea6436e2e797a8d718316d4ae6268716e Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:01:32 +0100 Subject: [PATCH 087/158] Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. --- meta/EDM.m | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 176671bbd..7c8c6f727 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -221,6 +221,9 @@ If you add new kinds of vertices (e.g for new diagram types): {SARAH`FieldToInsert[1], SARAH`FieldToInsert[2]}}], subtypedDiagrams, uniqueDiagrams}, + If[TreeMasses`IsFermion[edmField] =!= True, + Return[{edmField,{}}]]; + subtypedDiagrams = (Module[{photonEmitter = #[[2,1]], exchangeField = #[[2,2]], subType}, @@ -466,11 +469,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[cachedContributingDiagrams]; ]; -(* Returns a list of all concrete diagram evaluators - format: {{edmField1, {"DiagramEvaluator, Fe, VP>", "...", ... }}, - {edmField2, {"...", ... }}, - ...} - that need to be invoked in our calculation *) ConcreteDiagramEvaluators[] := ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> From e748cf61f5a8c3be6989de16d292f66147bacf21 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:02:58 +0100 Subject: [PATCH 088/158] Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. --- meta/FlexibleSUSY.m | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index cdb33b0de..6964a2231 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -5,7 +5,7 @@ "Phases`", "LoopMasses`", "WriteOut`", "Constraint`", "ThresholdCorrections`", "ConvergenceTester`", "Utils`", "ThreeLoopSM`", "ThreeLoopMSSM`", "Observables`", - "GMuonMinus2`", "EffectiveCouplings`", + "GMuonMinus2`", "EDM`", "EffectiveCouplings`", "FlexibleEFTHiggsMatching`", "FSMathLink`", "FlexibleTower`"}]; @@ -1480,7 +1480,7 @@ corresponding tadpole is real or imaginary (only in models with CP definitions = EDM`CreateDefinitions[vertexRules]; calculationCode = EDM`CreateCalculation[]; - (*WriteOut`ReplaceInFiles[files, + WriteOut`ReplaceInFiles[files, { "@EDM_Particles@" -> particles, "@EDM_ChargeGetters@" -> chargeGetters, "@EDM_Diagrams@" -> diagrams, @@ -1488,8 +1488,12 @@ corresponding tadpole is real or imaginary (only in models with CP "@EDM_Definitions@" -> definitions, "@EDM_Calculation@" -> IndentText[calculationCode], Sequence @@ GeneralReplacementRules[] +<<<<<<< 39b7519c812c04e0347cb5e65bcfdcc4fc687214 } ];*) >>>>>>> Too much to describe... +======= + } ]; +>>>>>>> Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. ]; EnableForBVPSolver[solver_, statements_String] := @@ -2961,8 +2965,11 @@ corresponding tadpole is real or imaginary (only in models with CP FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; Print["Creating class EDM"]; - WriteGMuonMinus2Class[vertexRules, - {}]; + WriteEDMClass[vertexRules, + {{FileNameJoin[{$flexiblesusyTemplateDir, "edm.hpp.in"}], + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.hpp"}]}, + {FileNameJoin[{$flexiblesusyTemplateDir, "edm.cpp.in"}], + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.cpp"}]}}]; PrintHeadline["Creating Mathematica interface"]; Print["Creating LibraryLink ", FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> ".mx"}], " ..."]; From 7dcfe586972c5f92919734d2e90531eeb4a5e791 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:58:04 +0100 Subject: [PATCH 089/158] Preparing for first run. --- meta/EDM.m | 12 +- meta/FlexibleSUSY.m | 38 +--- templates/edm.cpp.in | 511 +++++++++++++++++++++++++++++++++++++++++++ templates/edm.hpp.in | 43 ++++ 4 files changed, 571 insertions(+), 33 deletions(-) create mode 100644 templates/edm.cpp.in create mode 100644 templates/edm.hpp.in diff --git a/meta/EDM.m b/meta/EDM.m index 7c8c6f727..7316f4fb5 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -343,7 +343,7 @@ If you add new kinds of vertices (e.g for new diagram types): "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" );]; - definition = ("template<> template<> " <> functionClassName <> "::vertex_type\n" <> + definition = ("template<> " <> functionClassName <> "::vertex_type\n" <> functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> "{\n" <> IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> @@ -458,6 +458,7 @@ If you add new kinds of vertices (e.g for new diagram types): ContributingDiagrams[] := Module[{diagrams}, If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; + LoadVerticesIfNecessary[]; diagrams = Flatten[(ContributingDiagramsOfType[#] &) /@ diagramTypes @@ -469,6 +470,15 @@ If you add new kinds of vertices (e.g for new diagram types): Return[cachedContributingDiagrams]; ]; +LoadVerticesIfNecessary[] := + Module[{}, + If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, + SARAH`InitVertexCalculation[FSEigenstates`FSEigenstates, False]; + SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; + SARAH`MakeCouplingLists; + ]; + ]; + ConcreteDiagramEvaluators[] := ({#[[1]], (("DiagramEvaluator<" <> SymbolName @ Head @ #[[1]] <> "<" <> diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 6964a2231..8d10c6cbe 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1445,34 +1445,13 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the EDM c++ files *) WriteEDMClass[vertexRules_List, files_List] := -Module[{edmParticles, particles, chargeGetters, diagrams, vertexFunctionData, +Module[{fields, edmFields, chargeGetters, diagrams, vertexFunctionData, definitions, calculationCode}, - edmParticles = {SARAH`Electron}; + edmFields = {SARAH`Electron}; + EDM`SetEDMFields[edmParticles]; - SetEDMParticles[edmParticles]; + fields = EDM`CreateFields[]; -<<<<<<< f022a76758c5793154e4da8f864942d0900151ac - Print[EDM`CreateVertices[vertexRules]]; - (* - particles = EDM`CreateParticles[]; - chargeGetters = EDM`CreateChargeGetters[]; - diagrams = EDM`CreateDiagrams[]; - - vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; - definitions = EDM`CreateDefinitions[vertexRules]; - calculationCode = EDM`CreateCalculation[]; - - WriteOut`ReplaceInFiles[files, - { "@EDM_Particles@" -> particles, - "@EDM_ChargeGetters@" -> chargeGetters, - "@EDM_Diagrams@" -> diagrams, - "@EDM_VertexFunctionData@" -> vertexFunctionData, - "@EDM_Definitions@" -> definitions, - "@EDM_Calculation@" -> IndentText[calculationCode], - Sequence @@ GeneralReplacementRules[] - } ];*) -======= - particles = EDM`CreateParticles[]; chargeGetters = EDM`CreateChargeGetters[]; diagrams = EDM`CreateDiagrams[]; @@ -1481,19 +1460,14 @@ corresponding tadpole is real or imaginary (only in models with CP calculationCode = EDM`CreateCalculation[]; WriteOut`ReplaceInFiles[files, - { "@EDM_Particles@" -> particles, + { "@EDM_Fields@" -> fields, "@EDM_ChargeGetters@" -> chargeGetters, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, "@EDM_Calculation@" -> IndentText[calculationCode], Sequence @@ GeneralReplacementRules[] -<<<<<<< 39b7519c812c04e0347cb5e65bcfdcc4fc687214 - } ];*) ->>>>>>> Too much to describe... -======= } ]; ->>>>>>> Added check if edmParticle is a fermion. Otherwise we don't know how to calculate the diagrams. ]; EnableForBVPSolver[solver_, statements_String] := @@ -2051,7 +2025,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := EDM`NPointFunctions[]; +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in new file mode 100644 index 000000000..e10a9b3cd --- /dev/null +++ b/templates/edm.cpp.in @@ -0,0 +1,511 @@ +// ==================================================================== +// This file is part of FlexibleSUSY. +// +// FlexibleSUSY is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// FlexibleSUSY is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with FlexibleSUSY. If not, see +// . +// ==================================================================== + +// File generated at @DateAndTime@ + +/** + * @file @ModelName@_edm.cpp + * + * This file was generated at @DateAndTime@ with FlexibleSUSY + * @FlexibleSUSYVersion@ and SARAH @SARAHVersion@ . + */ + +#include "@ModelName@_edm.hpp" +#include "@ModelName@_mass_eigenstates.hpp" + +#include "numerics2.hpp" +#include "wrappers.hpp" + +#include +#include +#include +#include + +#define INPUTPARAMETER(p) context.model.get_input().p +#define MODELPARAMETER(p) context.model.get_##p() +#define DERIVEDPARAMETER(p) context.model.p() + +using namespace flexiblesusy; + +namespace { +/** + * @class IndexBounds + * @brief A class representing multiple (N) index ranges. + * + * N is a non-negative integer. + * The ranges are specified the c++ way; The range begins are inclusive + * and the range ends are exclusive. Misspecified ranges result in + * undefined behaviour! + * The intended use is to iterate over an IndexBounds using the normal + * begin()/end() syntax, which will iterate over every possible combination + * of the indices within their respective ranges. + * The ranges are const! Once they are initialized they cannot be changed. + * Initialization is done like = {{ beg1, beg2, ... }, { end1, end2, ... }} + */ +template struct IndexBounds; + +/** + * @class IndexIterator + * @brief The iterator class used by IndexBounds. + * + * It only fulfils the input iterator requirements! + * The value_type is a const std::array + * containing the current indices. + * Incrementing the iterator results in a new index combination. + */ +template struct IndexIterator +: public std::iterator< +std::input_iterator_tag, +const std::array> +{ + friend class IndexBounds; +private: + const IndexBounds *bounds; + std::array indices; + + IndexIterator(const IndexBounds &b, const unsigned *i) + : bounds(&b) + { + std::memcpy(indices.data(), i, N * sizeof(unsigned)); + } +public: + const std::array &operator*() const { + return indices; + } + + const std::array *operator->() const { + return &indices; + } + + IndexIterator &operator++() { + for (unsigned i = 0; i != N; i++) { + indices[i]++; + if (indices[i] == bounds->indexEnd[i]) { + indices[i] = bounds->indexBegin[i]; + continue; + } + + return *this; + } + + std::memcpy(indices.data(), bounds->indexEnd, N * sizeof(unsigned)); + return *this; + } + + IndexIterator operator++(int) { + IndexIterator it(*this); + this->operator++(); + return it; + } + + template + friend bool operator==(const IndexIterator &it1, const IndexIterator &it2); +}; + +template +bool operator==(const IndexIterator &it1, const IndexIterator &it2) +{ + return it1.indices == it2.indices; +} + +template +bool operator!=(const IndexIterator &it1, const IndexIterator &it2) +{ + return !(it1 == it2); +} + +template struct IndexBounds { + typedef const std::array indices_type; + + unsigned indexBegin[N]; + unsigned indexEnd[N]; + + typedef IndexIterator const_iterator; + + const_iterator begin() const { + return const_iterator(*this, indexBegin); + } + + const_iterator end() const { + return const_iterator(*this, indexEnd); + } +}; + +template<> struct IndexBounds<0> { + typedef const std::array indices_type; + typedef indices_type * const_iterator; + + static const indices_type dummyIndex; + + const_iterator begin() const + { return &dummyIndex; } + const_iterator end() const + { return (begin()+1); } +}; +IndexBounds<0>::indices_type IndexBounds<0>::dummyIndex{}; + +@EDM_Fields@ + +template struct remove_anti { typedef P type; }; +template struct remove_anti> { typedef P type; }; + +/** + * @class EvaluationContext + * @brief Represents an evaluation context. + * + * Actually it simply contains a reference to a model object. + * All computational functions are forwarded to that object, + * e.g. mass calculation functions. + */ +struct EvaluationContext { + @ModelName@_mass_eigenstates& model; ///< The model object. + + /** + * @fn mass

+ * @brief Returns the mass of a particle. + */ + template double mass() const { + return mass::type>(); + } + + template double mass(unsigned index) const { + return mass::type>(index); + } +}; + +/** + * @class DiagramEvaluator + * @brief A template that can calculate disagrams. + * + * This template is completely general. The intended use is + * to have specialisations of the kind: + * DiagramEvaluator + * along with a static member function: + * static double value( EvaluationContext &context ); + * that calculates the contribution to the edm + * for a specific diagram class with specified particles. + */ +template struct DiagramEvaluator; + +double OneLoopFunctionF1C(double); +double OneLoopFunctionF2C(double); +double OneLoopFunctionF1N(double); +double OneLoopFunctionF2N(double); + +@EDM_MuonFunctionPrototypes@ + +@EDM_Diagrams@ + +/** + * @class SingleComponentedVertex + * @brief A vertex whose value can be represented by a single complex number + */ +class SingleComponentedVertex { +private: + std::complex val; ///< The value +public: + SingleComponentedVertex(std::complex v) + : val(v) {} + + /** + * @fn value + * @brief Returns the value of the vertex. + */ + std::complex value() const { + return val; + } + + /** + * @fn isZero + * @brief Tests whether the value is numerically significant + */ + bool isZero() const { + return (is_zero(val.real()) && is_zero(val.imag())); + } +}; + +/** + * @class LeftAndRightComponentedVertex + * @brief A vertex whose value can be represented by two complex numbers + */ +class LeftAndRightComponentedVertex { +private: + std::pair, std::complex> value; ///< The values +public: + LeftAndRightComponentedVertex(const std::complex &left, + const std::complex &right) + : value(left, right) {} + + /** + * @fn left + * @brief Returns the left component of the vertex. + */ + std::complex left() const { + return value.first; + } + + /** + * @fn right + * @brief Returns the left component of the vertex. + */ + std::complex right() const { + return value.second; + } + + /** + * @fn isZero + * @brief Tests whether the values are numerically significant + */ + bool isZero() const { + return (is_zero(value.first.real()) && is_zero(value.first.imag()) && + is_zero(value.second.real()) && is_zero(value.second.imag())); + } +}; + +/** + * @class VertexFunctionData + * @brief Vertex data for a vertex with the particles specified by P... + * + * All elements in P... have to be publicly derived from Particle. + * The data includes the type of the vertex, whether P... is in + * canonical order or permuted as well as index bounds referring to + * the specific particles (generation and colour indices, etc). + * The intention is to have a program generate VertexFunctionData<> + * specialisations that are then used by the VertexFunction<> template. + */ +template struct VertexFunctionData; + +/** + * @class VertexFunction + * @brief A template that represents a vertex with open particle indices. + * + * All elements in P... have to be publicly derived from Particle. + * To obtain a conrete value, use the static member function vertex() + * along with the desired particle indices. + */ +template class VertexFunction { +{ +private: +typedef VertexFunctionData Base; +typedef typename Base::particleIndexStart particleIndexStart; +using Base::indexB; +public: +typedef typename Base::index_bounds index_bounds; +typedef typename index_bounds::indices_type indices_type; +typedef typename Base::vertex_type vertex_type; +public: + + + + + using Data = VertexFunctionData; +public: + using index_bounds = Data::index_bounds index_bounds; + using indices_type = index_bounds::indices_type; + using vertex_type = Data::vertex_type; + + /** + * @fn indexBounds + * @brief Returns the IndexBounds<> object of the VertexFunction. + */ + static const index_bounds &indexBounds() { + return indexB; + } + + /** + * @fn particleIndices + * @brief Returns the subset of indices belonging to + * a particle at a given index. + * @param indices The complete set of indices for all particles + * + * The particle indexing is in the same order as the template arguments + * and starts at 0. + */ + template + static std::vector particleIndices(const indices_type &indices) + { + auto begin = indices.begin() + boost::mpl::at_c::type::value; + auto end = indices.begin() + boost::mpl::at_c::type::value; + return std::vector(begin, end); + } + + /** + * @fn vertex + * @brief Calculates the vertex for a given set of particle indices. + * @param indices The particle indices + * @param context The evaluation context + */ + static vertex_type vertex(const indices_type &indices, EvaluationContext &context); +}; + +@EDM_VertexFunctionData@ +} + +@EDM_Calculation@ + +double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstates& model_) +{ + // make copy since model is modified via call to calculate_MFe_pole() + @ModelName@_mass_eigenstates model(model_); + + return edm(); +} + +namespace { +/** +* @defgroup LoopFunctions +* @brief The loop functions necessary for \f$a_\mu\f$ one-loop calculations. +* +* These are OneLoopFunctionF1C(), OneLoopFunctionF2C(), +* OneLoopFunctionF1N() and OneLoopFunctionF2N() +* as specified in arXiv:1311.1775 +*/ + +double OneLoopFunctionF1C(double x) +{ + if (is_zero(x)) + return 4.0; + + // error around x=1 is <= 10^-12 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.21) { + return (1.0000000000000000000 - + 0.60000000000000000000 * y + + 0.40000000000000000000 * y * y - + 0.28571428571428571429 * y * y * y + + 0.21428571428571428571 * y * y * y * y - + 0.16666666666666666667 * y * y * y * y * y + + 0.13333333333333333333 * y * y * y * y * y * y - + 0.10909090909090909091 * y * y * y * y * y * y * y + + 0.090909090909090909091 * y * y * y * y * y * y * y * y - + 0.076923076923076923077 * y * y * y * y * y * y * y * y * y + + 0.065934065934065934066 * y * y * y * y * y * y * y * y * y * y - + 0.057142857142857142857 * y * y * y * y * y * y * y * y * y * y * y + + 0.050000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.044117647058823529412 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.039215686274509803922 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.035087719298245614035 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + } + + return 2.0 / (y * y * y * y) * (2.0 + 3.0 * x - 6.0 * x * x + x * x * x + 6.0 * x * std::log(x)); +} + +double OneLoopFunctionF2C(double x) +{ + // error around x=1 is <= 10^-13 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.155) + return (1.0 - 0.75 * y + 0.6 * y * y - + 0.50000000000000000000 * y * y * y + + 0.4285714285714285714 * y * y * y * y - + 0.37500000000000000000 * y * y * y * y * y + + 0.33333333333333333333 * y * y * y * y * y * y - + 0.3000000000000000000 * y * y * y * y * y * y * y + + 0.2727272727272727273 * y * y * y * y * y * y * y * y - + 0.2500000000000000000 * y * y * y * y * y * y * y * y * y + + 0.23076923076923076923 * y * y * y * y * y * y * y * y * y * y - + 0.21428571428571428571 * y * y * y * y * y * y * y * y * y * y * y + + 0.2000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.1875000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.1764705882352941176 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.16666666666666666667 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + + return -3.0 / (2.0 * y * y * y) * (-3.0 + 4.0 * x - x * x - 2.0 * std::log(x)); +} + +double OneLoopFunctionF1N(double x) +{ + if (is_zero(x)) + return 2.0; + + // error around x=1 is <= 10^-12 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.23) + return (1.0000000000000000000 - + 0.4000000000000000000 * y + + 0.2000000000000000000 * y * y - + 0.11428571428571428571 * y * y * y + + 0.07142857142857142857 * y * y * y * y - + 0.04761904761904761905 * y * y * y * y * y + + 0.03333333333333333333 * y * y * y * y * y * y - + 0.02424242424242424242 * y * y * y * y * y * y * y + + 0.0181818181818181818 * y * y * y * y * y * y * y * y - + 0.01398601398601398601 * y * y * y * y * y * y * y * y * y + + 0.01098901098901098901 * y * y * y * y * y * y * y * y * y * y - + 0.0087912087912087912 * y * y * y * y * y * y * y * y * y * y * y + + 0.00714285714285714286 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.0058823529411764706 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.0049019607843137255 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.0041279669762641899 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + + return 2.0 / (y * y * y * y) * (1.0 - 6.0 * x + 3.0 * x * x + 2.0 * x * x * x - 6.0 * x * x * std::log(x)); +} + +double OneLoopFunctionF2N(double x) +{ + if (is_zero(x)) + return 3.0; + + // error around x=1 is <= 10^-13 on an intel i7 + const double y = x - 1.0; + + if (std::abs(y) < 0.185) + return (1.0000000000000000000 - + 0.50000000000000000000 * y + + 0.30000000000000000000 * y * y - + 0.2000000000000000000 * y * y * y + + 0.14285714285714285714 * y * y * y * y - + 0.10714285714285714286 * y * y * y * y * y + + 0.08333333333333333333 * y * y * y * y * y * y - + 0.06666666666666666667 * y * y * y * y * y * y * y + + 0.05454545454545454545 * y * y * y * y * y * y * y * y - + 0.0454545454545454545 * y * y * y * y * y * y * y * y * y + + 0.0384615384615384615 * y * y * y * y * y * y * y * y * y * y - + 0.03296703296703296703 * y * y * y * y * y * y * y * y * y * y * y + + 0.0285714285714285714 * y * y * y * y * y * y * y * y * y * y * y * y - + 0.02500000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + + 0.0220588235294117647 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - + 0.0196078431372549020 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + + return -3.0 / (y * y * y) * (1.0 - x * x + 2.0 * x * std::log(x)); +} + +@EDM_Definitions@ + +template +double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +{ + double res = 0.0; + + + return res; +} + +template +double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +{ + double res = 0.0; + + + + return res; +} +} diff --git a/templates/edm.hpp.in b/templates/edm.hpp.in new file mode 100644 index 000000000..880373086 --- /dev/null +++ b/templates/edm.hpp.in @@ -0,0 +1,43 @@ +// ==================================================================== +// This file is part of FlexibleSUSY. +// +// FlexibleSUSY is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// FlexibleSUSY is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with FlexibleSUSY. If not, see +// . +// ==================================================================== + +// File generated at @DateAndTime@ + +/** + * @file @ModelName@_edm.hpp + * + * This file was generated at @DateAndTime@ with FlexibleSUSY + * @FlexibleSUSYVersion@ and SARAH @SARAHVersion@ . + */ + +#ifndef @ModelName@_EDM_H +#define @ModelName@_EDM_H + +namespace flexiblesusy { +class @ModelName@_mass_eigenstates; + +namespace @ModelName@_edm { +/** +* @fn calculate_edm_electron +* @brief Calculates the electromagnetic dipole moment of the electron. +*/ +double calculate_edm_electron(const @ModelName@_mass_eigenstates& model); +} // namespace @ModelName@_edm +} // namespace flexiblesusy + +#endif From 45021fbd4cfabf52ba2c76c42f5cfa891b233e52 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:02:39 +0100 Subject: [PATCH 090/158] Fixed Typo --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 7316f4fb5..9f43fdc5e 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -473,7 +473,7 @@ If you add new kinds of vertices (e.g for new diagram types): LoadVerticesIfNecessary[] := Module[{}, If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, - SARAH`InitVertexCalculation[FSEigenstates`FSEigenstates, False]; + SARAH`InitVertexCalculation[FlexibleSUSY`FSEigenstates, False]; SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; SARAH`MakeCouplingLists; ]; From 33a849ee1a65745822d2e6cd2295ad8e40de9f65 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:43:59 +0100 Subject: [PATCH 091/158] Added edm as build template. Lots of small codegen fixes. --- meta/EDM.m | 5 ++- meta/FlexibleSUSY.m | 4 +- templates/edm.cpp.in | 99 ++++++++++++++++++++---------------------- templates/module.mk | 2 + templates/module.mk.in | 3 ++ 5 files changed, 56 insertions(+), 57 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 9f43fdc5e..a451b5443 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -43,6 +43,7 @@ If you add new kinds of vertices (e.g for new diagram types): "};\n" &) /@ fields, "\n"] <> "\n\n" <> "// Special field families\n" <> "using Photon = " <> CXXNameOfField @ SARAH`Photon <> ";\n" <> + "using Electron = " <> CXXNameOfField @ SARAH`Electron <> ";\n\n" <> "// Anti fields\n" <> "template struct anti : public Field\n" <> @@ -121,11 +122,11 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{code, evaluators}, evaluators = ConcreteDiagramEvaluators[]; - code = "template double edm( void );\n\n"; + code = "template double edm( CMSSM_mass_eigenstates& model );\n\n"; code = (code <> StringJoin @ Riffle[Module[{field = #[[1]], fieldEvaluators = #[[2]]}, - "template<> double edm<" <> CXXNameOfField[field] <> ">( void )\n" <> + "template<> double edm<" <> CXXNameOfField[field] <> ">( CMSSM_mass_eigenstates& model )\n" <> "{\n" <> IndentText["EvaluationContext context{ model };\n" <> "double val = 0.0;\n\n" <> diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 8d10c6cbe..d5340d16d 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1465,7 +1465,7 @@ corresponding tadpole is real or imaginary (only in models with CP "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, - "@EDM_Calculation@" -> IndentText[calculationCode], + "@EDM_Calculation@" -> calculationCode, Sequence @@ GeneralReplacementRules[] } ]; ]; @@ -2025,7 +2025,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index e10a9b3cd..e2ff9de09 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -161,8 +161,8 @@ IndexBounds<0>::indices_type IndexBounds<0>::dummyIndex{}; @EDM_Fields@ -template struct remove_anti { typedef P type; }; -template struct remove_anti> { typedef P type; }; +template struct remove_anti { typedef F type; }; +template struct remove_anti> { typedef F type; }; /** * @class EvaluationContext @@ -176,15 +176,15 @@ struct EvaluationContext { @ModelName@_mass_eigenstates& model; ///< The model object. /** - * @fn mass

- * @brief Returns the mass of a particle. + * @fn mass + * @brief Returns the mass of a field. */ - template double mass() const { - return mass::type>(); + template double mass() const { + return mass::type>(); } - template double mass(unsigned index) const { - return mass::type>(index); + template double mass(unsigned index) const { + return mass::type>(index); } }; @@ -194,11 +194,11 @@ struct EvaluationContext { * * This template is completely general. The intended use is * to have specialisations of the kind: - * DiagramEvaluator + * DiagramEvaluator * along with a static member function: * static double value( EvaluationContext &context ); * that calculates the contribution to the edm - * for a specific diagram class with specified particles. + * for a specific diagram class with specified fields. */ template struct DiagramEvaluator; @@ -207,7 +207,7 @@ double OneLoopFunctionF2C(double); double OneLoopFunctionF1N(double); double OneLoopFunctionF2N(double); -@EDM_MuonFunctionPrototypes@ +@EDM_ChargeGetters@ @EDM_Diagrams@ @@ -278,46 +278,35 @@ public: }; /** - * @class VertexFunctionData - * @brief Vertex data for a vertex with the particles specified by P... + * @class VertexFunctionData + * @brief Vertex data for a vertex with the fields specified by F... * - * All elements in P... have to be publicly derived from Particle. - * The data includes the type of the vertex, whether P... is in + * All elements in F... have to be publicly derived from Field. + * The data includes the type of the vertex, whether F... is in * canonical order or permuted as well as index bounds referring to - * the specific particles (generation and colour indices, etc). + * the specific fields (generation and colour indices, etc). * The intention is to have a program generate VertexFunctionData<> * specialisations that are then used by the VertexFunction<> template. */ -template struct VertexFunctionData; +template struct VertexFunctionData; /** - * @class VertexFunction - * @brief A template that represents a vertex with open particle indices. + * @class VertexFunction + * @brief A template that represents a vertex with open field indices. * - * All elements in P... have to be publicly derived from Particle. + * All elements in F... have to be publicly derived from Field. * To obtain a conrete value, use the static member function vertex() - * along with the desired particle indices. + * along with the desired field indices. */ -template class VertexFunction { +template class VertexFunction { { -private: -typedef VertexFunctionData Base; -typedef typename Base::particleIndexStart particleIndexStart; -using Base::indexB; -public: -typedef typename Base::index_bounds index_bounds; -typedef typename index_bounds::indices_type indices_type; -typedef typename Base::vertex_type vertex_type; + using Data = VertexFunctionData; public: + using index_bounds = typename Data::index_bounds index_bounds; + using indices_type = typename index_bounds::indices_type; + using vertex_type = typename Data::vertex_type; - - - - using Data = VertexFunctionData; -public: - using index_bounds = Data::index_bounds index_bounds; - using indices_type = index_bounds::indices_type; - using vertex_type = Data::vertex_type; + using fieldIndexStart = typename Data::fieldIndexStart; /** * @fn indexBounds @@ -328,26 +317,26 @@ public: } /** - * @fn particleIndices + * @fn fieldIndices * @brief Returns the subset of indices belonging to - * a particle at a given index. - * @param indices The complete set of indices for all particles + * a field at a given index. + * @param indices The complete set of indices for all fields * - * The particle indexing is in the same order as the template arguments + * The field indexing is in the same order as the template arguments * and starts at 0. */ - template - static std::vector particleIndices(const indices_type &indices) + template + static std::vector fieldIndices(const indices_type &indices) { - auto begin = indices.begin() + boost::mpl::at_c::type::value; - auto end = indices.begin() + boost::mpl::at_c::type::value; + auto begin = indices.begin() + boost::mpl::at_c::type::value; + auto end = indices.begin() + boost::mpl::at_c::type::value; return std::vector(begin, end); } /** * @fn vertex - * @brief Calculates the vertex for a given set of particle indices. - * @param indices The particle indices + * @brief Calculates the vertex for a given set of field indices. + * @param indices The field indices * @param context The evaluation context */ static vertex_type vertex(const indices_type &indices, EvaluationContext &context); @@ -363,7 +352,7 @@ double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstate // make copy since model is modified via call to calculate_MFe_pole() @ModelName@_mass_eigenstates model(model_); - return edm(); + return edm( model ); } namespace { @@ -490,8 +479,10 @@ double OneLoopFunctionF2N(double x) @EDM_Definitions@ -template -double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +template +double DiagramEvaluator, + EDMField, PhotonEmitter, ExchangeField +>::value(EvaluationContext &context) { double res = 0.0; @@ -499,8 +490,10 @@ double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::val return res; } -template -double DiagramEvaluator, PhotonEmitter, ExchangeParticle>::value(EvaluationContext &context) +template +double DiagramEvaluator, + EDMField, PhotonEmitter, ExchangeField +>::value(EvaluationContext &context) { double res = 0.0; diff --git a/templates/module.mk b/templates/module.mk index c28d91ddc..f5c55b3ad 100644 --- a/templates/module.mk +++ b/templates/module.mk @@ -4,6 +4,8 @@ MODNAME := templates BASE_TEMPLATES := \ $(DIR)/a_muon.hpp.in \ $(DIR)/a_muon.cpp.in \ + $(DIR)/edm.hpp.in \ + $(DIR)/edm.cpp.in \ $(DIR)/convergence_tester.hpp.in \ $(DIR)/effective_couplings.hpp.in \ $(DIR)/effective_couplings.cpp.in \ diff --git a/templates/module.mk.in b/templates/module.mk.in index b7a42ce9b..f35ada05a 100644 --- a/templates/module.mk.in +++ b/templates/module.mk.in @@ -31,6 +31,7 @@ WITH_$(MODNAME) := yes LIB@CLASSNAME@_SRC := \ $(DIR)/@CLASSNAME@_a_muon.cpp \ + $(DIR)/@CLASSNAME@_edm.cpp \ $(DIR)/@CLASSNAME@_effective_couplings.cpp \ $(DIR)/@CLASSNAME@_info.cpp \ $(DIR)/@CLASSNAME@_input_parameters.cpp \ @@ -58,6 +59,8 @@ LL@CLASSNAME@_MMA := \ LIB@CLASSNAME@_HDR := \ $(DIR)/@CLASSNAME@_a_muon.hpp \ + $(DIR)/@CLASSNAME@_edm.hpp \ + $(DIR)/@CLASSNAME@_convergence_tester.hpp \ $(DIR)/@CLASSNAME@_effective_couplings.hpp \ $(DIR)/@CLASSNAME@_info.hpp \ $(DIR)/@CLASSNAME@_input_parameters.hpp \ From eade3b29a2056d9de4f5724712853d11b1b48915 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:57:55 +0100 Subject: [PATCH 092/158] Fixed a dependency on a SARAH symbol that is only available after SARAH`Start[]. --- meta/EDM.m | 5 ++++- meta/FlexibleSUSY.m | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index a451b5443..04dacc4e1 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -2,6 +2,8 @@ (* This module generates c++ code that calculates electric dipole moments of fields *) +Initialize::usage="Initialize the EDM module."; + SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; CreateFields::usage="Returns the c++ code that contains all field fields"; @@ -27,6 +29,8 @@ If you add new kinds of vertices (e.g for new diagram types): (************* Begin public interface *******************) +Initialize[] := (subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___);) + edmFields = Null; SetEDMFields[fields_List] := (edmFields = fields;) @@ -179,7 +183,6 @@ If you add new kinds of vertices (e.g for new diagram types): (**************** Other Functions ***************) -subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; AddIndexPattern[field_] := SARAH`getFull[SARAH`getBlank[field]] /. subIndexPattern; diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index d5340d16d..c04116364 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2025,7 +2025,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); +PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, From 00cfa6396cc95308ff578cf80093aae7183acea7 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 15:34:31 +0100 Subject: [PATCH 093/158] Fixed scoping issues. --- meta/EDM.m | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 04dacc4e1..2f03f17b2 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -153,7 +153,7 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (**************** End public interface *****************) -(* TODO: privatize interface again Begin["`Private`"]; *) +Begin["`Private`"]; (* The supported vertex types. They have the same names as their c++ counterparts. *) @@ -361,7 +361,7 @@ If you add new kinds of vertices (e.g for new diagram types): from the elements of `arrayName'. *) DeclareIndices[indexedFields_List, arrayName_String] := - Module[{p, total = 0, fieldIndexList, decl = ""}, + Module[{p, total = 0, fieldIndexList, decl = "", idx}, DeclareIndex[idx_, num_Integer, an_String] := ( "const unsigned " <> CConversion`ToValidCSymbolString[idx] <> " = " <> an <> "[" <> ToString[num] <> "];\n"); @@ -393,7 +393,7 @@ If you add new kinds of vertices (e.g for new diagram types): expr, exprL, exprR}, indexedFields = MapIndexed[(Module[{field = #1, index = #2[[1]]}, - SARAH`getFull[#1] /.subGC[index] /. subIndFinal[index,index] + SARAH`getFull[#1] /. SARAH`subGC[index] /. SARAH`subIndFinal[index,index] ] &), fields]; numberOfIndices = ((Length @ Vertices`FieldIndexList[#] &) /@ indexedFields); @@ -467,6 +467,7 @@ If you add new kinds of vertices (e.g for new diagram types): diagrams = Flatten[(ContributingDiagramsOfType[#] &) /@ diagramTypes , 1]; + cachedContributingDiagrams = ({#, Union @ (Sequence @@ Cases[diagrams, {#, diags_List} -> diags])} &) /@ edmFields; @@ -477,6 +478,7 @@ If you add new kinds of vertices (e.g for new diagram types): LoadVerticesIfNecessary[] := Module[{}, If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, + SA`CurrentStates = FlexibleSUSY`FSEigenstates; SARAH`InitVertexCalculation[FlexibleSUSY`FSEigenstates, False]; SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; SARAH`MakeCouplingLists; @@ -491,6 +493,6 @@ If you add new kinds of vertices (e.g for new diagram types): ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; -(* TODO: End[]; *) +End[]; EndPackage[]; From f90076e8f626b1989dc596d97fd0c27d556cfbdc Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:43:57 +0100 Subject: [PATCH 094/158] Fixed scoping issue. --- meta/EDM.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 2f03f17b2..0e04a8637 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -407,7 +407,7 @@ If you add new kinds of vertices (e.g for new diagram types): "std::complex result;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[expr] <> "\n" <> - TreeMasses`ExpressionToString[expr, "result"] <> "\n" <> + Parameters`ExpressionToString[expr, "result"] <> "\n" <> "return vertex_type(result);", "LeftAndRightComponentedVertex", @@ -418,8 +418,8 @@ If you add new kinds of vertices (e.g for new diagram types): "std::complex left, right;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[exprL + exprR] <> "\n" <> - TreeMasses`ExpressionToString[exprL, "left"] <> "\n" <> - TreeMasses`ExpressionToString[exprR, "right"] <> "\n" <> + Parameters`ExpressionToString[exprL, "left"] <> "\n" <> + Parameters`ExpressionToString[exprR, "right"] <> "\n" <> "return vertex_type(left, right);"]; sarahFields = SARAH`getParticleName /@ fields; From b0e6dff0d14ffa3dc7d6726dc3f3984d39b54f23 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:44:50 +0100 Subject: [PATCH 095/158] Moved Vertex logic to a place where the vertex files definitely exist. --- meta/FlexibleSUSY.m | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index c04116364..5e7af59bf 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,9 +2024,6 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; -(* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); - PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2174,7 +2171,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, edmVertices = {}, + gmm2Vertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2221,8 +2218,6 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; - (* EDM vertices *) - edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; @@ -2733,7 +2728,7 @@ corresponding tadpole is real or imaginary (only in models with CP effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, edmVertices, extraVertices], Lat$massMatrices], + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; effectiveCouplings = Get[effectiveCouplingsFileName]; @@ -2939,7 +2934,10 @@ corresponding tadpole is real or imaginary (only in models with CP FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; Print["Creating class EDM"]; - WriteEDMClass[vertexRules, + EDM`Initialize[]; + EDM`SetEDMFields[{SARAH`Electron}]; + + WriteEDMClass[Join[vertexRules, Vertices`VertexRules[EDM`NPointFunctions[], Lat$massMatrices]], {{FileNameJoin[{$flexiblesusyTemplateDir, "edm.hpp.in"}], FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.hpp"}]}, {FileNameJoin[{$flexiblesusyTemplateDir, "edm.cpp.in"}], From 7859a88b56a1c5f02cd990a3cd2d4066a9c7f7ee Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:45:19 +0100 Subject: [PATCH 096/158] Fixed typos. --- templates/edm.cpp.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index e2ff9de09..8fdb604e7 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -299,10 +299,9 @@ template struct VertexFunctionData; * along with the desired field indices. */ template class VertexFunction { -{ using Data = VertexFunctionData; public: - using index_bounds = typename Data::index_bounds index_bounds; + using index_bounds = typename Data::index_bounds; using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; From 9f9aea858918becfa0f6920186764860d26b99fb Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 18:44:01 +0100 Subject: [PATCH 097/158] Added explicit dependency on Parameters module. --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 0e04a8637..865308370 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -1,4 +1,4 @@ -BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "Vertices`"}]; +BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "Vertices`", "Parameters`"}]; (* This module generates c++ code that calculates electric dipole moments of fields *) From a3af720ba248314840e0ec2ba69b23fec43ab666 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 19:26:26 +0100 Subject: [PATCH 098/158] CreateVertexFunction[] does not use a cache anymore. --- meta/EDM.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 865308370..f633ea7fa 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -309,13 +309,10 @@ If you add new kinds of vertices (e.g for new diagram types): empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) -createdVertexFunctions = {}; CreateVertexFunction[fields_List, vertexRules_List] := Module[{prototype, definition, parsedVertex, dataClassName, functionClassName, fieldIndexStartF, fieldIndexStart, indexBounds}, - If[MemberQ[createdVertexFunctions, fields], Return[{"",""}]]; - parsedVertex = ParseVertex[fields, vertexRules]; dataClassName = "VertexFunctionData<" <> StringJoin @ Riffle[CXXNameOfField /@ fields, ", "] <> ">"; @@ -353,7 +350,6 @@ If you add new kinds of vertices (e.g for new diagram types): IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); - AppendTo[createdVertexFunctions, fields]; Return[{prototype, definition}]; ]; From 8c746d7ac311b6a8cdf72fb496434ac1278bebb9 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 19:27:01 +0100 Subject: [PATCH 099/158] Refactoring issue --- templates/edm.cpp.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 8fdb604e7..233edaea6 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -312,7 +312,7 @@ public: * @brief Returns the IndexBounds<> object of the VertexFunction. */ static const index_bounds &indexBounds() { - return indexB; + return index_bounds(); } /** From 7488a8587b3c7028be71ead6de692312ce130b25 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 22 Nov 2016 09:10:34 +0100 Subject: [PATCH 100/158] Reintroduced some cxx conversion function calls that for some weird reason got lost along the way... --- meta/EDM.m | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index f633ea7fa..3aa5ceee9 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -369,6 +369,9 @@ If you add new kinds of vertices (e.g for new diagram types): decl ]; +GetComplexScalarCType[] := + CConversion`CreateCType[CConversion`ScalarType[CConversion`complexScalarCType]]; + (* ParsedVertex structure: ParsedVertex[ {numP1Indices, numP2Indices, ...}, @@ -400,22 +403,23 @@ If you add new kinds of vertices (e.g for new diagram types): "SingleComponentedVertex", expr = (SARAH`Cp @@ fields) /. vertexRules; expr = TreeMasses`ReplaceDependenciesReverse[expr]; - "std::complex result;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[expr] <> "\n" <> - Parameters`ExpressionToString[expr, "result"] <> "\n" <> + "const " <> GetComplexScalarCType[] <> " result = " <> + Parameters`ExpressionToString[expr] <> ";\n\n" <> "return vertex_type(result);", - + "LeftAndRightComponentedVertex", exprL = SARAH`Cp[Sequence @@ fields][SARAH`PL] /. vertexRules; exprR = SARAH`Cp[Sequence @@ fields][SARAH`PR] /. vertexRules; exprL = TreeMasses`ReplaceDependenciesReverse[exprL]; exprR = TreeMasses`ReplaceDependenciesReverse[exprR]; - "std::complex left, right;\n\n" <> declareIndices <> Parameters`CreateLocalConstRefs[exprL + exprR] <> "\n" <> - Parameters`ExpressionToString[exprL, "left"] <> "\n" <> - Parameters`ExpressionToString[exprR, "right"] <> "\n" <> + "const " <> GetComplexScalarCType[] <> " left = " <> + Parameters`ExpressionToString[exprL] <> ";\n\n" <> + "const " <> GetComplexScalarCType[] <> " right = " <> + Parameters`ExpressionToString[exprR] <> ";\n\n" <> "return vertex_type(left, right);"]; sarahFields = SARAH`getParticleName /@ fields; From e598965ab68ee0a639f54646930a109689bdf69a Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 22 Nov 2016 15:46:58 +0100 Subject: [PATCH 101/158] Some simplifications due to better c++11 support (constexpr). --- meta/EDM.m | 29 ++++++------- templates/edm.cpp.in | 99 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 104 insertions(+), 24 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 3aa5ceee9..01edab1d4 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -324,26 +324,27 @@ If you add new kinds of vertices (e.g for new diagram types): fieldIndexStart = Table[fieldIndexStartF[i], {i, 1, Length[fields] + 1}]; + indexBounds = IndexBounds[parsedVertex]; + prototype = ("template<> struct " <> dataClassName <> "\n" <> "{\n" <> IndentText @ - ("typedef IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds;\n" <> - "typedef " <> VertexClassName[parsedVertex] <> " vertex_type;\n" <> - "typedef boost::mpl::vector_c - StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> - "> fieldIndexStart;\n" <> - "static const index_bounds indexB;\n" + ("constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> + "> index_bounds" <> + If[NumberOfIndices[parsedVertex] =!= 0, + "= { " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> + "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };\n" + , + ";/n" + ] <> + "constexpr std::array ToString @ Length[fieldIndexStart] <> + "> fieldIndexStart = { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + " };\n" <> + "using vertex_type = " <> VertexClassName[parsedVertex] <> ";\n" ) <> "};"); - indexBounds = IndexBounds[parsedVertex]; - - If[NumberOfIndices[parsedVertex] =!= 0, - prototype = (prototype <> "\n" <> - "const " <> dataClassName <> "::index_bounds " <> dataClassName <> "::indexB = { " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> - "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };" - );]; definition = ("template<> " <> functionClassName <> "::vertex_type\n" <> functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> "{\n" <> diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 233edaea6..52670ec48 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -43,6 +43,87 @@ using namespace flexiblesusy; namespace { +/** \brief Helper template for utils::make_array + */ +template +struct make_array_it +{ + using decayed_type = typename std::decay< + typename std::iterator_traits::value_type + >::type; + static constexpr bool use_cast = !std::is_same::value; + + template + static auto iterate( ForwardIterator begin, Args &&...args ) + -> typename std::enable_if< + !use_cast, + std::array + >::type + { + ForwardIterator copy( begin ); + return make_array_it::iterate( ++begin, + std::forward( args )..., *copy ); + } + + template + static auto iterate( ForwardIterator begin, Args &&...args ) + -> typename std::enable_if< + use_cast, + std::array + >::type + { + ForwardIterator copy( begin ); + return make_array_it::iterate( ++begin, + std::forward( args )..., T( *copy ) ); + } +}; + +/** \brief Specialized helper template for utils::make_array */ +template +struct make_array_it +{ + template + static auto iterate( ForwardIterator begin, Args &&...args ) + { + return std::array{ std::forward( args )... }; + } +}; + +/** \class make_array +* \brief Facility for easy construction of \a std::array +* objects. +* \tparam N The size of the to be constructed array +* \tparam T The type of the objects the array should hold +* or void (by default) if the type should be +* inferred. +*/ +template +struct make_array +{ + /** \brief Construct a \a std::array by copying values + * from a range. + * \tparam ForwardIterator The iterator type (usually inferred) + * \param[in] begin The iterator marking the beginning of + * the range to be copied. + * \returns A \a std::array holding the desired objects. + * \warning \a begin must be incrementable sufficiently + * often (\a N times) otherwise the behaviour + * is undefined. + */ + template + static auto iterate( ForwardIterator begin ) + { + using value_type = typename std::conditional< + std::is_void::value, + typename std::iterator_traits::value_type, + T + >::type; + + return detail::make_array_it::iterate( begin ); + } +}; + + /** * @class IndexBounds * @brief A class representing multiple (N) index ranges. @@ -301,18 +382,14 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; public: - using index_bounds = typename Data::index_bounds; - using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; - using fieldIndexStart = typename Data::fieldIndexStart; - /** * @fn indexBounds * @brief Returns the IndexBounds<> object of the VertexFunction. */ - static const index_bounds &indexBounds() { - return index_bounds(); + static constexpr decltype(Data::index_bounds) indexBounds() { + return Data::index_bounds; } /** @@ -325,11 +402,13 @@ public: * and starts at 0. */ template - static std::vector fieldIndices(const indices_type &indices) + static + std::array + fieldIndices(const Data::index_bounds::indices_type &indices) { - auto begin = indices.begin() + boost::mpl::at_c::type::value; - auto end = indices.begin() + boost::mpl::at_c::type::value; - return std::vector(begin, end); + constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; + auto begin = indices.begin() + Data::fieldIndexStart[fieldIndex]; + return utils::make_array::iterate(begin); } /** From ce2eafdba7d55f39ce53af5c65638c86a4f9bbe1 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 18:25:58 +0100 Subject: [PATCH 102/158] Small fixes --- meta/EDM.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 01edab1d4..9859ba285 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -472,7 +472,6 @@ If you add new kinds of vertices (e.g for new diagram types): cachedContributingDiagrams = ({#, Union @ (Sequence @@ Cases[diagrams, {#, diags_List} -> diags])} &) /@ edmFields; - Return[cachedContributingDiagrams]; ]; @@ -494,6 +493,6 @@ If you add new kinds of vertices (e.g for new diagram types): ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; -End[]; +(* TODO: End[]; *) EndPackage[]; From 574fe5f826cf574fe486910527709bd9d17015ca Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 20:59:14 +0100 Subject: [PATCH 103/158] Implemented ContributingDiagrams[] --- meta/EDM.m | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/meta/EDM.m b/meta/EDM.m index 9859ba285..c6bc96fa6 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -209,7 +209,141 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +<<<<<<< 379db5394ffb4373e1ea0bcc6a72e5a0ce7ee357 (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) +======= +(************************ Begin helper routines *******************************) + +(* Return the name of the SARAH particle family containing the muon *) +GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, + SARAH`Electron, + Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], + {p_, {Description -> "Muon", ___}} -> p, 1][[1]] + ]; +(* If the muon has a generation index, return it, otherwise return Null. + e.g. CMSSMNoFV has no muon generation index *) +GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; + +GetPhoton[] := SARAH`Photon; + +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; +SetAttributes[StripLorentzIndices, {Listable}]; + +(* Takes a SARAH particle and returns its antiparticle *) +AntiParticle[SARAH`bar[p_]] := p; +AntiParticle[Susyno`LieGroups`conj[p_]] := p; +AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, + If[IsScalar[pNoIndices] || IsVector[pNoIndices], + Susyno`LieGroups`conj[p], + SARAH`bar[p]]]; +SetAttributes[AntiParticle, {Listable}]; + +(* Return a string corresponding to the c++ class name of the particle. + Note that "bar" and "conj" get turned into anti<...>::type! *) +ParticleToCXXName[p_] := SymbolName[p]; +ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; + +(* Return a string corresponding to the name of the particle. + Note that "bar" and "conj" are left as they are! *) +ParticleToSARAHString[p_] := SymbolName[p]; +ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; +ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; + +(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) +ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], + Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; + +(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) +IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := + ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); + +(* Returns the rules that are needed to change order of a prticle list. + i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} + For some reason SARAH expects the indices to always be in that order... *) +IndexReplacementRulesForParticleReordering[particles_List, ordering_] := +Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, + Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; + +(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) +OrderParticles[particles_List, ordering_] := Module[{indexRules}, + indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; + Return[particles[[ordering]] /. indexRules]; + ]; + +(* Essentially the same as above, but using the obtained rules, + transform a whole vertex expression, as returned by SARAH`Vertex[] *) +OrderVertex[vertex_, ordering_] := + Module[{indexRules, particles, expr, newVertex}, + indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; + + particles = vertex[[1]][[ordering]]; + expr = vertex[[2;;]]; + + newVertex = (Join[{particles}, expr] /. indexRules); + Return[newVertex]; + ]; + +(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) +(* MemoizingVertex[] only works when __no__ indices are specified!!! *) +(* Use of memoization gives ~30% speedup for the MSSM! *) +memoizedVertices = {}; +MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := + Module[{memo, ordering, orderedParticles}, + (* First we sort the particles *) + ordering = Ordering[particles]; + orderedParticles = particles[[ordering]]; + + memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; + If[memo =!= {}, memo = memo[[1]], + (* Create a new entry *) + memo = SARAH`Vertex[orderedParticles, options]; + AppendTo[memoizedVertices, memo];]; + + (* Now return the particles to their original order *) + memo = OrderVertex[memo, Ordering[ordering]]; + Return[memo]]; + +MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; + +(* Test whether a SARAH Vertex[] result is nonzero (exact) *) +IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; + +(* Returns the name of the coupling function that FlexibleSUSY generates for + a specific vertex in a canonical order! *) +NameOfCouplingFunction[particles_List] := +((* FIXME: Not upwards compatible if naming conventions change *) + "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); + +(********************** End helper routines **************************) + +(* The different vertex types that are supported. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; + +(* The different diagram types that should be taken into consideration *) +(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) +(* There is no bounds check done on the integers, so they have to fit + into a standard c++ unsigned (!) int *) +contributingDiagramTypes = { + OneLoopDiagram[0], + OneLoopDiagram[1] +}; + +(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +>>>>>>> Implemented ContributingDiagrams[] (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, From 458315d58b0569cd66c09399339d44f285a35104 Mon Sep 17 00:00:00 2001 From: iolojz Date: Fri, 4 Nov 2016 21:08:51 +0100 Subject: [PATCH 104/158] Fixed bug in ContributingDiagramsOfType[] --- meta/EDM.m | 134 ----------------------------------------------------- 1 file changed, 134 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index c6bc96fa6..9859ba285 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -209,141 +209,7 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -<<<<<<< 379db5394ffb4373e1ea0bcc6a72e5a0ce7ee357 (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) -======= -(************************ Begin helper routines *******************************) - -(* Return the name of the SARAH particle family containing the muon *) -GetMuonFamily[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, - SARAH`Electron, - Cases[SARAH`ParticleDefinitions[FlexibleSUSY`FSEigenstates], - {p_, {Description -> "Muon", ___}} -> p, 1][[1]] - ]; -(* If the muon has a generation index, return it, otherwise return Null. - e.g. CMSSMNoFV has no muon generation index *) -GetMuonIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 2, Null]; - -GetPhoton[] := SARAH`Photon; - -IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; - -StripLorentzIndices[p_Symbol] := p; -StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; -StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; -StripLorentzIndices[p_] := Module[{remainingIndices}, - remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; - If[Length[remainingIndices] === 0, Head[p], - Head[p][remainingIndices]] - ]; -SetAttributes[StripLorentzIndices, {Listable}]; - -(* Takes a SARAH particle and returns its antiparticle *) -AntiParticle[SARAH`bar[p_]] := p; -AntiParticle[Susyno`LieGroups`conj[p_]] := p; -AntiParticle[p_] := Module[{pNoIndices = Vertices`StripFieldIndices[p]}, - If[IsScalar[pNoIndices] || IsVector[pNoIndices], - Susyno`LieGroups`conj[p], - SARAH`bar[p]]]; -SetAttributes[AntiParticle, {Listable}]; - -(* Return a string corresponding to the c++ class name of the particle. - Note that "bar" and "conj" get turned into anti<...>::type! *) -ParticleToCXXName[p_] := SymbolName[p]; -ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; - -(* Return a string corresponding to the name of the particle. - Note that "bar" and "conj" are left as they are! *) -ParticleToSARAHString[p_] := SymbolName[p]; -ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; -ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; - -(* Change Symbol[indexNameNUMBEROLD] to Symbol[indexNameNUMBERNEW] *) -ChangeIndexNumber[index_Symbol, number_Integer] := Symbol @ StringReplace[ToString[index], - Shortest[name__] ~~ NumberString :> name ~~ ToString[number]]; - -(* Returns the rules to change p[{iN,jN,kN}] to p[{iM,jM,kM}] *) -IndexReplacementRulesForNewParticleIndexNumber[particle_, number_Integer] := - ((# -> ChangeIndexNumber[#, number] &) /@ Vertices`FieldIndexList[particle]); - -(* Returns the rules that are needed to change order of a prticle list. - i.e turn {p1[{i1,j1,k1}], p2[{l2,m2,n2}]} to {p2[{l1,m1,n1}], p1[{i2,j2,k2}]} - For some reason SARAH expects the indices to always be in that order... *) -IndexReplacementRulesForParticleReordering[particles_List, ordering_] := -Module[{indices = Table[i, {i, Length[particles]}], index, fieldIndexList}, - Flatten[(IndexReplacementRulesForNewParticleIndexNumber[particles[[ordering[[#]]]], #] &) /@ indices]]; - -(* Perform the actual transformation initiated by IndexReplacementRulesForParticleReordering[] *) -OrderParticles[particles_List, ordering_] := Module[{indexRules}, - indexRules = IndexReplacementRulesForParticleReordering[particles, ordering]; - Return[particles[[ordering]] /. indexRules]; - ]; - -(* Essentially the same as above, but using the obtained rules, - transform a whole vertex expression, as returned by SARAH`Vertex[] *) -OrderVertex[vertex_, ordering_] := - Module[{indexRules, particles, expr, newVertex}, - indexRules = IndexReplacementRulesForParticleReordering[vertex[[1]], ordering]; - - particles = vertex[[1]][[ordering]]; - expr = vertex[[2;;]]; - - newVertex = (Join[{particles}, expr] /. indexRules); - Return[newVertex]; - ]; - -(* MemoizingVertex[] works just like SARAH`Vertex[], but it caches the results *) -(* MemoizingVertex[] only works when __no__ indices are specified!!! *) -(* Use of memoization gives ~30% speedup for the MSSM! *) -memoizedVertices = {}; -MemoizingVertex[particles_List, options : OptionsPattern[SARAH`Vertex]] := - Module[{memo, ordering, orderedParticles}, - (* First we sort the particles *) - ordering = Ordering[particles]; - orderedParticles = particles[[ordering]]; - - memo = Select[memoizedVertices, MatchesMemoizedVertex[orderedParticles], 1]; - If[memo =!= {}, memo = memo[[1]], - (* Create a new entry *) - memo = SARAH`Vertex[orderedParticles, options]; - AppendTo[memoizedVertices, memo];]; - - (* Now return the particles to their original order *) - memo = OrderVertex[memo, Ordering[ordering]]; - Return[memo]]; - -MatchesMemoizedVertex[particles_List][vertex_] := MatchQ[particles, Vertices`StripFieldIndices /@ vertex[[1]]]; - -(* Test whether a SARAH Vertex[] result is nonzero (exact) *) -IsNonZeroVertex[v_] := MemberQ[v[[2 ;;]][[All, 1]], Except[0]]; - -(* Returns the name of the coupling function that FlexibleSUSY generates for - a specific vertex in a canonical order! *) -NameOfCouplingFunction[particles_List] := -((* FIXME: Not upwards compatible if naming conventions change *) - "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); - -(********************** End helper routines **************************) - -(* The different vertex types that are supported. - They have the same names as their c++ counterparts. *) -vertexTypes = { - SingleComponentedVertex, - LeftAndRightComponentedVertex -}; - -(* The different diagram types that should be taken into consideration *) -(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) -(* There is no bounds check done on the integers, so they have to fit - into a standard c++ unsigned (!) int *) -contributingDiagramTypes = { - OneLoopDiagram[0], - OneLoopDiagram[1] -}; - -(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) ->>>>>>> Implemented ContributingDiagrams[] (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, From 12b688d6d1e3403279521cfbfe3395b14b7caad9 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 19:49:14 +0100 Subject: [PATCH 105/158] Fixed lots of problems in CachedVertex[]. --- meta/EDM.m | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 9859ba285..209b64f82 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -181,20 +181,6 @@ If you add new kinds of vertices (e.g for new diagram types): CXXNameOfField[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; CXXNameOfField[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -(**************** Other Functions ***************) - -AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; -AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; -AddIndexPattern[field_] := SARAH`getFull[SARAH`getBlank[field]] /. subIndexPattern; - -CachedVertex[fields_List] := -Module[{ - vertexPattern = Alternatives @@ ({#, ___} &) /@ - Permutations[AddIndexPattern /@ fields], - vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[fields]]}, - FirstCase[vertexList, vertexPattern] - ]; - CreateEvaluationContextSpecializations[] := Module[{fields, code}, fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; @@ -255,8 +241,6 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - - (* TODO: Add every permutation of the above vertices *) {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); From 824005185e6ec605cec0febad5ca56f680261415 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:04:16 +0100 Subject: [PATCH 106/158] Rewrote CreateVertexFunction[] --- meta/EDM.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta/EDM.m b/meta/EDM.m index 209b64f82..3d3bda93a 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -241,6 +241,8 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; + + (* TODO: Add every permutation of the above vertices *) {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); From 4a226909045d0beb366ad52e61f170a19a046b3c Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 5 Nov 2016 20:13:02 +0100 Subject: [PATCH 107/158] First steps towards integrating the EDM module. --- meta/FlexibleSUSY.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 5e7af59bf..c408fe0d6 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1451,7 +1451,6 @@ corresponding tadpole is real or imaginary (only in models with CP EDM`SetEDMFields[edmParticles]; fields = EDM`CreateFields[]; - chargeGetters = EDM`CreateChargeGetters[]; diagrams = EDM`CreateDiagrams[]; @@ -2024,6 +2023,9 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; +(* Get all nPointFunctions that EDM needs *) +PrepareEDM[] := EDM`NPointFunctions[]; + PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2171,7 +2173,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, + gmm2Vertices = {}, edmVertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2218,6 +2220,8 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; + (* EDM vertices *) + edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; From 50358601dea23cf1074626c0e41b3b04b80b0759 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 7 Nov 2016 16:31:07 +0100 Subject: [PATCH 108/158] Some small fixes --- meta/EDM.m | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 3d3bda93a..960ef478d 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -93,6 +93,7 @@ If you add new kinds of vertices (e.g for new diagram types): "\n\n"] CreateDiagrams[] := +<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc Module[{diagramSubIndices, diagramTypeHeads, code}, code = StringJoin @ Riffle[(Module[{diagramType = #}, @@ -115,6 +116,21 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +======= + Module[{diagramTypes, diagramTypeHeads, code}, + diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); + + code = "// The different diagram types that contribute to the muon magnetic moment\n"; + code = (code <> + StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) + /@ diagramHeads, "\n"] <> + "\n\n"); + + code = (code <> "// Indexed diagram types\n" <> + StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> + "<" <> ToString @ #[[1]] <> "> {};" &) + /@ contributingDiagramTypes, "\n"]); +>>>>>>> Some small fixes CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; @@ -195,7 +211,75 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) +======= +(************************ Begin helper routines *******************************) + +GetPhoton[] := SARAH`Photon; + +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; +SetAttributes[StripLorentzIndices, {Listable}]; + +(* Return a string corresponding to the c++ class name of the particle. + Note that "bar" and "conj" get turned into anti<...>::type! *) +ParticleToCXXName[p_] := SymbolName[p]; +ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; + +(* Return a string corresponding to the name of the particle. + Note that "bar" and "conj" are left as they are! *) +ParticleToSARAHString[p_] := SymbolName[p]; +ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; +ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; + +subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); +AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; +AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; +AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; + +CachedVertex[particles_List] := + Module[{ + vertexPattern = Alternatives @@ ({#, ___} &) /@ + Permutations[AddIndexPattern /@ particles], + vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, + FirstCase[vertexList, vertexPattern] + ]; + +(* Returns the name of the coupling function that FlexibleSUSY generates for + a specific vertex in a canonical order! *) +NameOfCouplingFunction[particles_List] := +((* FIXME: Not upwards compatible if naming conventions change *) + "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); + +(********************** End helper routines **************************) + +(* The different vertex types that are supported. + They have the same names as their c++ counterparts. *) +vertexTypes = { + SingleComponentedVertex, + LeftAndRightComponentedVertex +}; + +(* The different diagram types that should be taken into consideration *) +(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) +(* There is no bounds check done on the integers, so they have to fit + into a standard c++ unsigned (!) int *) +contributingDiagramTypes = { + OneLoopDiagram[0] +}; + +(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) +>>>>>>> Some small fixes (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, @@ -282,7 +366,6 @@ If you add new kinds of vertices (e.g for new diagram types): CouplingsForFields[fields_List] := Module[{vertexType, couplings}, vertexType = VertexTypeForFields[fields]; - couplings = {SARAH`Cp @@ fields}; Switch[vertexType, From 6fd36be7bba92d7bdcde58d2bb861ae5c0994802 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 14 Nov 2016 22:13:09 +0100 Subject: [PATCH 109/158] Too much to describe... --- meta/EDM.m | 90 +----------------------------------------------------- 1 file changed, 1 insertion(+), 89 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 960ef478d..e25ff961d 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -5,7 +5,6 @@ Initialize::usage="Initialize the EDM module."; SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; - CreateFields::usage="Returns the c++ code that contains all field fields"; CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM fields."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; @@ -93,9 +92,7 @@ If you add new kinds of vertices (e.g for new diagram types): "\n\n"] CreateDiagrams[] := -<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc -Module[{diagramSubIndices, diagramTypeHeads, code}, - +Module[{code}, code = StringJoin @ Riffle[(Module[{diagramType = #}, "template class " <> SymbolName[diagramType] <> ";\n" <> StringJoin @ Riffle[("template<> class " <> SymbolName[diagramType] <> @@ -116,21 +113,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -======= - Module[{diagramTypes, diagramTypeHeads, code}, - diagramHeads = DeleteDuplicates @ (Head /@ contributingDiagramTypes); - - code = "// The different diagram types that contribute to the muon magnetic moment\n"; - code = (code <> - StringJoin @ Riffle[("template class " <> SymbolName[#] <> ";" &) - /@ diagramHeads, "\n"] <> - "\n\n"); - - code = (code <> "// Indexed diagram types\n" <> - StringJoin @ Riffle[("template<> class " <> SymbolName[Head[#]] <> - "<" <> ToString @ #[[1]] <> "> {};" &) - /@ contributingDiagramTypes, "\n"]); ->>>>>>> Some small fixes CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; @@ -211,75 +193,7 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -<<<<<<< 76e431123ca4f745441461ea5d26d0c9858066bc (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) -======= -(************************ Begin helper routines *******************************) - -GetPhoton[] := SARAH`Photon; - -IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; - -StripLorentzIndices[p_Symbol] := p; -StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; -StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; -StripLorentzIndices[p_] := Module[{remainingIndices}, - remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; - If[Length[remainingIndices] === 0, Head[p], - Head[p][remainingIndices]] - ]; -SetAttributes[StripLorentzIndices, {Listable}]; - -(* Return a string corresponding to the c++ class name of the particle. - Note that "bar" and "conj" get turned into anti<...>::type! *) -ParticleToCXXName[p_] := SymbolName[p]; -ParticleToCXXName[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; -ParticleToCXXName[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; - -(* Return a string corresponding to the name of the particle. - Note that "bar" and "conj" are left as they are! *) -ParticleToSARAHString[p_] := SymbolName[p]; -ParticleToSARAHString[SARAH`bar[p_]] := "bar" <> SymbolName[p]; -ParticleToSARAHString[Susyno`LieGroups`conj[p_]] := "conj" <> SymbolName[p]; - -subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___); -AddIndexPattern[SARAH`bar[p_]] := SARAH`bar[AddIndexPattern[p]]; -AddIndexPattern[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[AddIndexPattern[p]]; -AddIndexPattern[particle_] := SARAH`getFull[SARAH`getBlank[particle]] /. subIndexPattern; - -CachedVertex[particles_List] := - Module[{ - vertexPattern = Alternatives @@ ({#, ___} &) /@ - Permutations[AddIndexPattern /@ particles], - vertexList = Symbol["SARAH`VertexList" <> ToString @ Length[particles]]}, - FirstCase[vertexList, vertexPattern] - ]; - -(* Returns the name of the coupling function that FlexibleSUSY generates for - a specific vertex in a canonical order! *) -NameOfCouplingFunction[particles_List] := -((* FIXME: Not upwards compatible if naming conventions change *) - "Cp" <> StringJoin @ (ParticleToSARAHString /@ Sort[particles])); - -(********************** End helper routines **************************) - -(* The different vertex types that are supported. - They have the same names as their c++ counterparts. *) -vertexTypes = { - SingleComponentedVertex, - LeftAndRightComponentedVertex -}; - -(* The different diagram types that should be taken into consideration *) -(* They need to be called DIAGRAMTYPENAME[_Integer]! See CreateDiagramClasses[] below. *) -(* There is no bounds check done on the integers, so they have to fit - into a standard c++ unsigned (!) int *) -contributingDiagramTypes = { - OneLoopDiagram[0] -}; - -(* Find all diagrams of the type type_, testing all corresponding combinations of particles *) ->>>>>>> Some small fixes (* IMPORTANT: Return value should have the format {{edmField1, {Diagram[DIAGRAMTYPENAME[_Integer], Fields___], Diagram[...], ...}}, {edmField2, {...}}, @@ -374,8 +288,6 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (* Creates the actual c++ code for a vertex with given fields. - If the c++ for the field list has already been created, two - empty strings are returned. This involves creating the VertexFunctionData<> code as well as the VertexFunction<> code. You should never need to change this code! *) CreateVertexFunction[fields_List, vertexRules_List] := From cee2a0f51b80ef91718580bf57ecb7ad358f279f Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 12:58:04 +0100 Subject: [PATCH 110/158] Preparing for first run. --- meta/FlexibleSUSY.m | 2 +- templates/edm.cpp.in | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index c408fe0d6..6f40f96db 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,7 +2024,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := EDM`NPointFunctions[]; +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 52670ec48..f4111b3c0 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -123,7 +123,6 @@ struct make_array } }; - /** * @class IndexBounds * @brief A class representing multiple (N) index ranges. From 4d76751ea1e385048b9b14236cafe5ee7062a020 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:02:39 +0100 Subject: [PATCH 111/158] Fixed Typo --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index e25ff961d..54145e591 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -461,7 +461,7 @@ If you add new kinds of vertices (e.g for new diagram types): If[SARAH`VertexList3 =!= List || Length[SARAH`VertexList3] === 0, SA`CurrentStates = FlexibleSUSY`FSEigenstates; SARAH`InitVertexCalculation[FlexibleSUSY`FSEigenstates, False]; - SARAH`ReadVertexList[FSEigenstates`FSEigenstates, False, False, True]; + SARAH`ReadVertexList[FlexibleSUSY`FSEigenstates, False, False, True]; SARAH`MakeCouplingLists; ]; ]; From 2c4ebdbbdb71d1d718d681aee89b2ff945af1f0c Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:43:59 +0100 Subject: [PATCH 112/158] Added edm as build template. Lots of small codegen fixes. --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 6f40f96db..22e744aac 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,7 +2024,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[];) +PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, From a235b9fdaf16c2977d3421f8c40c0da027e530fd Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 13:57:55 +0100 Subject: [PATCH 113/158] Fixed a dependency on a SARAH symbol that is only available after SARAH`Start[]. --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 22e744aac..23c2d725d 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2024,7 +2024,7 @@ corresponding tadpole is real or imaginary (only in models with CP PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; (* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); +PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, From 855a2b3faabe530f39d372b67aacb7a27770cfc3 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 15:34:31 +0100 Subject: [PATCH 114/158] Fixed scoping issues. --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 54145e591..c7f190326 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -474,6 +474,6 @@ If you add new kinds of vertices (e.g for new diagram types): ">" &) /@ #[[2]]) } &) /@ ContributingDiagrams[]; -(* TODO: End[]; *) +End[]; EndPackage[]; From af3107caec7e7bde5d0376eaab4c85b5a1e6a1d4 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:44:50 +0100 Subject: [PATCH 115/158] Moved Vertex logic to a place where the vertex files definitely exist. --- meta/FlexibleSUSY.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 23c2d725d..18b06f3c4 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -2023,9 +2023,6 @@ corresponding tadpole is real or imaginary (only in models with CP (* Get all nPointFunctions that GMM2 needs *) PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; -(* Get all nPointFunctions that EDM needs *) -PrepareEDM[] := (EDM`Initialize[]; EDM`SetEDMFields[{SARAH`Electron}]; EDM`NPointFunctions[]); - PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, nonMixedParticlesFile = SearchUnrotatedParticles[$sarahCurrentOutputMainDir, eigenstates]; @@ -2173,7 +2170,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, edmVertices = {}, + gmm2Vertices = {}, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2220,8 +2217,6 @@ corresponding tadpole is real or imaginary (only in models with CP Join[PrepareSelfEnergies[FSEigenstates], PrepareTadpoles[FSEigenstates]]; (* GMM2 vertices *) gmm2Vertices = StripInvalidFieldIndices @ PrepareGMuonMinus2[]; - (* EDM vertices *) - edmVertices = StripInvalidFieldIndices @ PrepareEDM[]; PrepareUnrotatedParticles[FSEigenstates]; DebugPrint["particles (mass eigenstates): ", GetParticles[]]; @@ -2731,10 +2726,17 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; +<<<<<<< 367d2fb1e47420799045d314a2f65870790d20ee Put[vertexRules = Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; +======= + Put[vertexRules = + Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], + vertexRuleFileName], + vertexRules = Get[vertexRuleFileName]; +>>>>>>> Moved Vertex logic to a place where the vertex files definitely exist. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; From 633edffd24bbe194453d7cc43b8a12b42d7a8eb2 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 21 Nov 2016 17:45:19 +0100 Subject: [PATCH 116/158] Fixed typos. --- templates/edm.cpp.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index f4111b3c0..14ab68121 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -381,6 +381,8 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; public: + using index_bounds = typename Data::index_bounds; + using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; /** From 8123516f1d1e1f78c110ec65a26938c06855022d Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 22 Nov 2016 15:46:58 +0100 Subject: [PATCH 117/158] Some simplifications due to better c++11 support (constexpr). --- templates/edm.cpp.in | 2 -- 1 file changed, 2 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 14ab68121..f4111b3c0 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -381,8 +381,6 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; public: - using index_bounds = typename Data::index_bounds; - using indices_type = typename index_bounds::indices_type; using vertex_type = typename Data::vertex_type; /** From c4ec7af770e0287c845457d5f3378359d50860ea Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 16:32:26 +0100 Subject: [PATCH 118/158] Implemented EDM calculation function. --- templates/edm.cpp.in | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index f4111b3c0..b50c38d48 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -43,6 +43,8 @@ using namespace flexiblesusy; namespace { +static constexpr oneOver16PiSquared = 0.0063325739776461107152; + /** \brief Helper template for utils::make_array */ template @@ -556,6 +558,7 @@ double OneLoopFunctionF2N(double x) @EDM_Definitions@ +// PhotonEmitter is the fermion template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField @@ -563,10 +566,45 @@ double DiagramEvaluator, { double res = 0.0; + using FermionVertex = VertexFunction< + EDMField, + typename anti::type, + typename anti::type + >; + + for( auto indexIt = FermionVertex::indexBounds().begin(), + indexIt != FermionVertex::indexBounds().end(); + ++indexIt ) + { + constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); + constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); + auto &vertex = FermionVertex::vertex(*indexIt, context); + + auto photonEmitterMass = context.mass( photonEmitterIndices ); + auto exchangeFieldMass = context.mass( exchangeFieldIndices ); + + constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + + constexpr double numericFactor = oneOver16PiSquared; + double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); + double couplingFactor = (std::conj( vertex.right() ) * vertex.left()).imag(); + + double massRatioSquared = photonEmitterMass/exchangeFieldMass; + massRatioSquared *= massRatioSquared; + + double loopFactor = (photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ) + + exchangeFieldChargeCount * OneLoopFunctionB( massRatioSquared )); + + double contribution = numericFactor * massFactor * couplingFactor * loopFactor; + + res += contribution; + } return res; } +// ExchangeField is fermion template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField @@ -574,7 +612,40 @@ double DiagramEvaluator, { double res = 0.0; + using FermionVertex = VertexFunction< + EDMField, + typename anti::type, + typename anti::type + >; + + for( auto indexIt = FermionVertex::indexBounds().begin(), + indexIt != FermionVertex::indexBounds().end(); + ++indexIt ) + { + constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); + constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); + auto &vertex = FermionVertex::vertex(*indexIt, context); + + auto photonEmitterMass = context.mass( photonEmitterIndices ); + auto exchangeFieldMass = context.mass( exchangeFieldIndices ); + + constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + constexpr double numericFactor = oneOver16PiSquared; + double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); + double couplingFactor = (std::conj( vertex.right() ) * vertex.left()).imag(); + + double massRatioSquared = exchangeFieldMass / photonEmitterMass; + massRatioSquared *= massRatioSquared; + + double loopFactor = (exchangeFieldChargeCount * OneLoopFunctionA( massRatioSquared ) + + photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared )); + + double contribution = numericFactor * massFactor * couplingFactor * loopFactor; + + res += contribution; + } return res; } From c236da5c244157447a1e9771c3b09090a071e8fe Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 16:53:47 +0100 Subject: [PATCH 119/158] Implemented One Loop Functions --- templates/edm.cpp.in | 147 ++++++++++++------------------------------- 1 file changed, 41 insertions(+), 106 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index b50c38d48..c3bc27c73 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -437,125 +437,60 @@ double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstate namespace { /** * @defgroup LoopFunctions -* @brief The loop functions necessary for \f$a_\mu\f$ one-loop calculations. +* @brief The loop functions necessary for edm one-loop calculations. * -* These are OneLoopFunctionF1C(), OneLoopFunctionF2C(), -* OneLoopFunctionF1N() and OneLoopFunctionF2N() -* as specified in arXiv:1311.1775 +* These are OneLoopFunctionA(), OneLoopFunctionB() +* as specified in arXiv:0808.1819 */ -double OneLoopFunctionF1C(double x) +constexpr double OneLoopFunctionA(double r) { - if (is_zero(x)) - return 4.0; - - // error around x=1 is <= 10^-12 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.21) { - return (1.0000000000000000000 - - 0.60000000000000000000 * y + - 0.40000000000000000000 * y * y - - 0.28571428571428571429 * y * y * y + - 0.21428571428571428571 * y * y * y * y - - 0.16666666666666666667 * y * y * y * y * y + - 0.13333333333333333333 * y * y * y * y * y * y - - 0.10909090909090909091 * y * y * y * y * y * y * y + - 0.090909090909090909091 * y * y * y * y * y * y * y * y - - 0.076923076923076923077 * y * y * y * y * y * y * y * y * y + - 0.065934065934065934066 * y * y * y * y * y * y * y * y * y * y - - 0.057142857142857142857 * y * y * y * y * y * y * y * y * y * y * y + - 0.050000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.044117647058823529412 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.039215686274509803922 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.035087719298245614035 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + if( is_zero(r) ) + return std::numeric_limits::infinity(); + + const double d = r - 1.0; + + if( std::abs(d) < 0.15 ) { + return (-0.33333333333333333333 + + 0.25000000000000000000 * d - + 0.20000000000000000000 * d * d + + 0.16666666666666666667 * d * d * d - + 0.14285714285714285714 * d * d * d * d + + 0.12500000000000000000 * d * d * d * d * d - + 0.11111111111111111111 * d * d * d * d * d * d + + 0.10000000000000000000 * d * d * d * d * d * d * d - + 0.090909090909090909091 * d * d * d * d * d * d * d * d + + 0.083333333333333333333 * d * d * d * d * d * d * d * d * d - + 0.076923076923076923077 * d * d * d * d * d * d * d * d * d * d ); } - return 2.0 / (y * y * y * y) * (2.0 + 3.0 * x - 6.0 * x * x + x * x * x + 6.0 * x * std::log(x)); + return 1.0 / (2.0 * d * d) * (3.0 - r + 2.0 * std::log(r) / d); } -double OneLoopFunctionF2C(double x) +double OneLoopFunctionB(double x) { - // error around x=1 is <= 10^-13 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.155) - return (1.0 - 0.75 * y + 0.6 * y * y - - 0.50000000000000000000 * y * y * y + - 0.4285714285714285714 * y * y * y * y - - 0.37500000000000000000 * y * y * y * y * y + - 0.33333333333333333333 * y * y * y * y * y * y - - 0.3000000000000000000 * y * y * y * y * y * y * y + - 0.2727272727272727273 * y * y * y * y * y * y * y * y - - 0.2500000000000000000 * y * y * y * y * y * y * y * y * y + - 0.23076923076923076923 * y * y * y * y * y * y * y * y * y * y - - 0.21428571428571428571 * y * y * y * y * y * y * y * y * y * y * y + - 0.2000000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.1875000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.1764705882352941176 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.16666666666666666667 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); + if( is_zero(r) ) + return 1.0/2.0; + + const double d = r - 1.0; + + if( std::abs(y) < 0.15 ) + return (0.16666666666666666667 - + 0.083333333333333333333 * d + + 0.050000000000000000000 * d * d - + 0.033333333333333333333 * d * d * d + + 0.023809523809523809524 * d * d * d * d - + 0.017857142857142857143 * d * d * d * d * d + + 0.013888888888888888889 * d * d * d * d * d * d - + 0.011111111111111111111 * d * d * d * d * d * d * d + + 0.0090909090909090909091 * d * d * d * d * d * d * d * d - + 0.0075757575757575757576 * d * d * d * d * d * d * d * d * d + + 0.0064102564102564102564 * d * d * d * d * d * d * d * d * d * d ); +); return -3.0 / (2.0 * y * y * y) * (-3.0 + 4.0 * x - x * x - 2.0 * std::log(x)); } -double OneLoopFunctionF1N(double x) -{ - if (is_zero(x)) - return 2.0; - - // error around x=1 is <= 10^-12 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.23) - return (1.0000000000000000000 - - 0.4000000000000000000 * y + - 0.2000000000000000000 * y * y - - 0.11428571428571428571 * y * y * y + - 0.07142857142857142857 * y * y * y * y - - 0.04761904761904761905 * y * y * y * y * y + - 0.03333333333333333333 * y * y * y * y * y * y - - 0.02424242424242424242 * y * y * y * y * y * y * y + - 0.0181818181818181818 * y * y * y * y * y * y * y * y - - 0.01398601398601398601 * y * y * y * y * y * y * y * y * y + - 0.01098901098901098901 * y * y * y * y * y * y * y * y * y * y - - 0.0087912087912087912 * y * y * y * y * y * y * y * y * y * y * y + - 0.00714285714285714286 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.0058823529411764706 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.0049019607843137255 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.0041279669762641899 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); - - return 2.0 / (y * y * y * y) * (1.0 - 6.0 * x + 3.0 * x * x + 2.0 * x * x * x - 6.0 * x * x * std::log(x)); -} - -double OneLoopFunctionF2N(double x) -{ - if (is_zero(x)) - return 3.0; - - // error around x=1 is <= 10^-13 on an intel i7 - const double y = x - 1.0; - - if (std::abs(y) < 0.185) - return (1.0000000000000000000 - - 0.50000000000000000000 * y + - 0.30000000000000000000 * y * y - - 0.2000000000000000000 * y * y * y + - 0.14285714285714285714 * y * y * y * y - - 0.10714285714285714286 * y * y * y * y * y + - 0.08333333333333333333 * y * y * y * y * y * y - - 0.06666666666666666667 * y * y * y * y * y * y * y + - 0.05454545454545454545 * y * y * y * y * y * y * y * y - - 0.0454545454545454545 * y * y * y * y * y * y * y * y * y + - 0.0384615384615384615 * y * y * y * y * y * y * y * y * y * y - - 0.03296703296703296703 * y * y * y * y * y * y * y * y * y * y * y + - 0.0285714285714285714 * y * y * y * y * y * y * y * y * y * y * y * y - - 0.02500000000000000000 * y * y * y * y * y * y * y * y * y * y * y * y * y + - 0.0220588235294117647 * y * y * y * y * y * y * y * y * y * y * y * y * y * y - - 0.0196078431372549020 * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y); - - return -3.0 / (y * y * y) * (1.0 - x * x + 2.0 * x * std::log(x)); -} - @EDM_Definitions@ // PhotonEmitter is the fermion From 5d721b4f107e5dc9898206653f694a75b2b3ec41 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 18:27:47 +0100 Subject: [PATCH 120/158] Implemented charge getters. --- meta/EDM.m | 105 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 29 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index c7f190326..c89350722 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -62,34 +62,72 @@ If you add new kinds of vertices (e.g for new diagram types): "anti<" <> CXXNameOfField[#] <> ">" <> " { using type = " <> CXXNameOfField[#] <> "; };" &) /@ Select[fields, (# == SARAH`AntiField[#] &)], - "\n"] + "\n"] <> "\n\n" <> + + "template struct field_indices;\n\n" <> + + StringJoin @ Riffle[("template<> struct field_indices<" <> + CXXNameOfField[#] <> ">\n" <> + "{\n" <> + IndentText @ + ("using type = std::array + ToString @ Length @ CleanFieldInfo[#][[5]] <> + ">;\n" + ) <> + "};\n" &) /@ fields, "\n"] ); Return[code]; ]; -CreateChargeGetters[] := -"template\n" <> -"double charge( EvaluationContext & );\n\n" <> -"template\n" <> -"double charge( unsigned, EvaluationContext & );\n\n" <> -StringJoin @ Riffle[(Module[{photonVertexFields, fieldDim = TreeMasses`GetDimension[#]}, - photonVertexFields = {SARAH`Photon, #, SARAH`AntiField[#]}; - "template<>\n" <> - "double charge<" <> CXXNameOfField[#] <> ">" <> - If[fieldDim === 1, "( ", - "( unsigned index, "] <> "EvaluationContext& context )\n{\n" <> - IndentText["using VF = VertexFunction<" <> - StringJoin @ Riffle[CXXNameOfField /@ photonVertexFields, ", "] <> - ">;\n" <> - If[fieldDim === 1, - "constexpr std::array indices{};\n", - "const std::array indices{ index, index };\n" - ] <> - "return VF::vertex(indices, context).left().real();" - ] <> "\n}" - ] &) /@ edmFields, - "\n\n"] +CreateChargeCountGetters[] := +Module[{contributingDiagrams, photonEmitters, + electronDimension = TreeMasses`GetDimension[SARAH`Electron]}, + contributingDiagrams = ContributingDiagrams[]; + photonEmitters = Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; + + "double electronCharge( EvaluationContext &context )\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> + ">;\n" <> + If[electronDimension === 1, + "constexpr std::array indices{};\n", + "constexpr std::array indices{" <> + ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" + ] <> + "return PhotonVertex::vertex( indices, context ).left().real();\n" + ) <> + "}\n\n" <> + "template\n" <> + "double chargeCount( const typename field_indices::type &, EvaluationContext & );\n\n" <> + StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], + photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], + numberOfIndices}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; + fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; + + numberOfIndices = Length @ fieldInfo[[5]]; + + "template<>\n" <> + "double chargeCount<" <> CXXNameOfField[#] <> + ">( const std::array ToString @ numberOfIndices <> + "> &indices, EvaluationContext &context )\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> + ">;\n\n" <> + "double fieldCharge = PhotonVertex::vertex( concat( indices, indices ), context )" <> + If[photonVertexType === SingleComponentedVertex, + ".value().real();\n", + ".left().real();\n"] <> + "double electronCharge = electronCharge( context );\n\n" <> + "return fieldCharge / electronCharge;\n" + ) <> + "}"] &) /@ photonEmitters, "\n\n"] + ]; CreateDiagrams[] := Module[{code}, @@ -179,6 +217,16 @@ If you add new kinds of vertices (e.g for new diagram types): CXXNameOfField[SARAH`bar[p_]] := "anti<" <> SymbolName[p] <> ">::type"; CXXNameOfField[Susyno`LieGroups`conj[p_]] := "anti<" <> SymbolName[p] <> ">::type"; +(**************** Other Functions ***************) + +GetElectronIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 1, Null]; + +CleanFieldInfo[field_] := Module[{fieldInfo = FirstCase[SARAH`Particles[FlexibleSUSY`FSEigenstates], + {SARAH`getParticleName @ field, ___}]}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {2}]; + DeleteCases[fieldInfo, {SARAH`lorentz, _}, {2}] + ]; + CreateEvaluationContextSpecializations[] := Module[{fields, code}, fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; @@ -251,9 +299,10 @@ If you add new kinds of vertices (e.g for new diagram types): (* Returns the vertices that are present in the specified diagram. This function should be overloaded for future diagram types. *) VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmField_, photonEmitter_, exchangeField_]] := - Module[{edmVertex}, + Module[{edmVertex, photonVertex}, edmVertex = {edmField, SARAH`AntiField[photonEmitter], SARAH`AntiField[exchangeField]}; - Return[{edmVertex}]; + photonVertex = {SARAH`Photon, photonEmitter, SARAH`AntiField[photonEmitter]}; + Return[{edmVertex, photonVertex}]; ]; (* Returns the vertex type for a vertex with a given list of fields *) @@ -370,7 +419,7 @@ If you add new kinds of vertices (e.g for new diagram types): ParseVertex[fields_List, vertexRules_List] := Module[{indexedFields, numberOfIndices, declareIndices, parsedVertex, vertexClassName, vertexFunctionBody, - sarahFields, fieldInfo, trIndexBounds, indexBounds, + fieldInfo, trIndexBounds, indexBounds, expr, exprL, exprR}, indexedFields = MapIndexed[(Module[{field = #1, index = #2[[1]]}, @@ -404,9 +453,7 @@ If you add new kinds of vertices (e.g for new diagram types): Parameters`ExpressionToString[exprR] <> ";\n\n" <> "return vertex_type(left, right);"]; - sarahFields = SARAH`getParticleName /@ fields; - fieldInfo = Flatten[(Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], {#, ___}] &) /@ - sarahFields, 1]; + fieldInfo = CleanFieldInfo /@ fields; trIndexBounds = Cases[Flatten[(With[{fieldIndex = #}, (If[#[[1]] === SARAH`generation, From 2c0ce6ca417c09ec13598b3efdb38dd93b8f0aaf Mon Sep 17 00:00:00 2001 From: iolojz Date: Sat, 3 Dec 2016 18:28:45 +0100 Subject: [PATCH 121/158] Renamed function --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 18b06f3c4..d75dd09c1 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1451,7 +1451,7 @@ corresponding tadpole is real or imaginary (only in models with CP EDM`SetEDMFields[edmParticles]; fields = EDM`CreateFields[]; - chargeGetters = EDM`CreateChargeGetters[]; + chargeGetters = EDM`CreateChargeCountGetters[]; diagrams = EDM`CreateDiagrams[]; vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; From e8ce9de7cfff6569d5299ceeb25d40d8ba2986fb Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 5 Dec 2016 13:01:58 +0100 Subject: [PATCH 122/158] Things should work now! --- meta/EDM.m | 143 +++++++++++++++++++++++-------------------- meta/FlexibleSUSY.m | 11 +--- templates/edm.cpp.in | 104 +++++++++++++++++++------------ 3 files changed, 143 insertions(+), 115 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index c89350722..a5f29f7f5 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -6,7 +6,6 @@ SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; CreateFields::usage="Returns the c++ code that contains all field fields"; -CreateChargeGetters::usage="Returns the c++ code that contains the charge functions for the different EDM fields."; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; CreateDefinitions::usage="Returns the c++ that contains all function definitions" @@ -80,55 +79,6 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateChargeCountGetters[] := -Module[{contributingDiagrams, photonEmitters, - electronDimension = TreeMasses`GetDimension[SARAH`Electron]}, - contributingDiagrams = ContributingDiagrams[]; - photonEmitters = Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; - - "double electronCharge( EvaluationContext &context )\n" <> - "{\n" <> - IndentText @ - ("using PhotonVertex = VertexFunction - CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> - ">;\n" <> - If[electronDimension === 1, - "constexpr std::array indices{};\n", - "constexpr std::array indices{" <> - ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" - ] <> - "return PhotonVertex::vertex( indices, context ).left().real();\n" - ) <> - "}\n\n" <> - "template\n" <> - "double chargeCount( const typename field_indices::type &, EvaluationContext & );\n\n" <> - StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], - photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], - numberOfIndices}, - fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; - fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; - - numberOfIndices = Length @ fieldInfo[[5]]; - - "template<>\n" <> - "double chargeCount<" <> CXXNameOfField[#] <> - ">( const std::array ToString @ numberOfIndices <> - "> &indices, EvaluationContext &context )\n" <> - "{\n" <> - IndentText @ - ("using PhotonVertex = VertexFunction - CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> - ">;\n\n" <> - "double fieldCharge = PhotonVertex::vertex( concat( indices, indices ), context )" <> - If[photonVertexType === SingleComponentedVertex, - ".value().real();\n", - ".left().real();\n"] <> - "double electronCharge = electronCharge( context );\n\n" <> - "return fieldCharge / electronCharge;\n" - ) <> - "}"] &) /@ photonEmitters, "\n\n"] - ]; - CreateDiagrams[] := Module[{code}, code = StringJoin @ Riffle[(Module[{diagramType = #}, @@ -155,8 +105,8 @@ If you add new kinds of vertices (e.g for new diagram types): CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; CreateDefinitions[vertexRules_List] := -(CreateEvaluationContextSpecializations[] <> "\n\n" <> - CreateVertices[vertexRules][[2]]); +(CreateVertices[vertexRules][[2]] <> "\n\n" <> + CreateEvaluationContextSpecializations[]); CreateCalculation[] := Module[{code, evaluators}, @@ -221,6 +171,17 @@ If you add new kinds of vertices (e.g for new diagram types): GetElectronIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 1, Null]; +IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; + +StripLorentzIndices[p_Symbol] := p; +StripLorentzIndices[SARAH`bar[p_]] := SARAH`bar[StripLorentzIndices[p]]; +StripLorentzIndices[Susyno`LieGroups`conj[p_]] := Susyno`LieGroups`conj[StripLorentzIndices[p]]; +StripLorentzIndices[p_] := Module[{remainingIndices}, + remainingIndices = Select[p[[1]], (!IsLorentzIndex[#] &)]; + If[Length[remainingIndices] === 0, Head[p], + Head[p][remainingIndices]] + ]; + CleanFieldInfo[field_] := Module[{fieldInfo = FirstCase[SARAH`Particles[FlexibleSUSY`FSEigenstates], {SARAH`getParticleName @ field, ___}]}, fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {2}]; @@ -228,17 +189,65 @@ If you add new kinds of vertices (e.g for new diagram types): ]; CreateEvaluationContextSpecializations[] := -Module[{fields, code}, +Module[{fields, contributingDiagrams, photonEmitters, + electronDimension = TreeMasses`GetDimension[SARAH`Electron]}, fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; + + contributingDiagrams = ContributingDiagrams[]; + photonEmitters = DeleteDuplicates @ Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; - code = (StringJoin @ - Riffle[("template<> double EvaluationContext::mass<" <> ToString[#] <> ">(" <> - If[TreeMasses`GetDimension[#] === 1, "", "unsigned index"] <> ") const\n" <> - "{ return model.get_M" <> CXXNameOfField[#] <> - If[TreeMasses`GetDimension[#] === 1, "()", "(index)"] <> "; }" - &) /@ fields, "\n\n"]); - - Return[code]; + StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], numberOfIndices}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; + fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; + + numberOfIndices = Length @ fieldInfo[[5]]; + + "template<> double EvaluationContext::mass<" <> ToString[#] <> + ">( const std::array ToString @ numberOfIndices <> + "> &indices ) const\n" <> + "{ return model.get_M" <> CXXNameOfField[#] <> + If[TreeMasses`GetDimension[#] === 1, "()", "( indices[0] )"] <> "; }" + ] &) /@ fields, "\n\n"] <> "\n\n" <> + + "double EvaluationContext::electronCharge( void ) const\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> + ">;\n" <> + If[electronDimension === 1, + "constexpr std::array indices{};\n", + "constexpr std::array indices{" <> + ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" + ] <> + "return PhotonVertex::vertex( indices, *this ).left().real();\n" + ) <> + "}\n\n" <> + + StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], + photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], + numberOfIndices}, + fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; + fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; + + numberOfIndices = Length @ fieldInfo[[5]]; + + "template<>\n" <> + "double EvaluationContext::chargeCount<" <> CXXNameOfField[#] <> + ">( const std::array ToString @ numberOfIndices <> + "> &indices ) const\n" <> + "{\n" <> + IndentText @ + ("using PhotonVertex = VertexFunction + CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> + ">;\n\n" <> + "double fieldCharge = PhotonVertex::vertex( concatenate( indices, indices ), *this )" <> + If[photonVertexType === SingleComponentedVertex, + ".value().real();\n", + ".left().real();\n"] <> + "return fieldCharge / electronCharge();\n" + ) <> + "}"] &) /@ photonEmitters, "\n\n"] ]; (* Find all diagrams of the type type_, testing all corresponding combinations of fields *) @@ -359,7 +368,7 @@ If you add new kinds of vertices (e.g for new diagram types): prototype = ("template<> struct " <> dataClassName <> "\n" <> "{\n" <> IndentText @ - ("constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> + ("static constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds" <> If[NumberOfIndices[parsedVertex] =!= 0, "= { " <> @@ -368,15 +377,15 @@ If you add new kinds of vertices (e.g for new diagram types): , ";/n" ] <> - "constexpr std::array ToString @ Length[fieldIndexStart] <> - "> fieldIndexStart = { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> - " };\n" <> + "static constexpr std::array ToString @ Length[fieldIndexStart] <> + "> fieldIndexStart = { { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + " } };\n" <> "using vertex_type = " <> VertexClassName[parsedVertex] <> ";\n" ) <> "};"); definition = ("template<> " <> functionClassName <> "::vertex_type\n" <> - functionClassName <> "::vertex(const indices_type &indices, EvaluationContext &context)\n" <> + functionClassName <> "::vertex(const indices_type &indices, const EvaluationContext &context)\n" <> "{\n" <> IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); @@ -425,6 +434,8 @@ If you add new kinds of vertices (e.g for new diagram types): index = #2[[1]]}, SARAH`getFull[#1] /. SARAH`subGC[index] /. SARAH`subIndFinal[index,index] ] &), fields]; + indexedFields = StripLorentzIndices /@ indexedFields; + numberOfIndices = ((Length @ Vertices`FieldIndexList[#] &) /@ indexedFields); declareIndices = DeclareIndices[indexedFields, "indices"]; diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index d75dd09c1..7a0edde97 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1445,13 +1445,12 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the EDM c++ files *) WriteEDMClass[vertexRules_List, files_List] := -Module[{fields, edmFields, chargeGetters, diagrams, vertexFunctionData, +Module[{fields, edmFields, diagrams, vertexFunctionData, definitions, calculationCode}, edmFields = {SARAH`Electron}; EDM`SetEDMFields[edmParticles]; fields = EDM`CreateFields[]; - chargeGetters = EDM`CreateChargeCountGetters[]; diagrams = EDM`CreateDiagrams[]; vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; @@ -1460,7 +1459,6 @@ corresponding tadpole is real or imaginary (only in models with CP WriteOut`ReplaceInFiles[files, { "@EDM_Fields@" -> fields, - "@EDM_ChargeGetters@" -> chargeGetters, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, @@ -2726,17 +2724,10 @@ corresponding tadpole is real or imaginary (only in models with CP EffectiveCouplings`InitializeEffectiveCouplings[], effectiveCouplingsFileName]; extraVertices = EffectiveCouplings`GetNeededVerticesList[effectiveCouplings]; -<<<<<<< 367d2fb1e47420799045d314a2f65870790d20ee Put[vertexRules = Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], vertexRuleFileName], vertexRules = Get[vertexRuleFileName]; -======= - Put[vertexRules = - Vertices`VertexRules[Join[nPointFunctions, gmm2Vertices, extraVertices], Lat$massMatrices], - vertexRuleFileName], - vertexRules = Get[vertexRuleFileName]; ->>>>>>> Moved Vertex logic to a place where the vertex files definitely exist. effectiveCouplings = Get[effectiveCouplingsFileName]; ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index c3bc27c73..ee524582f 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -33,8 +33,7 @@ #include #include -#include -#include +#include #define INPUTPARAMETER(p) context.model.get_input().p #define MODELPARAMETER(p) context.model.get_##p() @@ -43,9 +42,9 @@ using namespace flexiblesusy; namespace { -static constexpr oneOver16PiSquared = 0.0063325739776461107152; +static constexpr double oneOver16PiSquared = 0.0063325739776461107152; -/** \brief Helper template for utils::make_array +/** \brief Helper template for make_array */ template struct make_array_it @@ -80,12 +79,13 @@ struct make_array_it } }; -/** \brief Specialized helper template for utils::make_array */ +/** \brief Specialized helper template for make_array */ template struct make_array_it { template static auto iterate( ForwardIterator begin, Args &&...args ) + -> std::array { return std::array{ std::forward( args )... }; } @@ -114,6 +114,11 @@ struct make_array */ template static auto iterate( ForwardIterator begin ) + -> std::array::value, + typename std::iterator_traits::value_type, + T + >::type, N> { using value_type = typename std::conditional< std::is_void::value, @@ -121,10 +126,34 @@ struct make_array T >::type; - return detail::make_array_it::iterate( begin ); + return make_array_it::iterate( begin ); } }; +template +auto concatenate( const Array1 &a1, const Array2 &a2 ) +-> std::array< + typename std::common_type< + typename Array1::value_type, + typename Array1::value_type + >::type, + std::tuple_size::value + std::tuple_size::value> +{ + using value_type = typename std::common_type< + typename Array1::value_type, + typename Array1::value_type + >::type; + constexpr auto size = std::tuple_size::value + std::tuple_size::value; + + auto range1 = boost::make_iterator_range( boost::begin(a1), + boost::end(a1) ); + auto range2 = boost::make_iterator_range( boost::begin(a2), + boost::end(a2) ); + auto joined = boost::join( range1, range2 ); + + return make_array::iterate( boost::begin( joined ) ); +} + /** * @class IndexBounds * @brief A class representing multiple (N) index ranges. @@ -229,17 +258,16 @@ template struct IndexBounds { }; template<> struct IndexBounds<0> { - typedef const std::array indices_type; - typedef indices_type * const_iterator; + using indices_type = const std::array; + using const_iterator = indices_type *; - static const indices_type dummyIndex; + static constexpr indices_type dummyIndex{}; const_iterator begin() const { return &dummyIndex; } const_iterator end() const { return (begin()+1); } }; -IndexBounds<0>::indices_type IndexBounds<0>::dummyIndex{}; @EDM_Fields@ @@ -258,16 +286,16 @@ struct EvaluationContext { @ModelName@_mass_eigenstates& model; ///< The model object. /** - * @fn mass + * @fn mass * @brief Returns the mass of a field. */ - template double mass() const { - return mass::type>(); - } + template + double mass( const typename field_indices::type & ) const; - template double mass(unsigned index) const { - return mass::type>(index); - } + double electronCharge( void ) const; + + template + double chargeCount( const typename field_indices::type & ) const; }; /** @@ -289,8 +317,6 @@ double OneLoopFunctionF2C(double); double OneLoopFunctionF1N(double); double OneLoopFunctionF2N(double); -@EDM_ChargeGetters@ - @EDM_Diagrams@ /** @@ -384,6 +410,7 @@ template class VertexFunction { using Data = VertexFunctionData; public: using vertex_type = typename Data::vertex_type; + using indices_type = typename decltype(Data::index_bounds)::indices_type; /** * @fn indexBounds @@ -405,11 +432,11 @@ public: template static std::array - fieldIndices(const Data::index_bounds::indices_type &indices) + fieldIndices(const indices_type &indices) { constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; auto begin = indices.begin() + Data::fieldIndexStart[fieldIndex]; - return utils::make_array::iterate(begin); + return make_array::iterate(begin); } /** @@ -418,7 +445,7 @@ public: * @param indices The field indices * @param context The evaluation context */ - static vertex_type vertex(const indices_type &indices, EvaluationContext &context); + static vertex_type vertex(const indices_type &indices, const EvaluationContext &context); }; @EDM_VertexFunctionData@ @@ -443,7 +470,7 @@ namespace { * as specified in arXiv:0808.1819 */ -constexpr double OneLoopFunctionA(double r) +double OneLoopFunctionA(double r) { if( is_zero(r) ) return std::numeric_limits::infinity(); @@ -467,14 +494,14 @@ constexpr double OneLoopFunctionA(double r) return 1.0 / (2.0 * d * d) * (3.0 - r + 2.0 * std::log(r) / d); } -double OneLoopFunctionB(double x) +double OneLoopFunctionB(double r) { if( is_zero(r) ) return 1.0/2.0; const double d = r - 1.0; - if( std::abs(y) < 0.15 ) + if( std::abs(d) < 0.15 ) return (0.16666666666666666667 - 0.083333333333333333333 * d + 0.050000000000000000000 * d * d - @@ -486,9 +513,8 @@ double OneLoopFunctionB(double x) 0.0090909090909090909091 * d * d * d * d * d * d * d * d - 0.0075757575757575757576 * d * d * d * d * d * d * d * d * d + 0.0064102564102564102564 * d * d * d * d * d * d * d * d * d * d ); -); - return -3.0 / (2.0 * y * y * y) * (-3.0 + 4.0 * x - x * x - 2.0 * std::log(x)); + return 1.0 / (2.0 * d * d) * (1.0 + r + 2.0 * r * std::log(r) / d); } @EDM_Definitions@ @@ -507,19 +533,19 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(), + for( auto indexIt = FermionVertex::indexBounds().begin(); indexIt != FermionVertex::indexBounds().end(); ++indexIt ) { - constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); - constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); - auto &vertex = FermionVertex::vertex(*indexIt, context); + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); + auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); + auto vertex = FermionVertex::vertex(*indexIt, context); auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -553,19 +579,19 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(), + for( auto indexIt = FermionVertex::indexBounds().begin(); indexIt != FermionVertex::indexBounds().end(); ++indexIt ) { - constexpr auto photonEmitterIndices = FermionVertex::template particleIndices<1>(*indexIt); - constexpr auto exchangeFieldIndices = FermionVertex::template particleIndices<2>(*indexIt); - auto &vertex = FermionVertex::vertex(*indexIt, context); + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); + auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); + auto vertex = FermionVertex::vertex(*indexIt, context); auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - constexpr double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - constexpr double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); From ee5ff7f60f706440a52fd2c1d55e6fa4a15a9163 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 5 Dec 2016 13:32:48 +0100 Subject: [PATCH 123/158] Fixed scope issue --- templates/edm.cpp.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index ee524582f..0eef688f9 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -544,8 +544,8 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -590,8 +590,8 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = chargeCount( exchangeFieldIndices ); + double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); From 3c524410d46cd89cb1e15d42b586375925a6449f Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 6 Dec 2016 15:14:22 +0100 Subject: [PATCH 124/158] Fixed overcounting and linking issues. --- meta/EDM.m | 13 ++++++----- meta/FlexibleSUSY.m | 6 +++++ templates/edm.cpp.in | 53 +++++++++++++++++++++++--------------------- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index a5f29f7f5..e11971a20 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -95,7 +95,7 @@ If you add new kinds of vertices (e.g for new diagram types): "struct DiagramEvaluator<" <> SymbolName[diagramType] <> "<" <> ToString @ # <> ">, EDMField, PhotonEmitter, ExchangeField>\n" <> - "{ static double value(EvaluationContext& context); };" + "{ static double value(const typename field_indices::type &indices, EvaluationContext& context); };" &) /@ diagramSubTypes[diagramType], "\n\n"]] &) /@ diagramTypes, "\n\n"] ); @@ -112,15 +112,18 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{code, evaluators}, evaluators = ConcreteDiagramEvaluators[]; - code = "template double edm( CMSSM_mass_eigenstates& model );\n\n"; + code = "template double edm( const typename field_indices::type &indices, CMSSM_mass_eigenstates& model );\n\n"; code = (code <> StringJoin @ Riffle[Module[{field = #[[1]], fieldEvaluators = #[[2]]}, - "template<> double edm<" <> CXXNameOfField[field] <> ">( CMSSM_mass_eigenstates& model )\n" <> + "template<> double edm<" <> CXXNameOfField[field] <> + ">( const std::array ToString @ Length @ CleanFieldInfo[field][[5]] <> + "> &indices, CMSSM_mass_eigenstates& model )\n" <> "{\n" <> IndentText["EvaluationContext context{ model };\n" <> "double val = 0.0;\n\n" <> - StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(context);" &) /@ fieldEvaluators, "\n"] <> "\n\n" <> + StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(indices, context);" &) /@ fieldEvaluators, "\n"] <> + "\n\n" <> "return val;" ] <> "\n}"] & /@ evaluators, "\n\n"]); @@ -371,7 +374,7 @@ If you add new kinds of vertices (e.g for new diagram types): ("static constexpr IndexBounds<" <> ToString @ NumberOfIndices[parsedVertex] <> "> index_bounds" <> If[NumberOfIndices[parsedVertex] =!= 0, - "= { " <> + " = { " <> "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };\n" , diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 7a0edde97..e66f5e2a1 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1457,12 +1457,18 @@ corresponding tadpole is real or imaginary (only in models with CP definitions = EDM`CreateDefinitions[vertexRules]; calculationCode = EDM`CreateCalculation[]; + declareElectronIndices = If[electronDimension === 1, + "constexpr std::array electronIndices{};", + "constexpr std::array electronIndices{1};" + ]; + WriteOut`ReplaceInFiles[files, { "@EDM_Fields@" -> fields, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, "@EDM_Calculation@" -> calculationCode, + "@EDM_DeclareElectronIndices@" -> declareElectronIndices, Sequence @@ GeneralReplacementRules[] } ]; ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 0eef688f9..995940145 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -408,17 +408,14 @@ template struct VertexFunctionData; */ template class VertexFunction { using Data = VertexFunctionData; + using bounds_type = typename std::decay::type; + using fieldIndexStart_type = decltype(Data::fieldIndexStart); public: using vertex_type = typename Data::vertex_type; using indices_type = typename decltype(Data::index_bounds)::indices_type; - /** - * @fn indexBounds - * @brief Returns the IndexBounds<> object of the VertexFunction. - */ - static constexpr decltype(Data::index_bounds) indexBounds() { - return Data::index_bounds; - } + static constexpr bounds_type index_bounds = Data::index_bounds; + static constexpr fieldIndexStart_type fieldIndexStart = Data::fieldIndexStart; /** * @fn fieldIndices @@ -431,11 +428,11 @@ public: */ template static - std::array + std::array fieldIndices(const indices_type &indices) { - constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; - auto begin = indices.begin() + Data::fieldIndexStart[fieldIndex]; + constexpr auto length = fieldIndexStart[fieldIndex+1] - fieldIndexStart[fieldIndex]; + auto begin = indices.begin() + fieldIndexStart[fieldIndex]; return make_array::iterate(begin); } @@ -458,7 +455,9 @@ double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstate // make copy since model is modified via call to calculate_MFe_pole() @ModelName@_mass_eigenstates model(model_); - return edm( model ); + @EDM_DeclareElectronIndices@ + + return edm( electronIndices, model ); } namespace { @@ -523,7 +522,7 @@ double OneLoopFunctionB(double r) template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField ->::value(EvaluationContext &context) +>::value(const typename field_indices::type &indices, EvaluationContext &context) { double res = 0.0; @@ -533,10 +532,14 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(); - indexIt != FermionVertex::indexBounds().end(); - ++indexIt ) + constexpr auto indexBounds = FermionVertex::index_bounds; + for( auto indexIt = indexBounds.begin(); indexIt != indexBounds.end(); ++indexIt ) { + auto edmFieldIndices = FermionVertex::template fieldIndices<0>(*indexIt); + + if( edmFieldIndices != indices ) + continue; + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); auto vertex = FermionVertex::vertex(*indexIt, context); @@ -545,7 +548,6 @@ double DiagramEvaluator, auto exchangeFieldMass = context.mass( exchangeFieldIndices ); double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -554,8 +556,7 @@ double DiagramEvaluator, double massRatioSquared = photonEmitterMass/exchangeFieldMass; massRatioSquared *= massRatioSquared; - double loopFactor = (photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ) + - exchangeFieldChargeCount * OneLoopFunctionB( massRatioSquared )); + double loopFactor = photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; @@ -569,7 +570,7 @@ double DiagramEvaluator, template double DiagramEvaluator, EDMField, PhotonEmitter, ExchangeField ->::value(EvaluationContext &context) +>::value(const typename field_indices::type &indices, EvaluationContext &context) { double res = 0.0; @@ -579,10 +580,14 @@ double DiagramEvaluator, typename anti::type >; - for( auto indexIt = FermionVertex::indexBounds().begin(); - indexIt != FermionVertex::indexBounds().end(); - ++indexIt ) + constexpr auto indexBounds = FermionVertex::index_bounds; + for( auto indexIt = indexBounds.begin(); indexIt != indexBounds.end(); ++indexIt ) { + auto edmFieldIndices = FermionVertex::template fieldIndices<0>(*indexIt); + + if( edmFieldIndices != indices ) + continue; + auto photonEmitterIndices = FermionVertex::template fieldIndices<1>(*indexIt); auto exchangeFieldIndices = FermionVertex::template fieldIndices<2>(*indexIt); auto vertex = FermionVertex::vertex(*indexIt, context); @@ -591,7 +596,6 @@ double DiagramEvaluator, auto exchangeFieldMass = context.mass( exchangeFieldIndices ); double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); - double exchangeFieldChargeCount = context.chargeCount( exchangeFieldIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); @@ -600,8 +604,7 @@ double DiagramEvaluator, double massRatioSquared = exchangeFieldMass / photonEmitterMass; massRatioSquared *= massRatioSquared; - double loopFactor = (exchangeFieldChargeCount * OneLoopFunctionA( massRatioSquared ) + - photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared )); + double loopFactor = photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; From 179d377f423a3b1c0decfe22ddd4d20857422c97 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 13 Dec 2016 14:46:25 +0100 Subject: [PATCH 125/158] Fixed typo --- meta/FlexibleSUSY.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index e66f5e2a1..3789bbf51 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1448,7 +1448,7 @@ corresponding tadpole is real or imaginary (only in models with CP Module[{fields, edmFields, diagrams, vertexFunctionData, definitions, calculationCode}, edmFields = {SARAH`Electron}; - EDM`SetEDMFields[edmParticles]; + EDM`SetEDMFields[edmFields]; fields = EDM`CreateFields[]; diagrams = EDM`CreateDiagrams[]; From daff364f2753828f9a9a8a693f7843ed5e2d583e Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 13 Dec 2016 15:03:40 +0100 Subject: [PATCH 126/158] Removed confusing and unused code. --- meta/FlexibleSUSY.m | 3 --- 1 file changed, 3 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 3789bbf51..0657293ed 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1447,9 +1447,6 @@ corresponding tadpole is real or imaginary (only in models with CP WriteEDMClass[vertexRules_List, files_List] := Module[{fields, edmFields, diagrams, vertexFunctionData, definitions, calculationCode}, - edmFields = {SARAH`Electron}; - EDM`SetEDMFields[edmFields]; - fields = EDM`CreateFields[]; diagrams = EDM`CreateDiagrams[]; From f7b252dca8b3b640fe80db78071a3a4287a95ea3 Mon Sep 17 00:00:00 2001 From: iolojz Date: Tue, 20 Dec 2016 14:24:36 +0100 Subject: [PATCH 127/158] Changed the c++ EDM interface. --- meta/EDM.m | 90 ++++++++++++++++++++++++++++---------------- meta/FlexibleSUSY.m | 15 +++----- templates/edm.cpp.in | 12 +----- templates/edm.hpp.in | 8 +--- 4 files changed, 65 insertions(+), 60 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index e11971a20..ff304fac2 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -7,9 +7,9 @@ SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; CreateFields::usage="Returns the c++ code that contains all field fields"; CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; +CreateInterfaceFunctions::usage="Returns the c++ code containing the interface functions {prototypeCode, definitionCode}." CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; CreateDefinitions::usage="Returns the c++ that contains all function definitions" -CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; @@ -102,35 +102,69 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; +CreateInterfaceFunctions[] := +Module[{prototypes, definitions, evaluators}, + evaluators = ConcreteDiagramEvaluators[]; + + prototypes = ("namespace " <> FlexibleSUSY`FSModelName <> "_edm {\n" <> + StringJoin @ Riffle[("double calculate_edm_" <> CXXNameOfField[#] <> + "(" <> + If[TreeMasses`GetDimension[#] =!= 1, + " unsigned generationIndex, ", + " "] <> + "const " <> FlexibleSUSY`FSModelName <> "_mass_eigenstates& model );" + &) /@ edmFields, "\n"] <> + "\n}"); + + definitions = StringJoin @ Riffle[ + Module[{field = #[[1]], fieldEvaluators = #[[2]], + numberOfIndices}, + numberOfIndices = Length @ CleanFieldInfo[field][[5]]; + + "double " <> FlexibleSUSY`FSModelName <> "_edm::calculate_edm_" <> CXXNameOfField[field] <> + "(" <> + If[TreeMasses`GetDimension[field] =!= 1, + " unsigned generationIndex, ", + " "] <> + "const " <> FlexibleSUSY`FSModelName <> "_mass_eigenstates& model )\n" <> + "{\n" <> + IndentText @ + ("CMSSM_mass_eigenstates model_ = model;\n" <> + "EvaluationContext context{ model_ };\n" <> + "std::array + ToString @ numberOfIndices <> + "> indices = {" <> + If[TreeMasses`GetDimension[field] =!= 1, + " generationIndex" <> + If[numberOfIndices =!= 1, + StringJoin @ Table[", 1", {numberOfIndices-1}], + "" + ] <> " ", + If[numberOfIndices =!= 0, + StringJoin @ Riffle[Table[" 1", {numberOfIndices}], ","] <> " ", + "" + ] + ] <> + "};\n\n" <> + + "double val = 0.0;\n\n" <> + StringJoin @ Riffle[("val += " <> ToString @ # <> + "::value(indices, context);" + &) /@ fieldEvaluators, "\n"] <> + "\n\n" <> + "return val;" + ) <> + "\n}"] & /@ evaluators, "\n\n"]; + + Return[{prototypes, definitions}]; + ]; + CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; CreateDefinitions[vertexRules_List] := (CreateVertices[vertexRules][[2]] <> "\n\n" <> CreateEvaluationContextSpecializations[]); -CreateCalculation[] := -Module[{code, evaluators}, - evaluators = ConcreteDiagramEvaluators[]; - - code = "template double edm( const typename field_indices::type &indices, CMSSM_mass_eigenstates& model );\n\n"; - code = (code <> - StringJoin @ Riffle[Module[{field = #[[1]], - fieldEvaluators = #[[2]]}, - "template<> double edm<" <> CXXNameOfField[field] <> - ">( const std::array ToString @ Length @ CleanFieldInfo[field][[5]] <> - "> &indices, CMSSM_mass_eigenstates& model )\n" <> - "{\n" <> - IndentText["EvaluationContext context{ model };\n" <> - "double val = 0.0;\n\n" <> - StringJoin @ Riffle[("val += " <> ToString @ # <> "::value(indices, context);" &) /@ fieldEvaluators, "\n"] <> - "\n\n" <> - "return val;" - ] <> - "\n}"] & /@ evaluators, "\n\n"]); - - Return[code]; - ]; - NPointFunctions[] := Module[{contributingDiagrams, vertices}, contributingDiagrams = ContributingDiagrams[]; @@ -200,9 +234,6 @@ If you add new kinds of vertices (e.g for new diagram types): photonEmitters = DeleteDuplicates @ Flatten[contributingDiagrams[[All, 2]], 1][[All, 3]]; StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], numberOfIndices}, - fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; - fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; - numberOfIndices = Length @ fieldInfo[[5]]; "template<> double EvaluationContext::mass<" <> ToString[#] <> @@ -230,9 +261,6 @@ If you add new kinds of vertices (e.g for new diagram types): StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], numberOfIndices}, - fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {3}]; - fieldInfo = DeleteCases[fieldInfo, {SARAH`lorentz, _}, {3}]; - numberOfIndices = Length @ fieldInfo[[5]]; "template<>\n" <> @@ -300,8 +328,6 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - (* TODO: Add every permutation of the above vertices *) - {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 0657293ed..7505855b3 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1445,27 +1445,22 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the EDM c++ files *) WriteEDMClass[vertexRules_List, files_List] := -Module[{fields, edmFields, diagrams, vertexFunctionData, - definitions, calculationCode}, +Module[{fields, diagrams, interfaceFunctions, + vertexFunctionData, definitions}, fields = EDM`CreateFields[]; diagrams = EDM`CreateDiagrams[]; + interfaceFunctions = EDM`CreateInterfaceFunctions[]; vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; definitions = EDM`CreateDefinitions[vertexRules]; - calculationCode = EDM`CreateCalculation[]; - - declareElectronIndices = If[electronDimension === 1, - "constexpr std::array electronIndices{};", - "constexpr std::array electronIndices{1};" - ]; WriteOut`ReplaceInFiles[files, { "@EDM_Fields@" -> fields, "@EDM_Diagrams@" -> diagrams, "@EDM_VertexFunctionData@" -> vertexFunctionData, "@EDM_Definitions@" -> definitions, - "@EDM_Calculation@" -> calculationCode, - "@EDM_DeclareElectronIndices@" -> declareElectronIndices, + "@EDM_InterfaceFunctionPrototypes@" -> interfaceFunctions[[1]], + "@EDM_InterfaceFunctionDefinitions@" -> interfaceFunctions[[2]], Sequence @@ GeneralReplacementRules[] } ]; ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 995940145..9254b5e9f 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -448,17 +448,7 @@ public: @EDM_VertexFunctionData@ } -@EDM_Calculation@ - -double @ModelName@_edm::calculate_edm_electron(const @ModelName@_mass_eigenstates& model_) -{ - // make copy since model is modified via call to calculate_MFe_pole() - @ModelName@_mass_eigenstates model(model_); - - @EDM_DeclareElectronIndices@ - - return edm( electronIndices, model ); -} +@EDM_InterfaceFunctionDefinitions@ namespace { /** diff --git a/templates/edm.hpp.in b/templates/edm.hpp.in index 880373086..65712b80f 100644 --- a/templates/edm.hpp.in +++ b/templates/edm.hpp.in @@ -31,13 +31,7 @@ namespace flexiblesusy { class @ModelName@_mass_eigenstates; -namespace @ModelName@_edm { -/** -* @fn calculate_edm_electron -* @brief Calculates the electromagnetic dipole moment of the electron. -*/ -double calculate_edm_electron(const @ModelName@_mass_eigenstates& model); -} // namespace @ModelName@_edm +@EDM_InterfaceFunctionPrototypes@ } // namespace flexiblesusy #endif From 488c91948885c63ec0b1bce392bfe573c568a50d Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 2 Jan 2017 18:32:21 +0100 Subject: [PATCH 128/158] Changed edm units. --- meta/EDM.m | 19 ++----------------- templates/edm.cpp.in | 12 +++++------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index ff304fac2..eab0d91c4 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -243,28 +243,13 @@ If you add new kinds of vertices (e.g for new diagram types): If[TreeMasses`GetDimension[#] === 1, "()", "( indices[0] )"] <> "; }" ] &) /@ fields, "\n\n"] <> "\n\n" <> - "double EvaluationContext::electronCharge( void ) const\n" <> - "{\n" <> - IndentText @ - ("using PhotonVertex = VertexFunction - CXXNameOfField[SARAH`Electron] <> ", " <> CXXNameOfField[SARAH`AntiField @ SARAH`Electron] <> - ">;\n" <> - If[electronDimension === 1, - "constexpr std::array indices{};\n", - "constexpr std::array indices{" <> - ToString[GetElectronIndex[]-1] <> ", " <> ToString[GetElectronIndex[]-1] <> "};\n" - ] <> - "return PhotonVertex::vertex( indices, *this ).left().real();\n" - ) <> - "}\n\n" <> - StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], numberOfIndices}, numberOfIndices = Length @ fieldInfo[[5]]; "template<>\n" <> - "double EvaluationContext::chargeCount<" <> CXXNameOfField[#] <> + "double EvaluationContext::charge<" <> CXXNameOfField[#] <> ">( const std::array ToString @ numberOfIndices <> "> &indices ) const\n" <> "{\n" <> @@ -276,7 +261,7 @@ If you add new kinds of vertices (e.g for new diagram types): If[photonVertexType === SingleComponentedVertex, ".value().real();\n", ".left().real();\n"] <> - "return fieldCharge / electronCharge();\n" + "return fieldCharge;\n" ) <> "}"] &) /@ photonEmitters, "\n\n"] ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 9254b5e9f..ee62847ef 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -292,10 +292,8 @@ struct EvaluationContext { template double mass( const typename field_indices::type & ) const; - double electronCharge( void ) const; - template - double chargeCount( const typename field_indices::type & ) const; + double charge( const typename field_indices::type & ) const; }; /** @@ -537,7 +535,7 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double photonEmitterCharge = context.charge( photonEmitterIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = photonEmitterMass/(exchangeFieldMass * exchangeFieldMass); @@ -546,7 +544,7 @@ double DiagramEvaluator, double massRatioSquared = photonEmitterMass/exchangeFieldMass; massRatioSquared *= massRatioSquared; - double loopFactor = photonEmitterChargeCount * OneLoopFunctionA( massRatioSquared ); + double loopFactor = photonEmitterCharge * OneLoopFunctionA( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; @@ -585,7 +583,7 @@ double DiagramEvaluator, auto photonEmitterMass = context.mass( photonEmitterIndices ); auto exchangeFieldMass = context.mass( exchangeFieldIndices ); - double photonEmitterChargeCount = context.chargeCount( photonEmitterIndices ); + double photonEmitterCharge = context.charge( photonEmitterIndices ); constexpr double numericFactor = oneOver16PiSquared; double massFactor = exchangeFieldMass/(photonEmitterMass * photonEmitterMass); @@ -594,7 +592,7 @@ double DiagramEvaluator, double massRatioSquared = exchangeFieldMass / photonEmitterMass; massRatioSquared *= massRatioSquared; - double loopFactor = photonEmitterChargeCount * OneLoopFunctionB( massRatioSquared ); + double loopFactor = photonEmitterCharge * OneLoopFunctionB( massRatioSquared ); double contribution = numericFactor * massFactor * couplingFactor * loopFactor; From 04735463b98de9dd01eec51396776283d6a6729a Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 11 Jan 2017 21:49:16 +0100 Subject: [PATCH 129/158] Fixed clang++ c++11 compatibility issues. --- meta/EDM.m | 13 ++++++------- templates/edm.cpp.in | 9 ++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index eab0d91c4..2dfb27aa2 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -129,7 +129,7 @@ If you add new kinds of vertices (e.g for new diagram types): "const " <> FlexibleSUSY`FSModelName <> "_mass_eigenstates& model )\n" <> "{\n" <> IndentText @ - ("CMSSM_mass_eigenstates model_ = model;\n" <> + (FlexibleSUSY`FSModelName <> "_mass_eigenstates model_ = model;\n" <> "EvaluationContext context{ model_ };\n" <> "std::array ToString @ numberOfIndices <> @@ -257,11 +257,10 @@ If you add new kinds of vertices (e.g for new diagram types): ("using PhotonVertex = VertexFunction CXXNameOfField[#] <> ", " <> CXXNameOfField[SARAH`AntiField @ #] <> ">;\n\n" <> - "double fieldCharge = PhotonVertex::vertex( concatenate( indices, indices ), *this )" <> + "return PhotonVertex::vertex( concatenate( indices, indices ), *this )" <> If[photonVertexType === SingleComponentedVertex, ".value().real();\n", - ".left().real();\n"] <> - "return fieldCharge;\n" + ".left().real();\n"] ) <> "}"] &) /@ photonEmitters, "\n\n"] ]; @@ -391,9 +390,9 @@ If you add new kinds of vertices (e.g for new diagram types): , ";/n" ] <> - "static constexpr std::array ToString @ Length[fieldIndexStart] <> - "> fieldIndexStart = { { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> - " } };\n" <> + "static constexpr unsigned fieldIndexStart[" <> ToString @ Length[fieldIndexStart] <> + "] = { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> + " };\n" <> "using vertex_type = " <> VertexClassName[parsedVertex] <> ";\n" ) <> "};"); diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index ee62847ef..2c83a009b 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -407,13 +407,11 @@ template struct VertexFunctionData; template class VertexFunction { using Data = VertexFunctionData; using bounds_type = typename std::decay::type; - using fieldIndexStart_type = decltype(Data::fieldIndexStart); public: using vertex_type = typename Data::vertex_type; using indices_type = typename decltype(Data::index_bounds)::indices_type; static constexpr bounds_type index_bounds = Data::index_bounds; - static constexpr fieldIndexStart_type fieldIndexStart = Data::fieldIndexStart; /** * @fn fieldIndices @@ -426,11 +424,12 @@ public: */ template static - std::array + std::array fieldIndices(const indices_type &indices) { - constexpr auto length = fieldIndexStart[fieldIndex+1] - fieldIndexStart[fieldIndex]; - auto begin = indices.begin() + fieldIndexStart[fieldIndex]; + constexpr auto length = Data::fieldIndexStart[fieldIndex+1] - Data::fieldIndexStart[fieldIndex]; + constexpr auto offset = Data::fieldIndexStart[fieldIndex]; + auto begin = indices.begin() + offset; return make_array::iterate(begin); } From 2ecc476d9b23bcce21faa4d0c61b6a909e489444 Mon Sep 17 00:00:00 2001 From: iolojz Date: Sun, 22 Jan 2017 16:39:53 +0100 Subject: [PATCH 130/158] Fixed sign mistake in loop functions. --- templates/edm.cpp.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 2c83a009b..1a13bc8af 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -477,7 +477,7 @@ double OneLoopFunctionA(double r) 0.076923076923076923077 * d * d * d * d * d * d * d * d * d * d ); } - return 1.0 / (2.0 * d * d) * (3.0 - r + 2.0 * std::log(r) / d); + return 1.0 / (2.0 * d * d) * (3.0 - r - 2.0 * std::log(r) / d); } double OneLoopFunctionB(double r) @@ -500,7 +500,7 @@ double OneLoopFunctionB(double r) 0.0075757575757575757576 * d * d * d * d * d * d * d * d * d + 0.0064102564102564102564 * d * d * d * d * d * d * d * d * d * d ); - return 1.0 / (2.0 * d * d) * (1.0 + r + 2.0 * r * std::log(r) / d); + return 1.0 / (2.0 * d * d) * (1.0 + r - 2.0 * r * std::log(r) / d); } @EDM_Definitions@ From b0e0db88c8dd22a667aec0cdfc52f1708185c077 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 30 Jan 2017 21:17:12 +0100 Subject: [PATCH 131/158] Fixed some issues with antifields --- meta/EDM.m | 17 ++--------------- templates/edm.cpp.in | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 2dfb27aa2..2c0f60f6c 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -36,9 +36,7 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{fields, code}, fields = TreeMasses`GetParticles[]; - code = ("struct Field {};\n\n" <> - - StringJoin @ Riffle[("struct " <> CXXNameOfField[#] <> + code = (StringJoin @ Riffle[("struct " <> CXXNameOfField[#] <> ": public Field {\n" <> TextFormatting`IndentText["static const unsigned numberOfGenerations = " <> ToString @ TreeMasses`GetDimension[#] <> ";\n"] <> @@ -47,15 +45,6 @@ If you add new kinds of vertices (e.g for new diagram types): "using Photon = " <> CXXNameOfField @ SARAH`Photon <> ";\n" <> "using Electron = " <> CXXNameOfField @ SARAH`Electron <> ";\n\n" <> - "// Anti fields\n" <> - "template struct anti : public Field\n" <> - "{\n" <> - IndentText @ - ("static const unsigned numberOfGenerations = P::numberOfGenerations;\n" <> - "using type = anti

;\n") <> - "};\n" <> - "template struct anti> { using type = P; };\n\n" <> - "// Fields that are their own anti fields\n" <> StringJoin @ Riffle[("template<> struct " <> "anti<" <> CXXNameOfField[#] <> ">" <> @@ -63,8 +52,6 @@ If you add new kinds of vertices (e.g for new diagram types): &) /@ Select[fields, (# == SARAH`AntiField[#] &)], "\n"] <> "\n\n" <> - "template struct field_indices;\n\n" <> - StringJoin @ Riffle[("template<> struct field_indices<" <> CXXNameOfField[#] <> ">\n" <> "{\n" <> @@ -388,7 +375,7 @@ If you add new kinds of vertices (e.g for new diagram types): "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[1]], ", "] <> " }, " <> "{ " <> StringJoin @ Riffle[ToString /@ indexBounds[[2]], ", "] <> " } };\n" , - ";/n" + "{};\n" ] <> "static constexpr unsigned fieldIndexStart[" <> ToString @ Length[fieldIndexStart] <> "] = { " <> StringJoin @ Riffle[ToString /@ fieldIndexStart, ", "] <> diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 1a13bc8af..679324bc9 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -38,6 +38,7 @@ #define INPUTPARAMETER(p) context.model.get_input().p #define MODELPARAMETER(p) context.model.get_##p() #define DERIVEDPARAMETER(p) context.model.p() +#define PHASE(p) context.model.get_##p() using namespace flexiblesusy; @@ -269,10 +270,29 @@ template<> struct IndexBounds<0> { { return (begin()+1); } }; -@EDM_Fields@ +struct Field {}; + +// Anti fields +template struct anti : public Field +{ + static const unsigned numberOfGenerations = F::numberOfGenerations; + using type = anti; +}; -template struct remove_anti { typedef F type; }; -template struct remove_anti> { typedef F type; }; +template struct anti> { using type = F; }; + +template struct is_anti { static constexpr bool value = false; }; +template struct is_anti> { static constexpr bool value = true; }; + +template struct field_indices; + +template +struct field_indices> +{ + using type = typename field_indices::type; +}; + +@EDM_Fields@ /** * @class EvaluationContext @@ -290,7 +310,13 @@ struct EvaluationContext { * @brief Returns the mass of a field. */ template - double mass( const typename field_indices::type & ) const; + double mass( const typename std::enable_if::value, + typename field_indices::type>::type &indices ) const + { return mass::type>( indices ); } + + template + double mass( const typename std::enable_if::value, + typename field_indices::type>::type &indices ) const; template double charge( const typename field_indices::type & ) const; From 1f7d0608f2061a4a361e1c9a4db89816db470140 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 6 Feb 2017 17:00:02 +0100 Subject: [PATCH 132/158] Fixed off by one range issue --- meta/GMuonMinus2.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/GMuonMinus2.m b/meta/GMuonMinus2.m index 02e33f2ca..355954c3c 100644 --- a/meta/GMuonMinus2.m +++ b/meta/GMuonMinus2.m @@ -618,7 +618,7 @@ If you add new kinds of vertices (e.g for new diagram types): indexBounds = (With[{particleIndex = #}, (If[#[[1]] === SARAH`generation, {particleInfo[[particleIndex, 2]]-1, particleInfo[[particleIndex, 3]]}, - {1, #[[2]]}] + {0, #[[2]]}] &) /@ particleInfo[[particleIndex, 5]]] &) /@ Table[i, {i, Length[particles]}]; indexBounds = Cases[Flatten[indexBounds, 1], Except[{}]]; From 4cd8246f46801a5b63c23f1130e6c3c3b5b46e28 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 27 Feb 2017 17:24:22 +0100 Subject: [PATCH 133/158] Remove use of FirstCase[] in favor of Cases[] --- meta/EDM.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 2c0f60f6c..51c3ef8f4 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -206,8 +206,8 @@ If you add new kinds of vertices (e.g for new diagram types): Head[p][remainingIndices]] ]; -CleanFieldInfo[field_] := Module[{fieldInfo = FirstCase[SARAH`Particles[FlexibleSUSY`FSEigenstates], - {SARAH`getParticleName @ field, ___}]}, +CleanFieldInfo[field_] := Module[{fieldInfo = Cases[SARAH`Particles[FlexibleSUSY`FSEigenstates], + {SARAH`getParticleName @ field, ___}][[1]]}, fieldInfo = DeleteCases[fieldInfo, {SARAH`generation, 1}, {2}]; DeleteCases[fieldInfo, {SARAH`lorentz, _}, {2}] ]; From 79aa080e598e1227e93dac657df5e5ff6d2a18a1 Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 1 Mar 2017 15:26:33 +0100 Subject: [PATCH 134/158] Added funciton prefixes to better distinguish between EDM and GMM2 packages. --- meta/EDM.m | 32 ++++++++++++++++---------------- meta/FlexibleSUSY.m | 30 +++++++++++++++--------------- meta/GMuonMinus2.m | 30 +++++++++++++++--------------- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 51c3ef8f4..bf3396d73 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -2,16 +2,16 @@ (* This module generates c++ code that calculates electric dipole moments of fields *) -Initialize::usage="Initialize the EDM module."; +EDMInitialize::usage="EDMInitialize the EDM module."; -SetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; -CreateFields::usage="Returns the c++ code that contains all field fields"; -CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; -CreateInterfaceFunctions::usage="Returns the c++ code containing the interface functions {prototypeCode, definitionCode}." -CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; -CreateDefinitions::usage="Returns the c++ that contains all function definitions" +EDMSetEDMFields::usage="Set the fields for which the EDMs shall be calculated."; +EDMCreateFields::usage="Returns the c++ code that contains all field fields"; +EDMCreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; +EDMCreateInterfaceFunctions::usage="Returns the c++ code containing the interface functions {prototypeCode, definitionCode}." +EDMCreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; +EDMCreateDefinitions::usage="Returns the c++ that contains all function definitions" -NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; +EDMNPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; (******** TODO: IMPORTANT NOTES: If you add new kinds of vertices (e.g for new diagram types): @@ -27,12 +27,12 @@ If you add new kinds of vertices (e.g for new diagram types): (************* Begin public interface *******************) -Initialize[] := (subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___);) +EDMInitialize[] := (subIndexPattern = (Alternatives @@ SARAH`subIndizes[[All, 1]] -> ___);) edmFields = Null; -SetEDMFields[fields_List] := (edmFields = fields;) +EDMSetEDMFields[fields_List] := (edmFields = fields;) -CreateFields[] := +EDMCreateFields[] := Module[{fields, code}, fields = TreeMasses`GetParticles[]; @@ -66,7 +66,7 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateDiagrams[] := +EDMCreateDiagrams[] := Module[{code}, code = StringJoin @ Riffle[(Module[{diagramType = #}, "template class " <> SymbolName[diagramType] <> ";\n" <> @@ -89,7 +89,7 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateInterfaceFunctions[] := +EDMCreateInterfaceFunctions[] := Module[{prototypes, definitions, evaluators}, evaluators = ConcreteDiagramEvaluators[]; @@ -146,13 +146,13 @@ If you add new kinds of vertices (e.g for new diagram types): Return[{prototypes, definitions}]; ]; -CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; +EDMCreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; -CreateDefinitions[vertexRules_List] := +EDMCreateDefinitions[vertexRules_List] := (CreateVertices[vertexRules][[2]] <> "\n\n" <> CreateEvaluationContextSpecializations[]); -NPointFunctions[] := +EDMNPointFunctions[] := Module[{contributingDiagrams, vertices}, contributingDiagrams = ContributingDiagrams[]; diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index d69ca50de..7cd90fb21 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1431,12 +1431,12 @@ corresponding tadpole is real or imaginary (only in models with CP WriteGMuonMinus2Class[vertexRules_List, files_List] := Module[{particles, muonFunctionPrototypes, diagrams, vertexFunctionData, definitions, calculationCode}, - particles = GMuonMinus2`CreateParticles[]; - muonFunctionPrototypes = GMuonMinus2`CreateMuonFunctions[vertexRules][[1]]; - diagrams = GMuonMinus2`CreateDiagrams[]; - vertexFunctionData = GMuonMinus2`CreateVertexFunctionData[vertexRules]; - definitions = GMuonMinus2`CreateDefinitions[vertexRules]; - calculationCode = GMuonMinus2`CreateCalculation[]; + particles = GMuonMinus2`GMuonMinus2CreateParticles[]; + muonFunctionPrototypes = GMuonMinus2`GMuonMinus2CreateMuonFunctions[vertexRules][[1]]; + diagrams = GMuonMinus2`GMuonMinus2CreateDiagrams[]; + vertexFunctionData = GMuonMinus2`GMuonMinus2CreateVertexFunctionData[vertexRules]; + definitions = GMuonMinus2`GMuonMinus2CreateDefinitions[vertexRules]; + calculationCode = GMuonMinus2`GMuonMinus2CreateCalculation[]; WriteOut`ReplaceInFiles[files, { "@GMuonMinus2_Particles@" -> particles, @@ -1453,12 +1453,12 @@ corresponding tadpole is real or imaginary (only in models with CP WriteEDMClass[vertexRules_List, files_List] := Module[{fields, diagrams, interfaceFunctions, vertexFunctionData, definitions}, - fields = EDM`CreateFields[]; - diagrams = EDM`CreateDiagrams[]; + fields = EDM`EDMCreateFields[]; + diagrams = EDM`EDMCreateDiagrams[]; - interfaceFunctions = EDM`CreateInterfaceFunctions[]; - vertexFunctionData = EDM`CreateVertexFunctionData[vertexRules]; - definitions = EDM`CreateDefinitions[vertexRules]; + interfaceFunctions = EDM`EDMCreateInterfaceFunctions[]; + vertexFunctionData = EDM`EDMCreateVertexFunctionData[vertexRules]; + definitions = EDM`EDMCreateDefinitions[vertexRules]; WriteOut`ReplaceInFiles[files, { "@EDM_Fields@" -> fields, @@ -2031,7 +2031,7 @@ corresponding tadpole is real or imaginary (only in models with CP ]; (* Get all nPointFunctions that GMM2 needs *) -PrepareGMuonMinus2[] := GMuonMinus2`NPointFunctions[]; +PrepareGMuonMinus2[] := GMuonMinus2`GMuonMinus2NPointFunctions[]; PrepareUnrotatedParticles[eigenstates_] := Module[{nonMixedParticles = {}, nonMixedParticlesFile}, @@ -2944,10 +2944,10 @@ corresponding tadpole is real or imaginary (only in models with CP FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; Print["Creating class EDM"]; - EDM`Initialize[]; - EDM`SetEDMFields[{SARAH`Electron}]; + EDM`EDMInitialize[]; + EDM`EDMSetEDMFields[{SARAH`Electron}]; - WriteEDMClass[Join[vertexRules, Vertices`VertexRules[EDM`NPointFunctions[], Lat$massMatrices]], + WriteEDMClass[Join[vertexRules, Vertices`VertexRules[EDM`EDMNPointFunctions[], Lat$massMatrices]], {{FileNameJoin[{$flexiblesusyTemplateDir, "edm.hpp.in"}], FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.hpp"}]}, {FileNameJoin[{$flexiblesusyTemplateDir, "edm.cpp.in"}], diff --git a/meta/GMuonMinus2.m b/meta/GMuonMinus2.m index 355954c3c..07ab39f78 100644 --- a/meta/GMuonMinus2.m +++ b/meta/GMuonMinus2.m @@ -1,15 +1,15 @@ BeginPackage["GMuonMinus2`", {"SARAH`", "CConversion`", "TextFormatting`", "TreeMasses`", "LoopMasses`", "Vertices`"}]; -CreateParticles::usage="Returns the c++ code that contains all particle classes"; -CreateMuonFunctions::usage="Returns the c++ code that contains all muon functions"; -CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; -CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; +GMuonMinus2CreateParticles::usage="Returns the c++ code that contains all particle classes"; +GMuonMinus2CreateMuonFunctions::usage="Returns the c++ code that contains all muon functions"; +GMuonMinus2CreateDiagrams::usage="Returns the c++ code that contains all relevant diagram classes"; +GMuonMinus2CreateVertexFunctionData::usage="Returns the c++ code that contains all relevant vertex function data"; -CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; +GMuonMinus2CreateCalculation::usage="Returns the c++ code that performs the actual calculation the magnetic moment"; -CreateDefinitions::usage="Returns the c++ that contains all function definitions" +GMuonMinus2CreateDefinitions::usage="Returns the c++ that contains all function definitions" -NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; +GMuonMinus2NPointFunctions::usage="Returns a list of all n point functions that are needed. Actually it is a list of fake functions to extract vertex functions..."; (******** IMPORTANT NOTES: If you add new kinds of vertices (e.g for new diagram types): @@ -45,7 +45,7 @@ If you add new kinds of vertices (e.g for new diagram types): ]; (* Create c++ classes for all particles *) -CreateParticles[] := +GMuonMinus2CreateParticles[] := Module[{particles, code}, (* Get a list of all particles *) particles = TreeMasses`GetParticles[]; @@ -107,7 +107,7 @@ If you add new kinds of vertices (e.g for new diagram types): ]; muonFunctions = Null; -CreateMuonFunctions[vertexRules_List] := +GMuonMinus2CreateMuonFunctions[vertexRules_List] := Module[{muonIndex, muonFamily, prototypes = "", definitions, contextMuonPole}, If[muonFunctions =!= Null, Return[muonFunctions]]; @@ -140,7 +140,7 @@ If you add new kinds of vertices (e.g for new diagram types): {prototypes, definitions} ]; -CreateDiagrams[] := +GMuonMinus2CreateDiagrams[] := Module[{diagramTypes, diagramTypeHeads, code}, diagrams = contributingFeynmanDiagramTypes; diagramHeads = DeleteDuplicates @ (Head /@ diagrams); @@ -162,7 +162,7 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; +GMuonMinus2CreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; CreateDiagramEvaluatorClass[type_OneLoopDiagram] := ("template\n" <> @@ -172,7 +172,7 @@ If you add new kinds of vertices (e.g for new diagram types): "{ static double value(EvaluationContext& context); };"); calculationCode = Null; -CreateCalculation[] := +GMuonMinus2CreateCalculation[] := Module[{code}, (* If we have been here before return the old result *) If[calculationCode =!= Null, Return[calculationCode]]; @@ -192,13 +192,13 @@ If you add new kinds of vertices (e.g for new diagram types): Return[code]; ]; -CreateDefinitions[vertexRules_List] := +GMuonMinus2CreateDefinitions[vertexRules_List] := (CreateEvaluationContextSpecializations[] <> "\n\n" <> - CreateMuonFunctions[vertexRules][[2]] <> "\n\n" <> + GMuonMinus2CreateMuonFunctions[vertexRules][[2]] <> "\n\n" <> CreateVertices[vertexRules][[2]]); nPointFunctions = Null; -NPointFunctions[] := +GMuonMinus2NPointFunctions[] := Module[{contributingDiagrams, vertices}, If[nPointFunctions =!= Null, Return[nPointFunctions]]; From 7e777142e398ae209778ed08f0588b9b14e759f9 Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 1 Mar 2017 16:06:49 +0100 Subject: [PATCH 135/158] Make IndexBounds<> slightly less ugly. --- templates/edm.cpp.in | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 679324bc9..28e0f7373 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -181,20 +181,20 @@ template struct IndexBounds; * Incrementing the iterator results in a new index combination. */ template struct IndexIterator -: public std::iterator< -std::input_iterator_tag, -const std::array> { + using difference_type = typename std::array::difference_type; + using value_type = unsigned; + using pointer = unsigned *; + using reference = unsigned &; + using iterator_category = std::input_iterator_tag; + friend class IndexBounds; private: - const IndexBounds *bounds; + const IndexBounds &bounds; std::array indices; - IndexIterator(const IndexBounds &b, const unsigned *i) - : bounds(&b) - { - std::memcpy(indices.data(), i, N * sizeof(unsigned)); - } + IndexIterator(const IndexBounds &b, std::array &&i ) + : bounds(b), indices( std::move(i) ) {} public: const std::array &operator*() const { return indices; @@ -207,15 +207,15 @@ public: IndexIterator &operator++() { for (unsigned i = 0; i != N; i++) { indices[i]++; - if (indices[i] == bounds->indexEnd[i]) { - indices[i] = bounds->indexBegin[i]; + if (indices[i] == bounds.indexEnd[i]) { + indices[i] = bounds.indexBegin[i]; continue; } return *this; } - std::memcpy(indices.data(), bounds->indexEnd, N * sizeof(unsigned)); + indices = make_array::iterate( bounds.indexEnd ); return *this; } @@ -250,11 +250,11 @@ template struct IndexBounds { typedef IndexIterator const_iterator; const_iterator begin() const { - return const_iterator(*this, indexBegin); + return const_iterator(*this, make_array::iterate( indexBegin )); } const_iterator end() const { - return const_iterator(*this, indexEnd); + return const_iterator(*this, make_array::iterate( indexEnd )); } }; @@ -262,13 +262,14 @@ template<> struct IndexBounds<0> { using indices_type = const std::array; using const_iterator = indices_type *; - static constexpr indices_type dummyIndex{}; + static constexpr indices_type dummyIndex = {}; const_iterator begin() const { return &dummyIndex; } const_iterator end() const { return (begin()+1); } }; +constexpr IndexBounds<0>::indices_type IndexBounds<0>::dummyIndex; struct Field {}; From a1b69b3146644228f007fd0d9ca9294d31c135e9 Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 15 Mar 2017 16:51:52 +0100 Subject: [PATCH 136/158] Fixed merge issue --- meta/FlexibleSUSY.m | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 981c08c1c..198ade0eb 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1466,25 +1466,15 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the GMM2 c++ files *) WriteGMuonMinus2Class[vertexRules_List, files_List] := Module[{particles, muonFunctionPrototypes, diagrams, vertexFunctionData, -<<<<<<< HEAD - definitions, calculationCode}, + definitions, calculationCode, getMSUSY, getQED2L}, particles = GMuonMinus2`GMuonMinus2CreateParticles[]; muonFunctionPrototypes = GMuonMinus2`GMuonMinus2CreateMuonFunctions[vertexRules][[1]]; diagrams = GMuonMinus2`GMuonMinus2CreateDiagrams[]; vertexFunctionData = GMuonMinus2`GMuonMinus2CreateVertexFunctionData[vertexRules]; definitions = GMuonMinus2`GMuonMinus2CreateDefinitions[vertexRules]; calculationCode = GMuonMinus2`GMuonMinus2CreateCalculation[]; -======= - definitions, calculationCode, getMSUSY, getQED2L}, - particles = GMuonMinus2`CreateParticles[]; - muonFunctionPrototypes = GMuonMinus2`CreateMuonFunctions[vertexRules][[1]]; - diagrams = GMuonMinus2`CreateDiagrams[]; - vertexFunctionData = GMuonMinus2`CreateVertexFunctionData[vertexRules]; - definitions = GMuonMinus2`CreateDefinitions[vertexRules]; - calculationCode = GMuonMinus2`CreateCalculation[]; getMSUSY = GMuonMinus2`GetMSUSY[]; getQED2L = GMuonMinus2`GetQED2L[]; ->>>>>>> feature-2.0 WriteOut`ReplaceInFiles[files, { "@GMuonMinus2_Particles@" -> particles, @@ -2230,7 +2220,7 @@ corresponding tadpole is real or imaginary (only in models with CP MakeFlexibleSUSY[OptionsPattern[]] := Module[{nPointFunctions, runInputFile, initialGuesserInputFile, - gmm2Vertices = {}, + gmm2Vertices = {}, edmFields, susyBetaFunctions, susyBreakingBetaFunctions, numberOfSusyParameters, anomDim, inputParameters (* list of 3-component lists of the form {name, block, type} *), @@ -2994,8 +2984,10 @@ corresponding tadpole is real or imaginary (only in models with CP FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; Print["Creating class EDM"]; + edmFields = DeleteDuplicates @ Cases[Observables`GetRequestedObservables[extraSLHAOutputBlocks], + FlexibleSUSYObservable`EDM[p_[__]|p_] :> p]; EDM`EDMInitialize[]; - EDM`EDMSetEDMFields[{SARAH`Electron}]; + EDM`EDMSetEDMFields[edmFields]; WriteEDMClass[Join[vertexRules, Vertices`VertexRules[EDM`EDMNPointFunctions[], Lat$massMatrices]], {{FileNameJoin[{$flexiblesusyTemplateDir, "edm.hpp.in"}], From 64efb8a538c01b15a76a9e2b0647069aeb397935 Mon Sep 17 00:00:00 2001 From: iolojz Date: Thu, 16 Mar 2017 09:06:50 +0100 Subject: [PATCH 137/158] EDM now works with an empty list of EDMFields as well --- meta/EDM.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta/EDM.m b/meta/EDM.m index bf3396d73..9782207ac 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -299,6 +299,8 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; + If[vertices === {}, Return[{"",""}];]; + {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); From b49c4b2f4ef8a2a51b21fb09f7633107b686691b Mon Sep 17 00:00:00 2001 From: iolojz Date: Thu, 16 Mar 2017 09:09:40 +0100 Subject: [PATCH 138/158] Added EDM header to observables.cpp.in template --- templates/observables.cpp.in | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/observables.cpp.in b/templates/observables.cpp.in index 37a37f806..aadf3b715 100644 --- a/templates/observables.cpp.in +++ b/templates/observables.cpp.in @@ -21,6 +21,7 @@ #include "@ModelName@_observables.hpp" #include "@ModelName@_mass_eigenstates.hpp" #include "@ModelName@_a_muon.hpp" +#include "@ModelName@_edm.hpp" #include "@ModelName@_effective_couplings.hpp" #include "gm2calc_interface.hpp" #include "eigen_utils.hpp" From 0f99ea36b172f86e192f6e4df9d7b11ce4ee3a38 Mon Sep 17 00:00:00 2001 From: iolojz Date: Mon, 3 Apr 2017 12:44:10 +0200 Subject: [PATCH 139/158] Changed to the conjugate edm vertices --- meta/EDM.m | 2 +- templates/edm.cpp.in | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 9782207ac..20b6686a1 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -311,7 +311,7 @@ If you add new kinds of vertices (e.g for new diagram types): This function should be overloaded for future diagram types. *) VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmField_, photonEmitter_, exchangeField_]] := Module[{edmVertex, photonVertex}, - edmVertex = {edmField, SARAH`AntiField[photonEmitter], SARAH`AntiField[exchangeField]}; + edmVertex = {SARAH`AntiField[edmField], photonEmitter, exchangeField}; photonVertex = {SARAH`Photon, photonEmitter, SARAH`AntiField[photonEmitter]}; Return[{edmVertex, photonVertex}]; ]; diff --git a/templates/edm.cpp.in b/templates/edm.cpp.in index 28e0f7373..0053905b8 100644 --- a/templates/edm.cpp.in +++ b/templates/edm.cpp.in @@ -541,9 +541,9 @@ double DiagramEvaluator, double res = 0.0; using FermionVertex = VertexFunction< - EDMField, - typename anti::type, - typename anti::type + typename anti::type, + PhotonEmitter, + ExchangeField >; constexpr auto indexBounds = FermionVertex::index_bounds; @@ -589,9 +589,9 @@ double DiagramEvaluator, double res = 0.0; using FermionVertex = VertexFunction< - EDMField, - typename anti::type, - typename anti::type + typename anti::type, + PhotonEmitter, + ExchangeField >; constexpr auto indexBounds = FermionVertex::index_bounds; From 5da09bc1a14aa809ae9d330e7a04a5a03ee3196f Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Tue, 18 Apr 2017 18:55:04 +0200 Subject: [PATCH 140/158] remove redundant dependence on convergence tester header --- templates/module.mk.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/module.mk.in b/templates/module.mk.in index f35ada05a..5f251dc8c 100644 --- a/templates/module.mk.in +++ b/templates/module.mk.in @@ -31,7 +31,7 @@ WITH_$(MODNAME) := yes LIB@CLASSNAME@_SRC := \ $(DIR)/@CLASSNAME@_a_muon.cpp \ - $(DIR)/@CLASSNAME@_edm.cpp \ + $(DIR)/@CLASSNAME@_edm.cpp \ $(DIR)/@CLASSNAME@_effective_couplings.cpp \ $(DIR)/@CLASSNAME@_info.cpp \ $(DIR)/@CLASSNAME@_input_parameters.cpp \ @@ -60,7 +60,6 @@ LL@CLASSNAME@_MMA := \ LIB@CLASSNAME@_HDR := \ $(DIR)/@CLASSNAME@_a_muon.hpp \ $(DIR)/@CLASSNAME@_edm.hpp \ - $(DIR)/@CLASSNAME@_convergence_tester.hpp \ $(DIR)/@CLASSNAME@_effective_couplings.hpp \ $(DIR)/@CLASSNAME@_info.hpp \ $(DIR)/@CLASSNAME@_input_parameters.hpp \ From 1aca0f907200a216d104eaa9a90c78fd07039b03 Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 19 Apr 2017 13:34:05 +0200 Subject: [PATCH 141/158] Removed all uses of Return[] --- meta/EDM.m | 65 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 20b6686a1..5807444f5 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -1,3 +1,5 @@ +(* ::Package:: *) + BeginPackage["EDM`", {"SARAH`", "TextFormatting`", "TreeMasses`", "Vertices`", "Parameters`"}]; (* This module generates c++ code that calculates electric dipole moments of fields *) @@ -63,7 +65,7 @@ If you add new kinds of vertices (e.g for new diagram types): "};\n" &) /@ fields, "\n"] ); - Return[code]; + code ]; EDMCreateDiagrams[] := @@ -86,7 +88,7 @@ If you add new kinds of vertices (e.g for new diagram types): &) /@ diagramSubTypes[diagramType], "\n\n"]] &) /@ diagramTypes, "\n\n"] ); - Return[code]; + code ]; EDMCreateInterfaceFunctions[] := @@ -143,7 +145,7 @@ If you add new kinds of vertices (e.g for new diagram types): ) <> "\n}"] & /@ evaluators, "\n\n"]; - Return[{prototypes, definitions}]; + {prototypes, definitions} ]; EDMCreateVertexFunctionData[vertexRules_List] := CreateVertices[vertexRules][[1]]; @@ -231,7 +233,7 @@ If you add new kinds of vertices (e.g for new diagram types): ] &) /@ fields, "\n\n"] <> "\n\n" <> StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], - photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], + photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @\[NonBreakingSpace]#}], numberOfIndices}, numberOfIndices = Length @ fieldInfo[[5]]; @@ -269,9 +271,9 @@ If you add new kinds of vertices (e.g for new diagram types): subtypedDiagrams, uniqueDiagrams}, If[TreeMasses`IsFermion[edmField] =!= True, - Return[{edmField,{}}]]; - - subtypedDiagrams = (Module[{photonEmitter = #[[2,1]], + {edmField,{}}, + + subtypedDiagrams = (Module[{photonEmitter = #[[2,1]], exchangeField = #[[2,2]], subType}, subType = If[TreeMasses`IsFermion[photonEmitter] && @@ -285,9 +287,8 @@ If you add new kinds of vertices (e.g for new diagram types): Diagram[OneLoopDiagram[subType], edmField, photonEmitter, exchangeField]] ] &) /@ diagrams; - uniqueDiagrams = DeleteDuplicates @ Cases[subtypedDiagrams, Except[Null]]; - - {edmField, uniqueDiagrams}] & /@ edmFields; + uniqueDiagrams = DeleteDuplicates @ Cases[subtypedDiagrams, Except[Null]]; + {edmField, uniqueDiagrams}]] & /@ edmFields; (* Returns the necessary c++ code corresponding to the vertices that need to be calculated. The returned value is a list {prototypes, definitions}. *) @@ -299,13 +300,13 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - If[vertices === {}, Return[{"",""}];]; - - {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ + If[vertices =!= {}, + {"",""}, + + {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ ((CreateVertexFunction[#, vertexRules] &) /@ vertices); - - (StringJoin @ Riffle[#, "\n\n"] &) /@ {vertexClassesPrototypes, vertexClassesDefinitions} - ]; + (StringJoin @ Riffle[#, "\n\n"] &) /@ {vertexClassesPrototypes, vertexClassesDefinitions} + ]]; (* Returns the vertices that are present in the specified diagram. This function should be overloaded for future diagram types. *) @@ -313,12 +314,12 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{edmVertex, photonVertex}, edmVertex = {SARAH`AntiField[edmField], photonEmitter, exchangeField}; photonVertex = {SARAH`Photon, photonEmitter, SARAH`AntiField[photonEmitter]}; - Return[{edmVertex, photonVertex}]; + {edmVertex, photonVertex} ]; (* Returns the vertex type for a vertex with a given list of fields *) VertexTypeForFields[fields_List] := - Module[{fermions, scalarCount, vectorCount, fermionCount}, + Module[{fermions, scalarCount, vectorCount, fermionCount, vertexType = Null}, fermions = Select[fields, TreeMasses`IsFermion]; scalarCount = Length @ Select[fields, TreeMasses`IsScalar]; @@ -326,14 +327,14 @@ If you add new kinds of vertices (e.g for new diagram types): fermionCount = Length @ fermions; If[fermionCount === 2 && scalarCount === 1 && vectorCount === 0, - Return[LeftAndRightComponentedVertex]]; + vertexType = LeftAndRightComponentedVertex]; If[fermionCount === 2 && scalarCount === 0 && vectorCount === 1, If[fermions[[1]] === SARAH`AntiField[fermions[[2]]], - Return[LeftAndRightComponentedVertex]]]; + vertexType = LeftAndRightComponentedVertex]]; If[fermionCount === 0 && scalarCount === 2 && vectorCount === 1, - Return[SingleComponentedVertex]]; + vertexType = SingleComponentedVertex]; - Return[Null]; + vertexType ]; (* Returns the different SARAH`Cp coupling parts for a vertex with a given list of fields *) @@ -392,7 +393,7 @@ If you add new kinds of vertices (e.g for new diagram types): IndentText @ VertexFunctionBody[parsedVertex] <> "\n" <> "}"); - Return[{prototype, definition}]; + {prototype, definition} ]; (* Creates local declarations of field indices, whose values are taken @@ -486,7 +487,7 @@ If you add new kinds of vertices (e.g for new diagram types): vertexClassName, vertexFunctionBody]; - Return[parsedVertex]; + parsedVertex ]; (** Getters to the ParsedVertex structure **) @@ -503,17 +504,19 @@ If you add new kinds of vertices (e.g for new diagram types): cachedContributingDiagrams = Null; ContributingDiagrams[] := Module[{diagrams}, - If[cachedContributingDiagrams =!= Null, Return[cachedContributingDiagrams]]; - LoadVerticesIfNecessary[]; - - diagrams = Flatten[(ContributingDiagramsOfType[#] &) + If[cachedContributingDiagrams =!= Null, + cachedContributingDiagrams, + + LoadVerticesIfNecessary[]; + + diagrams = Flatten[(ContributingDiagramsOfType[#] &) /@ diagramTypes , 1]; - - cachedContributingDiagrams = ({#, Union @ + cachedContributingDiagrams = ({#, Union @ (Sequence @@ Cases[diagrams, {#, diags_List} -> diags])} &) /@ edmFields; - Return[cachedContributingDiagrams]; + + cachedContributingDiagrams]; ]; LoadVerticesIfNecessary[] := From 3b30c0963fa2cda13a92b80aae81b42f4a3d727e Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 19 Apr 2017 14:17:45 +0200 Subject: [PATCH 142/158] Fixed severe typos from last commit --- meta/EDM.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 5807444f5..54ac4ffe5 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -300,7 +300,7 @@ If you add new kinds of vertices (e.g for new diagram types): vertices = DeleteDuplicates @ Flatten[VerticesForDiagram /@ Flatten @ contributingDiagrams[[All, 2]], 1]; - If[vertices =!= {}, + If[vertices === {}, {"",""}, {vertexClassesPrototypes, vertexClassesDefinitions} = Transpose @ @@ -516,7 +516,7 @@ If you add new kinds of vertices (e.g for new diagram types): (Sequence @@ Cases[diagrams, {#, diags_List} -> diags])} &) /@ edmFields; - cachedContributingDiagrams]; + cachedContributingDiagrams] ]; LoadVerticesIfNecessary[] := From a38aa25cf4e5b21b0d3fe89a59219e4f2a4cc64f Mon Sep 17 00:00:00 2001 From: iolojz Date: Wed, 19 Apr 2017 17:15:30 +0200 Subject: [PATCH 143/158] Removed non-ascii character in source that caused trouble with earlier Mathematica versions. --- meta/EDM.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/EDM.m b/meta/EDM.m index 54ac4ffe5..370c0a45a 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -233,7 +233,7 @@ If you add new kinds of vertices (e.g for new diagram types): ] &) /@ fields, "\n\n"] <> "\n\n" <> StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], - photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @\[NonBreakingSpace]#}], + photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], numberOfIndices}, numberOfIndices = Length @ fieldInfo[[5]]; From 5240ed28c32bfc2d0045e77bb9ad4d0f4592e0f3 Mon Sep 17 00:00:00 2001 From: Dylan Harries Date: Fri, 2 Jun 2017 16:45:33 +0930 Subject: [PATCH 144/158] Fix uninitialized variable --- src/numerics.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/numerics.cpp b/src/numerics.cpp index c499a5ebc..7029516b0 100644 --- a/src/numerics.cpp +++ b/src/numerics.cpp @@ -358,10 +358,12 @@ double d0(double m1, double m2, double m3, double m4) noexcept { using std::log; - const double m1sq = sqr(m1), m2sq = sqr(m2); + const double m1sq = sqr(m1); + const double m2sq = sqr(m2); if (is_close(m1, m2, EPSTOL)) { - const double m3sq = m3sq, m4sq = sqr(m4); + const double m3sq = sqr(m3); + const double m4sq = sqr(m4); if (is_close(m2,0.,EPSTOL)) { // d0 is undefined for m1 == m2 == 0 From 642d75849e9868f9c29c09c4de5a90edd55a31d7 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Sun, 4 Jun 2017 13:30:04 +0200 Subject: [PATCH 145/158] adding rk.hpp back to list of headers since it must be installed --- src/module.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/src/module.mk b/src/module.mk index ab8a30dfa..de2de9d02 100644 --- a/src/module.mk +++ b/src/module.mk @@ -106,6 +106,7 @@ LIBFLEXI_HDR := \ $(DIR)/pv.hpp \ $(DIR)/raii.hpp \ $(DIR)/rg_flow.hpp \ + $(DIR)/rk.hpp \ $(DIR)/rkf_integrator.hpp \ $(DIR)/root_finder.hpp \ $(DIR)/scan.hpp \ From d6633eb237c99d8ff1255ec4737d807da249af16 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Tue, 6 Jun 2017 10:34:29 +0200 Subject: [PATCH 146/158] add template keyword because a templated function is called of a templated class. --- meta/CConversion.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/CConversion.m b/meta/CConversion.m index 67dd40c22..ffbcfcaed 100644 --- a/meta/CConversion.m +++ b/meta/CConversion.m @@ -224,7 +224,7 @@ CConversion`ArrayType[ CConversion`complexScalarCType,_] | CConversion`MatrixType[CConversion`complexScalarCType,__]| CConversion`TensorType[CConversion`complexScalarCType,__], - "(" <> expr <> ").cast<" <> CreateCType[CConversion`ScalarType[complexScalarCType]] <> " >()" + "(" <> expr <> ").template cast<" <> CreateCType[CConversion`ScalarType[complexScalarCType]] <> " >()" , _, Print["Error: CastTo: cannot cast expression ", expr, " to ", toType]; From ccab6d5ca38d08105a3d98628551eb2d09321972 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Tue, 6 Jun 2017 10:59:37 +0200 Subject: [PATCH 147/158] Bugfix: triliear couplings and soft squared masses are complex in general, even in super-CKM basis. --- meta/WriteOut.m | 60 +++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/meta/WriteOut.m b/meta/WriteOut.m index 58d36252c..484c4d15f 100644 --- a/meta/WriteOut.m +++ b/meta/WriteOut.m @@ -901,13 +901,13 @@ CConversion`ToValidCSymbolString[c] <> "_slha"; GetSLHATrilinearCouplingType[c_] := - CConversion`ToRealType[Parameters`GetType[c]]; + Parameters`GetType[c]; CreateSLHASoftSquaredMassName[c_] := CConversion`ToValidCSymbolString[c] <> "_slha"; GetSLHASoftSquaredMassType[c_] := - CConversion`ToRealType[Parameters`GetType[c]]; + Parameters`GetType[c]; CreateSLHAYukawaDefinition[] := StringJoin[Parameters`CreateParameterDefinitionAndDefaultInitialize[ @@ -992,19 +992,24 @@ If[Parameters`IsOutputParameter[{vL, vR}] && ParametersHaveSameDimension[{vL, vR, #}], result = result <> - CreateSLHATrilinearCouplingName[#] <> " = (" <> - CreateSLHAFermionMixingMatrixName[vR] <> ".conjugate() * " <> - "MODELPARAMETER(" <> - CConversion`ToValidCSymbolString[#] <> ") * " <> - CreateSLHAFermionMixingMatrixName[vL] <> ".adjoint()" <> - ").real();\n"; + CreateSLHATrilinearCouplingName[#] <> " = " <> + CConversion`CastTo[ + CreateSLHAFermionMixingMatrixName[vR] <> ".conjugate() * " <> + "MODELPARAMETER(" <> + CConversion`ToValidCSymbolString[#] <> ") * " <> + CreateSLHAFermionMixingMatrixName[vL] <> ".adjoint()", + GetSLHATrilinearCouplingType[#] + ] <> ";\n"; , Print["Warning: Cannot convert Trilinear coupling ", #, " to SLHA, because ", {vL,vR}, " are not defined", " or have incompatible dimension."]; result = result <> - CreateSLHATrilinearCouplingName[#] <> " = MODELPARAMETER(" <> - CConversion`ToValidCSymbolString[#] <> ").real();\n"; + CreateSLHATrilinearCouplingName[#] <> " = " <> + CConversion`CastTo[ + "MODELPARAMETER(" <> CConversion`ToValidCSymbolString[#] <> ")", + GetSLHATrilinearCouplingType[#] + ] <> ";\n"; ]; ]& /@ tril; result @@ -1054,28 +1059,35 @@ ParametersHaveSameDimension[{vL, vR, #}], If[IsLeftHanded[#], result = result <> - CreateSLHASoftSquaredMassName[#] <> " = (" <> - CreateSLHAFermionMixingMatrixName[vL] <> " * " <> - "MODELPARAMETER(" <> - CConversion`ToValidCSymbolString[#] <> ") * " <> - CreateSLHAFermionMixingMatrixName[vL] <> ".adjoint()" <> - ").real();\n"; + CreateSLHASoftSquaredMassName[#] <> " = " <> + CConversion`CastTo[ + CreateSLHAFermionMixingMatrixName[vL] <> " * " <> + "MODELPARAMETER(" <> + CConversion`ToValidCSymbolString[#] <> ") * " <> + CreateSLHAFermionMixingMatrixName[vL] <> ".adjoint()", + GetSLHASoftSquaredMassType[#] + ] <> ";\n"; , result = result <> - CreateSLHASoftSquaredMassName[#] <> " = (" <> - CreateSLHAFermionMixingMatrixName[vR] <> ".conjugate() * " <> - "MODELPARAMETER(" <> - CConversion`ToValidCSymbolString[#] <> ") * " <> - CreateSLHAFermionMixingMatrixName[vR] <> ".transpose()" <> - ").real();\n"; + CreateSLHASoftSquaredMassName[#] <> " = " <> + CConversion`CastTo[ + CreateSLHAFermionMixingMatrixName[vR] <> ".conjugate() * " <> + "MODELPARAMETER(" <> + CConversion`ToValidCSymbolString[#] <> ") * " <> + CreateSLHAFermionMixingMatrixName[vR] <> ".transpose()", + GetSLHASoftSquaredMassType[#] + ] <> ";\n"; ]; , Print["Warning: Cannot convert soft squared mass ", #, " to SLHA, because ", {vL,vR}, " are not defined", " or have incompatible dimension."]; result = result <> - CreateSLHASoftSquaredMassName[#] <> " = MODELPARAMETER(" <> - CConversion`ToValidCSymbolString[#] <> ").real();\n"; + CreateSLHASoftSquaredMassName[#] <> " = " <> + CConversion`CastTo[ + "MODELPARAMETER(" <> CConversion`ToValidCSymbolString[#] <> ")", + GetSLHASoftSquaredMassType[#] + ] <> ";\n"; ]; ]& /@ massSq; result From 26f4b5f79b4a67d724852cb6f52a61b8a94c91ef Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 12:12:47 +0200 Subject: [PATCH 148/158] fix indentation --- meta/FlexibleSUSY.m | 46 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/meta/FlexibleSUSY.m b/meta/FlexibleSUSY.m index 1083bd45d..c274b4c2d 100644 --- a/meta/FlexibleSUSY.m +++ b/meta/FlexibleSUSY.m @@ -1465,25 +1465,23 @@ corresponding tadpole is real or imaginary (only in models with CP (* Write the EDM c++ files *) WriteEDMClass[vertexRules_List, files_List] := -Module[{fields, diagrams, interfaceFunctions, - vertexFunctionData, definitions}, - fields = EDM`EDMCreateFields[]; - diagrams = EDM`EDMCreateDiagrams[]; - - interfaceFunctions = EDM`EDMCreateInterfaceFunctions[]; - vertexFunctionData = EDM`EDMCreateVertexFunctionData[vertexRules]; - definitions = EDM`EDMCreateDefinitions[vertexRules]; - - WriteOut`ReplaceInFiles[files, - { "@EDM_Fields@" -> fields, - "@EDM_Diagrams@" -> diagrams, - "@EDM_VertexFunctionData@" -> vertexFunctionData, - "@EDM_Definitions@" -> definitions, - "@EDM_InterfaceFunctionPrototypes@" -> interfaceFunctions[[1]], - "@EDM_InterfaceFunctionDefinitions@" -> interfaceFunctions[[2]], - Sequence @@ GeneralReplacementRules[] - } ]; - ]; + Module[{fields, diagrams, interfaceFunctions, + vertexFunctionData, definitions}, + fields = EDM`EDMCreateFields[]; + diagrams = EDM`EDMCreateDiagrams[]; + interfaceFunctions = EDM`EDMCreateInterfaceFunctions[]; + vertexFunctionData = EDM`EDMCreateVertexFunctionData[vertexRules]; + definitions = EDM`EDMCreateDefinitions[vertexRules]; + WriteOut`ReplaceInFiles[files, + { "@EDM_Fields@" -> fields, + "@EDM_Diagrams@" -> diagrams, + "@EDM_VertexFunctionData@" -> vertexFunctionData, + "@EDM_Definitions@" -> definitions, + "@EDM_InterfaceFunctionPrototypes@" -> interfaceFunctions[[1]], + "@EDM_InterfaceFunctionDefinitions@" -> interfaceFunctions[[2]], + Sequence @@ GeneralReplacementRules[] + } ]; + ]; EnableForBVPSolver[solver_, statements_String] := Module[{result = "#ifdef "}, @@ -2927,18 +2925,18 @@ corresponding tadpole is real or imaginary (only in models with CP FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.hpp"}]}, {FileNameJoin[{$flexiblesusyTemplateDir, "a_muon.cpp.in"}], FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_a_muon.cpp"}]}}]; - + Print["Creating class EDM"]; edmFields = DeleteDuplicates @ Cases[Observables`GetRequestedObservables[extraSLHAOutputBlocks], FlexibleSUSYObservable`EDM[p_[__]|p_] :> p]; EDM`EDMInitialize[]; EDM`EDMSetEDMFields[edmFields]; - + WriteEDMClass[Join[vertexRules, Vertices`VertexRules[EDM`EDMNPointFunctions[], Lat$massMatrices]], {{FileNameJoin[{$flexiblesusyTemplateDir, "edm.hpp.in"}], - FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.hpp"}]}, - {FileNameJoin[{$flexiblesusyTemplateDir, "edm.cpp.in"}], - FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.cpp"}]}}]; + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.hpp"}]}, + {FileNameJoin[{$flexiblesusyTemplateDir, "edm.cpp.in"}], + FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> "_edm.cpp"}]}}]; PrintHeadline["Creating Mathematica interface"]; Print["Creating LibraryLink ", FileNameJoin[{FSOutputDir, FlexibleSUSY`FSModelName <> ".mx"}], " ..."]; From 884475cd9c83eec7a83f3efc4fd65b4be83cc081 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 12:27:13 +0200 Subject: [PATCH 149/158] calculate EDMs in all CP-violating models --- model_files/CMSSMCPV/FlexibleSUSY.m.in | 5 ++++- model_files/MSSMCPV/FlexibleSUSY.m.in | 5 ++++- model_files/NMSSMCPV/FlexibleSUSY.m.in | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/model_files/CMSSMCPV/FlexibleSUSY.m.in b/model_files/CMSSMCPV/FlexibleSUSY.m.in index 6bb6566c7..6053466f4 100644 --- a/model_files/CMSSMCPV/FlexibleSUSY.m.in +++ b/model_files/CMSSMCPV/FlexibleSUSY.m.in @@ -85,7 +85,10 @@ ExtraSLHAOutputBlocks = { {1, Hold[SUSYScale]}, {2, Hold[LowScale]} } }, {FlexibleSUSYLowEnergy, - {{21, FlexibleSUSYObservable`aMuon} } }, + {{21, FlexibleSUSYObservable`aMuon}, + {23, FlexibleSUSYObservable`EDM[Fe[1]]}, + {24, FlexibleSUSYObservable`EDM[Fe[2]]}, + {25, FlexibleSUSYObservable`EDM[Fe[3]]} } }, {EFFHIGGSCOUPLINGS, NoScale, {{1, FlexibleSUSYObservable`CpHiggsPhotonPhoton}, {2, FlexibleSUSYObservable`CpHiggsGluonGluon}, diff --git a/model_files/MSSMCPV/FlexibleSUSY.m.in b/model_files/MSSMCPV/FlexibleSUSY.m.in index 6a785b392..fe80a3c1e 100644 --- a/model_files/MSSMCPV/FlexibleSUSY.m.in +++ b/model_files/MSSMCPV/FlexibleSUSY.m.in @@ -93,7 +93,10 @@ ExtraSLHAOutputBlocks = { {1, Hold[SUSYScale]}, {2, Hold[LowScale]} } }, {FlexibleSUSYLowEnergy, - {{21, FlexibleSUSYObservable`aMuon} } }, + {{21, FlexibleSUSYObservable`aMuon}, + {23, FlexibleSUSYObservable`EDM[Fe[1]]}, + {24, FlexibleSUSYObservable`EDM[Fe[2]]}, + {25, FlexibleSUSYObservable`EDM[Fe[3]]} } }, {EFFHIGGSCOUPLINGS, NoScale, {{1, FlexibleSUSYObservable`CpHiggsPhotonPhoton}, {2, FlexibleSUSYObservable`CpHiggsGluonGluon}, diff --git a/model_files/NMSSMCPV/FlexibleSUSY.m.in b/model_files/NMSSMCPV/FlexibleSUSY.m.in index 667e2d19b..6adc274a9 100644 --- a/model_files/NMSSMCPV/FlexibleSUSY.m.in +++ b/model_files/NMSSMCPV/FlexibleSUSY.m.in @@ -98,6 +98,11 @@ ExtraSLHAOutputBlocks = { {{0, Hold[HighScale]}, {1, Hold[SUSYScale]}, {2, Hold[LowScale]} } }, + {FlexibleSUSYLowEnergy, + {{21, FlexibleSUSYObservable`aMuon}, + {23, FlexibleSUSYObservable`EDM[Fe[1]]}, + {24, FlexibleSUSYObservable`EDM[Fe[2]]}, + {25, FlexibleSUSYObservable`EDM[Fe[3]]} } }, {NMSSMRUN, {{1 , Re[\[Lambda]] }, {2 , Re[\[Kappa]] }, From f39c3efd58cafc4ebd1560ad40c430ce84d7ecb4 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 12:34:30 +0200 Subject: [PATCH 150/158] adding unit to the comment section in the SLHA output --- meta/Observables.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meta/Observables.m b/meta/Observables.m index cfcabb879..c1e3c414e 100644 --- a/meta/Observables.m +++ b/meta/Observables.m @@ -74,8 +74,8 @@ GetObservableDescription[obs_ /; obs === FlexibleSUSYObservable`CpHiggsGluonGluon] := "effective H-Gluon-Gluon coupling"; GetObservableDescription[obs_ /; obs === FlexibleSUSYObservable`CpPseudoScalarPhotonPhoton] := "effective A-Photon-Photon coupling"; GetObservableDescription[obs_ /; obs === FlexibleSUSYObservable`CpPseudoScalarGluonGluon] := "effective A-Gluon-Gluon coupling"; -GetObservableDescription[FlexibleSUSYObservable`EDM[p_[idx_]]] := GetObservableDescription[FlexibleSUSYObservable`EDM[p]] <> "(" <> ToString[idx] <> ")"; -GetObservableDescription[FlexibleSUSYObservable`EDM[p_]] := "electric dipole moment of " <> CConversion`ToValidCSymbolString[p]; +GetObservableDescription[FlexibleSUSYObservable`EDM[p_[idx_]]] := "electric dipole moment of " <> CConversion`ToValidCSymbolString[p] <> "(" <> ToString[idx] <> ") [1/GeV]"; +GetObservableDescription[FlexibleSUSYObservable`EDM[p_]] := "electric dipole moment of " <> CConversion`ToValidCSymbolString[p] <> " [1/GeV]"; GetObservableType[obs_ /; obs === FlexibleSUSYObservable`aMuon] := CConversion`ScalarType[CConversion`realScalarCType]; GetObservableType[obs_ /; obs === FlexibleSUSYObservable`aMuonUncertainty] := CConversion`ScalarType[CConversion`realScalarCType]; From 3e27390866cf4dc6ee5dd8a2a28f6e935410bfa0 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 12:34:58 +0200 Subject: [PATCH 151/158] update ChangeLog --- ChangeLog | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ChangeLog b/ChangeLog index 39452ae74..82fa4118c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -40,6 +40,28 @@ FlexibleSUSY 2.0.0 [not released yet] Thanks to Jobst Ziebell. + * Feature: BSM contributions to the electric dipole moment of + fermions at the 1L level in any given BSM model. Note: Diagrams + with non-SM vector bosons are not taken into account. + + In order to let FlexibleSUSY calculate the EDM of a fermion F, the + symbol FlexibleSUSYObservable`EDM[F] must be written into an SLHA + output block in the ExtraSLHAOutputBlocks variable in the + FlexibleSUSY model file. If F is a multiplet, the field index must + be specified, for example FlexibleSUSYObservable`EDM[F[1]] for the + first field in the multiplet. + + Example: + + ExtraSLHAOutputBlocks = { + {FlexibleSUSYLowEnergy, + {{23, FlexibleSUSYObservable`EDM[Fe[1]]}, + {24, FlexibleSUSYObservable`EDM[Fe[2]]}, + {25, FlexibleSUSYObservable`EDM[Fe[3]]} } } + }; + + Thanks to Jobst Ziebell. + * Feature: New functions, FSGetProblems[], FSGetWarnings[] and FSToSLHA[], have been added to FlexibleSUSY's spectrum generator Mathematica interface. The first From 3e38312b582e0079c5eceb4331db6cdd5f75a592 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 16:15:11 +0200 Subject: [PATCH 152/158] test aMuon in the CMSSM --- test/test_CMSSM_librarylink.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_CMSSM_librarylink.m b/test/test_CMSSM_librarylink.m index 125bf9d50..7f08c3814 100644 --- a/test/test_CMSSM_librarylink.m +++ b/test/test_CMSSM_librarylink.m @@ -94,7 +94,8 @@ {CpHGG1, {0}, {EFFHIGGSCOUPLINGS, 25, 21, 21}}, {CpHGG2, {0}, {EFFHIGGSCOUPLINGS, 35, 21, 21}}, {CpAPP, {0}, {EFFHIGGSCOUPLINGS, 36, 22, 22}}, - {CpAGG, {0}, {EFFHIGGSCOUPLINGS, 36, 21, 21}} + {CpAGG, {0}, {EFFHIGGSCOUPLINGS, 36, 21, 21}}, + {aMuon, {0}, {FlexibleSUSYLowEnergy, 21}} }; slhaData = ReadSLHAString[slhaStr, parameters]; @@ -128,6 +129,7 @@ TestCloseRel[{CpHGG1, CpHGG2} /. slhaData, Abs[FlexibleSUSYObservable`CpHiggsGluonGluon] /. obsML, delta]; TestCloseRel[CpAPP /. slhaData, Abs[FlexibleSUSYObservable`CpPseudoScalarPhotonPhoton /. obsML], delta]; TestCloseRel[CpAGG /. slhaData, Abs[FlexibleSUSYObservable`CpPseudoScalarGluonGluon /. obsML], delta]; +TestCloseRel[aMuon /. slhaData, FlexibleSUSYObservable`aMuon /. obsML, delta]; TestEquality[probML, {}]; TestEquality[warnML, {}]; From 027526949d7c1454df8042baee5b2643abccc6a8 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 16:59:37 +0200 Subject: [PATCH 153/158] adding overloads to allow rules to numbers --- src/mathlink_utils.hpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/mathlink_utils.hpp b/src/mathlink_utils.hpp index 1a6c75ddc..4cf1a641f 100644 --- a/src/mathlink_utils.hpp +++ b/src/mathlink_utils.hpp @@ -125,8 +125,22 @@ inline void MLPutRule(MLINK link, const std::string& name, const std::vector(name.c_str()), name.size()); } -template -void MLPutRuleTo(MLINK link, T t, const std::string& name, const std::vector& heads = {}) +inline void MLPutRule(MLINK link, int number, const std::vector& heads = {}) +{ + MLPutFunction(link, "Rule", 2); + MLPutHeads(link, heads); + MLPutInteger(link, number); +} + +inline void MLPutRule(MLINK link, long number, const std::vector& heads = {}) +{ + MLPutFunction(link, "Rule", 2); + MLPutHeads(link, heads); + MLPutLongInteger(link, number); +} + +template +void MLPutRuleTo(MLINK link, T1 t, const T2& name, const std::vector& heads = {}) { MLPutRule(link, name, heads); MLPut(link, t); From 1047af61d62434f7f2edc72ef0e77a77b53b41ed Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 17:00:03 +0200 Subject: [PATCH 154/158] rewrite rules to EDMs in terms of heads to avoid a LibraryLink error. --- meta/FSMathLink.m | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/meta/FSMathLink.m b/meta/FSMathLink.m index 3235d3a2a..85ca0b504 100644 --- a/meta/FSMathLink.m +++ b/meta/FSMathLink.m @@ -164,9 +164,20 @@ PutSpectrum[pars_List, link_String] := StringJoin[PutParameter[#,link]& /@ pars]; -PutObservable[obs_, type_, link_String] := - "MLPutRuleTo(" <> link <> ", OBSERVABLE(" <> Observables`GetObservableName[obs] <> - "), \"" <> ToString[obs] <> "\");\n"; +ObsToStr[obs_?NumericQ] := ToString[obs]; +ObsToStr[obs_] := "\"" <> ToString[obs] <> "\""; + +HeadToStr[sym_] := "\"" <> ToString[sym] <> "\""; +HeadsToStr[{}] := ""; +HeadsToStr[l_List] := ", {" <> StringJoin[Riffle[HeadToStr /@ l, ", "]] <> "}"; + +PutObservable[obs_[sub_], type_, link_String, heads_:{}] := + PutObservable[sub, type, link, Join[heads, {obs}]]; + +PutObservable[obs_, type_, link_String, heads_:{}] := + "MLPutRuleTo(" <> link <> ", OBSERVABLE(" <> + Observables`GetObservableName[Composition[Sequence @@ heads][obs]] <> + "), " <> ObsToStr[obs] <> HeadsToStr[heads] <> ");\n"; PutObservables[obs_List, link_String] := StringJoin[PutObservable[#, Observables`GetObservableType[#], link]& /@ obs]; From 4a04a945ea0e55c4cdc10977fc43660d78461284 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 7 Jun 2017 17:54:50 +0200 Subject: [PATCH 155/158] adding CMSSMCPV test Note: it is not 100% correct to comapre the SLHA output with the Mathematica output, because in the SLHA output there some parameters are converted to SLHA convention. --- test/module.mk | 50 +++++---- test/test_CMSSMCPV_librarylink.in.spc | 54 +++++++++ test/test_CMSSMCPV_librarylink.m | 153 ++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 24 deletions(-) create mode 100644 test/test_CMSSMCPV_librarylink.in.spc create mode 100644 test/test_CMSSMCPV_librarylink.m diff --git a/test/module.mk b/test/module.mk index f48b0847c..a6308a665 100644 --- a/test/module.mk +++ b/test/module.mk @@ -52,6 +52,30 @@ TEST_SH := \ $(DIR)/test_run_all_spectrum_generators.sh \ $(DIR)/test_space_dir.sh +TEST_META := \ + $(DIR)/test_BetaFunction.m \ + $(DIR)/test_CConversion.m \ + $(DIR)/test_Constraint.m \ + $(DIR)/test_EWSB.m \ + $(DIR)/test_LoopFunctions.m \ + $(DIR)/test_MSSM_2L_analytic.m \ + $(DIR)/test_MSSM_2L_mt.m \ + $(DIR)/test_MSSM_2L_yb_softsusy.m \ + $(DIR)/test_MSSM_2L_yt.m \ + $(DIR)/test_MSSM_2L_yt_loopfunction.m \ + $(DIR)/test_MSSM_2L_yt_softsusy.m \ + $(DIR)/test_Parameters.m \ + $(DIR)/test_ReadSLHA.m \ + $(DIR)/test_RGIntegrator.m \ + $(DIR)/test_SelfEnergies.m \ + $(DIR)/test_TextFormatting.m \ + $(DIR)/test_THDM_threshold_corrections.m \ + $(DIR)/test_THDM_threshold_corrections_gauge.m \ + $(DIR)/test_ThreeLoopQCD.m \ + $(DIR)/test_ThresholdCorrections.m \ + $(DIR)/test_TreeMasses.m \ + $(DIR)/test_Vertices.m + ifneq ($(findstring lattice,$(ALGORITHMS)),) TEST_SRC += endif @@ -273,6 +297,8 @@ endif ifeq ($(WITH_CMSSMCPV),yes) TEST_SRC += \ $(DIR)/test_CMSSMCPV_ewsb.cpp +TEST_META += \ + $(DIR)/test_CMSSMCPV_librarylink.m endif ifeq ($(WITH_CMSSMCPV) $(WITH_CMSSM),yes yes) @@ -379,30 +405,6 @@ TEST_META += \ $(DIR)/test_HGTHDM_THDM_threshold_corrections_scale_invariance.m endif -TEST_META := \ - $(DIR)/test_BetaFunction.m \ - $(DIR)/test_CConversion.m \ - $(DIR)/test_Constraint.m \ - $(DIR)/test_EWSB.m \ - $(DIR)/test_LoopFunctions.m \ - $(DIR)/test_MSSM_2L_analytic.m \ - $(DIR)/test_MSSM_2L_mt.m \ - $(DIR)/test_MSSM_2L_yb_softsusy.m \ - $(DIR)/test_MSSM_2L_yt.m \ - $(DIR)/test_MSSM_2L_yt_loopfunction.m \ - $(DIR)/test_MSSM_2L_yt_softsusy.m \ - $(DIR)/test_Parameters.m \ - $(DIR)/test_ReadSLHA.m \ - $(DIR)/test_RGIntegrator.m \ - $(DIR)/test_SelfEnergies.m \ - $(DIR)/test_TextFormatting.m \ - $(DIR)/test_THDM_threshold_corrections.m \ - $(DIR)/test_THDM_threshold_corrections_gauge.m \ - $(DIR)/test_ThreeLoopQCD.m \ - $(DIR)/test_ThresholdCorrections.m \ - $(DIR)/test_TreeMasses.m \ - $(DIR)/test_Vertices.m - ifeq ($(WITH_SM),yes) TEST_META += \ $(DIR)/test_SM_3loop_beta.m diff --git a/test/test_CMSSMCPV_librarylink.in.spc b/test/test_CMSSMCPV_librarylink.in.spc new file mode 100644 index 000000000..93cee4b1a --- /dev/null +++ b/test/test_CMSSMCPV_librarylink.in.spc @@ -0,0 +1,54 @@ +Block MODSEL # Select model +# 12 1000 # DRbar parameter output scale (GeV) +Block FlexibleSUSY + 0 1.000000000e-04 # precision goal + 1 0 # max. iterations (0 = automatic) + 2 0 # algorithm (0 = two_scale, 1 = lattice) + 3 0 # calculate SM pole masses + 4 2 # pole mass loop order + 5 2 # EWSB loop order + 6 3 # beta-functions loop order + 7 2 # threshold corrections loop order + 8 1 # Higgs 2-loop corrections O(alpha_t alpha_s) + 9 1 # Higgs 2-loop corrections O(alpha_b alpha_s) + 10 1 # Higgs 2-loop corrections O((alpha_t + alpha_b)^2) + 11 1 # Higgs 2-loop corrections O(alpha_tau^2) + 12 0 # force output + 13 1 # Top quark 2-loop corrections QCD + 14 1.000000000e-11 # beta-function zero threshold + 15 1 # calculate observables (a_muon, ...) + 16 0 # force positive majorana masses + 17 0 # pole mass renormalization scale (0 = SUSY scale) +Block FlexibleSUSYInput + 0 0.00729735 # alpha_em(0) + 1 125.09 # Mh pole +Block SMINPUTS # Standard Model inputs + 1 1.279340000e+02 # alpha^(-1) SM MSbar(MZ) + 2 1.166370000e-05 # G_Fermi + 3 1.176000000e-01 # alpha_s(MZ) SM MSbar + 4 9.118760000e+01 # MZ(pole) + 5 4.200000000e+00 # mb(mb) SM MSbar + 6 1.733000000e+02 # mtop(pole) + 7 1.777000000e+00 # mtau(pole) + 8 0.000000000e+00 # mnu3(pole) + 9 80.404 # MW pole + 11 5.109989020e-04 # melectron(pole) + 12 0.000000000e+00 # mnu1(pole) + 13 1.056583570e-01 # mmuon(pole) + 14 0.000000000e+00 # mnu2(pole) + 21 4.750000000e-03 # md(2 GeV) MS-bar + 22 2.400000000e-03 # mu(2 GeV) MS-bar + 23 1.040000000e-01 # ms(2 GeV) MS-bar + 24 1.270000000e+00 # mc(mc) MS-bar +Block MINPAR # Input parameters + 1 125. # m0 + 2 500. # m12 + 3 10. # TanBeta + 4 1 # SignMu + 5 0 # Azero +Block IMMINPAR + 2 10 # Imm12 + 4 0 # SinPhiMu + 5 10 # ImAzero +Block EXTPAR + 100 0.1 # etaInput diff --git a/test/test_CMSSMCPV_librarylink.m b/test/test_CMSSMCPV_librarylink.m new file mode 100644 index 000000000..79e2bcc77 --- /dev/null +++ b/test/test_CMSSMCPV_librarylink.m @@ -0,0 +1,153 @@ +Needs["TestSuite`", "TestSuite.m"]; +Needs["ReadSLHA`", "ReadSLHA.m"]; + +Get["models/CMSSMCPV/CMSSMCPV_librarylink.m"]; + +Print["Comparing SLHA output to LibraryLink output"]; + +settings = { + precisionGoal -> 0.0001, + maxIterations -> 0, + calculateStandardModelMasses -> 0, + poleMassLoopOrder -> 2, + ewsbLoopOrder -> 2, + betaFunctionLoopOrder -> 3, + thresholdCorrectionsLoopOrder -> 2, + higgs2loopCorrectionAtAs -> 1, + higgs2loopCorrectionAbAs -> 1, + higgs2loopCorrectionAtAt -> 1, + higgs2loopCorrectionAtauAtau -> 1, + forceOutput -> 0, + topPoleQCDCorrections -> 1, + betaZeroThreshold -> 1.*10^-11, + forcePositiveMasses -> 0, + poleMassScale -> 0., + parameterOutputScale -> 0. +}; + +smInputs = { + alphaEmMZ -> 1./127.934, + GF -> 0.0000116637, + alphaSMZ -> 0.1176, + MZ -> 91.1876, + mbmb -> 4.2, + Mt -> 173.3, + Mtau -> 1.777, + Mv3 -> 0, + MW -> 80.404, + Me -> 0.000510998902, + Mv1 -> 0., + Mm -> 0.105658357, + Mv2 -> 0., + md2GeV -> 0.00475, + mu2GeV -> 0.0024, + ms2GeV -> 0.104, + mcmc -> 1.27 +}; + +handle = FSCMSSMCPVOpenHandle[ + fsSettings -> settings, + fsSMParameters -> smInputs, + fsModelParameters -> { + m0 -> 125, m12 -> 500, TanBeta -> 10, CosPhiMu -> 1, Azero -> 0, + Imm12 -> 10, SinPhiMu -> 0, ImAzero -> 10, etaInput -> 0.1 + } +]; + +specML = CMSSMCPV /. FSCMSSMCPVCalculateSpectrum[handle]; +obsML = FSCMSSMCPVCalculateObservables[handle]; +probML = FSCMSSMCPVGetProblems[handle]; +warnML = FSCMSSMCPVGetWarnings[handle]; + +FSCMSSMCPVCloseHandle[handle]; + +inputFile = "test/test_CMSSMCPV_librarylink.in.spc"; +outputFile = "test/test_CMSSMCPV_librarylink.out.spc"; +cmd = "models/CMSSMCPV/run_CMSSMCPV.x --slha-input-file=" <> inputFile <> + " --slha-output-file=" <> outputFile; + +Run["rm -f " <> outputFile]; +Run[cmd]; +slhaStr = Import[outputFile, "String"]; + +parameters = { + {g1, {0} , {GAUGE, 1}}, + {g2, {0} , {GAUGE, 2}}, + {g3, {0} , {GAUGE, 3}}, + {Yu, {3, 3}, Yu}, + {Yd, {3, 3}, Yd}, + {Ye, {3, 3}, Ye}, + {Tu, {3, 3}, Tu}, + {Td, {3, 3}, Td}, + {Te, {3, 3}, Te}, + {ImTu, {3, 3}, ImTu}, + {ImTd, {3, 3}, ImTd}, + {ImTe, {3, 3}, ImTe}, + {mq2, {3, 3}, MSQ2}, + {ml2, {3, 3}, MSL2}, + {mu2, {3, 3}, MSU2}, + {md2, {3, 3}, MSD2}, + {me2, {3, 3}, MSE2}, + {Immq2, {3, 3}, ImMSQ2}, + {Imml2, {3, 3}, ImMSL2}, + {Immu2, {3, 3}, ImMSU2}, + {Immd2, {3, 3}, ImMSD2}, + {Imme2, {3, 3}, ImMSE2}, + {mHu2, {0}, {MSOFT, 22}}, + {mHd2, {0}, {MSOFT, 21}}, + {vu, {0}, {HMIX, 103}}, + {vd, {0}, {HMIX, 102}}, + {Mu, {0}, {HMIX, 1}}, + {BMu, {0}, {HMIX, 101}}, + {ImMu, {0}, {ImHMIX, 1}}, + {ImBMu, {0}, {ImHMIX, 101}}, + {CpHPP1, {0}, {EFFHIGGSCOUPLINGS, 25, 22, 22}}, + {CpHPP2, {0}, {EFFHIGGSCOUPLINGS, 35, 22, 22}}, + {CpHPP3, {0}, {EFFHIGGSCOUPLINGS, 36, 22, 22}}, + {CpHGG1, {0}, {EFFHIGGSCOUPLINGS, 25, 21, 21}}, + {CpHGG2, {0}, {EFFHIGGSCOUPLINGS, 35, 21, 21}}, + {CpHGG3, {0}, {EFFHIGGSCOUPLINGS, 36, 21, 21}}, + {aMuon, {0}, {FlexibleSUSYLowEnergy, 21}}, + {EDM[Fe[0]], {0}, {FlexibleSUSYLowEnergy, 23}}, + {EDM[Fe[1]], {0}, {FlexibleSUSYLowEnergy, 24}}, + {EDM[Fe[2]], {0}, {FlexibleSUSYLowEnergy, 25}} +}; + +slhaData = ReadSLHAString[slhaStr, parameters]; + +delta = 1*^-4; + +TestCloseRel[g1 * Sqrt[5/3] /. slhaData, g1 /. specML, delta]; +TestCloseRel[g2 /. slhaData, g2 /. specML, delta]; +TestCloseRel[g3 /. slhaData, g3 /. specML, delta]; +TestCloseRel[Abs[Yu] /. slhaData, Abs[Yu] /. specML, delta]; +TestCloseRel[Abs[Yd] /. slhaData, Abs[Yd] /. specML, delta]; +TestCloseRel[Abs[Ye] /. slhaData, Abs[Ye] /. specML, delta]; +TestCloseRel[Abs[Tu + I ImTu] /. slhaData, Abs[T[Yu]] /. specML, delta]; +TestCloseRel[Abs[Td + I ImTd] /. slhaData, Abs[T[Yd]] /. specML, delta]; +TestCloseRel[Abs[Te + I ImTe] /. slhaData, Abs[T[Ye]] /. specML, delta]; +TestCloseRel[Abs[mq2 + I Immq2] /. slhaData, Abs[mq2] /. specML, delta]; +TestCloseRel[Abs[ml2 + I Imml2] /. slhaData, Abs[ml2] /. specML, delta]; +TestCloseRel[Abs[mu2 + I Immu2] /. slhaData, Abs[mu2] /. specML, delta]; +TestCloseRel[Abs[md2 + I Immd2] /. slhaData, Abs[md2] /. specML, delta]; +TestCloseRel[Abs[me2 + I Imme2] /. slhaData, Abs[me2] /. specML, delta]; +TestCloseRel[mHu2 /. slhaData, mHu2 /. specML, delta]; +TestCloseRel[mHd2 /. slhaData, mHd2 /. specML, delta]; +TestCloseRel[vu /. slhaData, vu /. specML, delta]; +TestCloseRel[vd /. slhaData, vd /. specML, delta]; +TestCloseRel[Mu + I ImMu /. slhaData, \[Mu] /. specML, delta]; +TestCloseRel[BMu + I ImBMu /. slhaData, B[\[Mu]] /. specML, delta]; + +delta = 1*^-5; + +TestCloseRel[{CpHPP1, CpHPP2, CpHPP3} /. slhaData, Abs[FlexibleSUSYObservable`CpHiggsPhotonPhoton /. obsML], delta]; +TestCloseRel[{CpHGG1, CpHGG2, CpHGG3} /. slhaData, Abs[FlexibleSUSYObservable`CpHiggsGluonGluon] /. obsML, delta]; +TestCloseRel[aMuon /. slhaData, FlexibleSUSYObservable`aMuon /. obsML, delta]; +TestCloseRel[EDM[Fe[0]] /. slhaData, FlexibleSUSYObservable`EDM[Fe[0]] /. obsML, delta]; +TestCloseRel[EDM[Fe[1]] /. slhaData, FlexibleSUSYObservable`EDM[Fe[1]] /. obsML, delta]; +TestCloseRel[EDM[Fe[2]] /. slhaData, FlexibleSUSYObservable`EDM[Fe[2]] /. obsML, delta]; + +TestEquality[probML, {}]; +TestEquality[warnML, {}]; + +PrintTestSummary[]; From fa29b7459facc4889e6f7e374b0be13b78d731bf Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Thu, 8 Jun 2017 09:47:42 +0200 Subject: [PATCH 156/158] remove reference to SARAH`Electron which is not defined in some models, as in the MSSMNoFV for example. --- meta/EDM.m | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/meta/EDM.m b/meta/EDM.m index 370c0a45a..82641081c 100644 --- a/meta/EDM.m +++ b/meta/EDM.m @@ -44,8 +44,7 @@ If you add new kinds of vertices (e.g for new diagram types): ToString @ TreeMasses`GetDimension[#] <> ";\n"] <> "};\n" &) /@ fields, "\n"] <> "\n\n" <> "// Special field families\n" <> - "using Photon = " <> CXXNameOfField @ SARAH`Photon <> ";\n" <> - "using Electron = " <> CXXNameOfField @ SARAH`Electron <> ";\n\n" <> + "using Photon = " <> CXXNameOfField @ GetPhoton[] <> ";\n\n" <> "// Fields that are their own anti fields\n" <> StringJoin @ Riffle[("template<> struct " <> @@ -195,7 +194,7 @@ If you add new kinds of vertices (e.g for new diagram types): (**************** Other Functions ***************) -GetElectronIndex[] := If[TreeMasses`GetDimension[SARAH`Electron] =!= 1, 1, Null]; +GetPhoton[] := SARAH`Photon; IsLorentzIndex[index_] := StringMatchQ[ToString @ index, "lt" ~~ __]; @@ -215,8 +214,7 @@ If you add new kinds of vertices (e.g for new diagram types): ]; CreateEvaluationContextSpecializations[] := -Module[{fields, contributingDiagrams, photonEmitters, - electronDimension = TreeMasses`GetDimension[SARAH`Electron]}, +Module[{fields, contributingDiagrams, photonEmitters}, fields = Select[TreeMasses`GetParticles[], (! TreeMasses`IsGhost[#] &)]; contributingDiagrams = ContributingDiagrams[]; @@ -233,7 +231,7 @@ If you add new kinds of vertices (e.g for new diagram types): ] &) /@ fields, "\n\n"] <> "\n\n" <> StringJoin @ Riffle[(Module[{fieldInfo = CleanFieldInfo[#], - photonVertexType = VertexTypeForFields[{SARAH`Photon, #, SARAH`AntiField @ #}], + photonVertexType = VertexTypeForFields[{GetPhoton[], #, SARAH`AntiField @ #}], numberOfIndices}, numberOfIndices = Length @ fieldInfo[[5]]; @@ -263,7 +261,7 @@ If you add new kinds of vertices (e.g for new diagram types): Module[{edmField = #, diagrams = SARAH`InsFields[ {{C[#, SARAH`AntiField[SARAH`FieldToInsert[1]], SARAH`AntiField[SARAH`FieldToInsert[2]]], - C[SARAH`FieldToInsert[1], SARAH`Photon, + C[SARAH`FieldToInsert[1], GetPhoton[], SARAH`AntiField[SARAH`FieldToInsert[1]]], C[SARAH`FieldToInsert[1], SARAH`FieldToInsert[2], SARAH`AntiField[#]]}, @@ -313,7 +311,7 @@ If you add new kinds of vertices (e.g for new diagram types): VerticesForDiagram[Diagram[loopDiagram_OneLoopDiagram, edmField_, photonEmitter_, exchangeField_]] := Module[{edmVertex, photonVertex}, edmVertex = {SARAH`AntiField[edmField], photonEmitter, exchangeField}; - photonVertex = {SARAH`Photon, photonEmitter, SARAH`AntiField[photonEmitter]}; + photonVertex = {GetPhoton[], photonEmitter, SARAH`AntiField[photonEmitter]}; {edmVertex, photonVertex} ]; From 5ecdf73e89835c99fe6218be03cf7a83f8173812 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Tue, 13 Jun 2017 21:26:32 +0200 Subject: [PATCH 157/158] use up-to date value of GF in generated code Thanks to Markus Bach --- doc/librarylink.dox | 2 +- src/ew_input.hpp | 2 +- templates/LesHouches.in | 2 +- templates/librarylink.m.in | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/librarylink.dox b/doc/librarylink.dox index 433a2e569..6cb97baf2 100644 --- a/doc/librarylink.dox +++ b/doc/librarylink.dox @@ -227,7 +227,7 @@ _Output_: ~~~~~~~~~~~~~~~~~~~~{.m} { alphaEmMZ -> 0.00781763, (* alpha_em(MZ) in the SM(5), MS-bar *) - GF -> 0.0000116637, (* Fermi constant *) + GF -> 0.000011663787, (* Fermi constant *) alphaSMZ -> 0.1184, (* alpha_s(MZ) in the SM(5), MS-bar *) MZ -> 91.1876, (* Z pole mass *) mbmb -> 4.18, (* MS-bar bottom mass at Q = mb *) diff --git a/src/ew_input.hpp b/src/ew_input.hpp index da28676dc..75f1487af 100644 --- a/src/ew_input.hpp +++ b/src/ew_input.hpp @@ -80,7 +80,7 @@ namespace Electroweak_constants { const double PMNS_DELTA = 0.; const double PMNS_ALPHA1 = 0.; const double PMNS_ALPHA2 = 0.; - const double gfermi = 1.16637e-5; ///< Fermi constant G_F + const double gfermi = 1.1663787e-5; ///< Fermi constant G_F const double yeSM = 2.85784368E-06; ///< Ye(1,1) MS-bar in the SM at Q = MZ const double ymSM = 5.90911374E-04; ///< Ye(2,2) MS-bar in the SM at Q = MZ const double ylSM = 9.95869693E-03; ///< Ye(3,3) MS-bar in the SM at Q = MZ diff --git a/templates/LesHouches.in b/templates/LesHouches.in index 72efb2ebe..2d2610861 100644 --- a/templates/LesHouches.in +++ b/templates/LesHouches.in @@ -31,7 +31,7 @@ Block FlexibleSUSYInput 1 125.09 # Mh pole Block SMINPUTS # Standard Model inputs 1 1.279440000e+02 # alpha^(-1) SM MSbar(MZ) - 2 1.166380000e-05 # G_Fermi + 2 1.166378700e-05 # G_Fermi 3 1.184000000e-01 # alpha_s(MZ) SM MSbar 4 9.118760000e+01 # MZ(pole) 5 4.180000000e+00 # mb(mb) SM MSbar diff --git a/templates/librarylink.m.in b/templates/librarylink.m.in index bcb236e3c..8f40df0f9 100644 --- a/templates/librarylink.m.in +++ b/templates/librarylink.m.in @@ -64,7 +64,7 @@ fsDefaultSettings = { fsDefaultSMParameters = { alphaEmMZ -> 1/127.916, (* SMINPUTS[1] *) - GF -> 1.16637*^-5, (* SMINPUTS[2] *) + GF -> 1.1663787*^-5, (* SMINPUTS[2] *) alphaSMZ -> 0.1184, (* SMINPUTS[3] *) MZ -> 91.1876, (* SMINPUTS[4] *) mbmb -> 4.18, (* SMINPUTS[5] *) From 8df67a1863471fa1a85457d1136e98b3a714f690 Mon Sep 17 00:00:00 2001 From: Alexander Voigt Date: Wed, 14 Jun 2017 10:19:38 +0200 Subject: [PATCH 158/158] adding brackets for readability --- src/numerics.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/numerics.cpp b/src/numerics.cpp index 7029516b0..249e8f903 100644 --- a/src/numerics.cpp +++ b/src/numerics.cpp @@ -313,21 +313,20 @@ double b22(double p, double m1, double m2, double q) // m1 == m2 with good accuracy if (is_close(m1, m2, EPSTOL)) { answer = -m12 * log(sqr(m1 / q)) * 0.5 + m12 * 0.5; - } - else + } else { /// This zero p limit is good if (fabs(m1) > EPSTOL && fabs(m2) > EPSTOL) { answer = 0.375 * (m12 + m22) - 0.25 * (sqr(m22) * log(sqr(m2 / q)) - sqr(m12) * log(sqr(m1 / q))) / (m22 - m12); - } - else + } else { if (fabs(m1) < EPSTOL) { answer = 0.375 * m22 - 0.25 * m22 * log(sqr(m2 / q)); - } - else { + } else { answer = 0.375 * m12 - 0.25 * m12 * log(sqr(m1 / q)); } + } + } } else { const double b0Save = b0(p, m1, m2, q);