diff --git a/src/computational_graph/feynmangraph.jl b/src/computational_graph/feynmangraph.jl index 54393b5a..3bee49a2 100644 --- a/src/computational_graph/feynmangraph.jl +++ b/src/computational_graph/feynmangraph.jl @@ -489,7 +489,8 @@ julia> g.subgraphs ``` """ function feynman_diagram(subgraphs::Vector{FeynmanGraph{F,W}}, topology::Vector{Vector{Int}}, perm_noleg::Union{Vector{Int},Nothing}=nothing; - factor=one(_dtype.factor), weight=zero(_dtype.weight), name="", diagtype::DiagramType=GenericDiag(), is_signed::Bool=false) where {F,W} + contraction_orders::Union{Nothing,Vector{Vector{Int}}}=nothing, factor=one(F), weight=zero(W), + name="", diagtype::DiagramType=GenericDiag(), is_signed::Bool=false) where {F,W} # external_ops = OperatorProduct(operators[external]) # the external operators for the building diagram after contractions contraction = collect(Iterators.flatten(topology)) @@ -498,7 +499,11 @@ function feynman_diagram(subgraphs::Vector{FeynmanGraph{F,W}}, topology::Vector{ vertices, all_external_legs = OperatorProduct[], Bool[] external_leg, external_noleg = Int[], Int[] # index all leg/nonleg external operators ind = 0 + + orders_length = length(orders(subgraphs[1])) + diag_orders = zeros(Int, orders_length) for g in subgraphs + diag_orders += orders(g) diagram_type(g) == Propagator && continue # exclude propagator subgraph to avoid double counting. push!(vertices, external_operators(g)) append!(all_external_legs, external_legs(g)) @@ -534,13 +539,22 @@ function feynman_diagram(subgraphs::Vector{FeynmanGraph{F,W}}, topology::Vector{ sign = 1 end - for connection in topology - push!(subgraphs, propagator(operators[connection])) + if isnothing(contraction_orders) + for (i, connection) in enumerate(topology) + push!(subgraphs, propagator(operators[connection]; orders=zeros(Int, orders_length))) + end + else + for (i, connection) in enumerate(topology) + propagator_orders = zeros(Int, orders_length) + propagator_orders[eachindex(contraction_orders[i])] = contraction_orders[i] + push!(subgraphs, propagator(operators[connection]; orders=propagator_orders)) + diag_orders += propagator_orders + end end _external_indices = union(external_leg, external_noleg) _external_legs = append!([true for i in eachindex(external_leg)], [false for i in eachindex(external_noleg)]) return FeynmanGraph(subgraphs; topology=topology, external_indices=_external_indices, external_legs=_external_legs, vertices=vertices, - name=name, diagtype=diagtype, operator=Prod(), factor=factor * sign, weight=weight) + orders=diag_orders, name=name, diagtype=diagtype, operator=Prod(), factor=factor * sign, weight=weight) end # do nothing when already a OperatorProduct; @@ -554,13 +568,18 @@ _extract_vertex(::Type{<:FeynmanGraph}, g) = OperatorProduct(external_operators( Create a Propagator-type FeynmanGraph from given OperatorProduct or Vector{QuantumOperator} `ops`, including two quantum operators. """ -function propagator(ops::Union{OperatorProduct,Vector{QuantumOperator}}; +function propagator(ops::Union{OperatorProduct,Vector{QuantumOperator}}; orders::Union{Nothing,Vector{Int}}=nothing, name="", factor=one(_dtype.factor), weight=zero(_dtype.weight), operator=Sum()) @assert length(ops) == 2 @assert adjoint(ops[1].operator) == ops[2].operator sign, perm = correlator_order(OperatorProduct(ops)) - return FeynmanGraph(FeynmanGraph[]; topology=[[1, 2]], external_indices=perm, external_legs=[true, true], vertices=OperatorProduct.(ops), - diagtype=Propagator(), name=name, operator=operator, factor=factor * sign, weight=weight) + if isnothing(orders) + return FeynmanGraph(FeynmanGraph[]; topology=[[1, 2]], external_indices=perm, external_legs=[true, true], vertices=OperatorProduct.(ops), + diagtype=Propagator(), name=name, operator=operator, factor=factor * sign, weight=weight) + else + return FeynmanGraph(FeynmanGraph[]; topology=[[1, 2]], external_indices=perm, external_legs=[true, true], vertices=OperatorProduct.(ops), + orders=orders, diagtype=Propagator(), name=name, operator=operator, factor=factor * sign, weight=weight) + end end """ diff --git a/src/computational_graph/optimize.jl b/src/computational_graph/optimize.jl index b6e57e21..e37b669e 100644 --- a/src/computational_graph/optimize.jl +++ b/src/computational_graph/optimize.jl @@ -191,11 +191,13 @@ end # Returns: - The vector of unique leaf nodes. +- The vector of unique leaf nodes' index. - A mapping dictionary from the id of each unique leaf node to its index in collect(1:length(leafs)). """ function unique_leaves(graphs::AbstractVector{<:AbstractGraph}) ############### find the unique Leaves ##################### unique_graphs = [] + unique_graphs_id = Int[] mapping = Dict{Int,Int}() idx = 1 @@ -210,11 +212,12 @@ function unique_leaves(graphs::AbstractVector{<:AbstractGraph}) end if flag push!(unique_graphs, g) - mapping[id(g)] = idx + push!(unique_graphs_id, g.id) + mapping[g.id] = idx idx += 1 end end - return unique_graphs, mapping + return unique_graphs, unique_graphs_id, mapping end """ @@ -245,14 +248,18 @@ function remove_duplicated_leaves!(graphs::Union{Tuple,AbstractVector{<:Abstract sort!(leaves, by=x -> id(x)) #sort the id of the leaves in an asscend order unique!(x -> id(x), leaves) #filter out the leaves with the same id number - _unique_leaves, leafmap = unique_leaves(leaves) + _unique_leaves, uniqueleaves_id, mapping = unique_leaves(leaves) verbose > 0 && length(leaves) > 0 && println("Number of independent Leaves $(length(leaves)) → $(length(_unique_leaves))") + leafmap = Dict{Int,Int}() for g in graphs for n in PreOrderDFS(g) for (si, sub_g) in enumerate(subgraphs(n)) if isleaf(sub_g) - set_subgraph!(n, _unique_leaves[leafmap[id(sub_g)]], si) + set_subgraph!(n, _unique_leaves[mapping[id(sub_g)]], si) + if sub_g.id ∈ uniqueleaves_id + leafmap[sub_g.id] = mapping[sub_g.id] + end end end end diff --git a/src/frontend/GV.jl b/src/frontend/GV.jl index 6e4c1274..fbfc3e1b 100644 --- a/src/frontend/GV.jl +++ b/src/frontend/GV.jl @@ -15,32 +15,27 @@ include("GV_diagrams/readfile.jl") function eachorder_diag(type::Symbol, order::Int, VerOrder::Int=0, GOrder::Int=0; loopPool::Union{LoopPool,Nothing}=nothing, tau_labels::Union{Nothing,Vector{Int}}=nothing, GTypes::Union{Nothing,Vector{Int}}=nothing, VTypes::Union{Nothing,Vector{Int}}=nothing) - Generates a `Vector{FeynmanGraph}`: the polarization diagrams with static interactions of a given order, where the actual order of diagrams equals to `order + VerOrder + 2 * GOrder`. - Generates fermionic/bosonic `LabelProduct`: `fermi_labelProd`/`bose_labelProd` with inputs `tau_labels`, `GTypes`/`VTypes`, and updated `loopPool`. + Generates a `Vector{FeynmanGraph}`: the given-`type` diagrams with static interactions of a given order, where the actual order of diagrams equals to `order + VerOrder + 2 * GOrder`. + Generates a `LabelProduct`: `labelProd` with inputs `tau_labels` and all the possible momenta-loop basis. Generates external tau labels Vector{Vector{Int}}. The i-th labels (Vector{Int}) corresponds to the i-th `FeynmanGraph` in `Vector{FeynmanGraph}`. # Arguments: - `type` (Symbol): The type of the diagrams, including `:spinPolar`, `:chargePolar`, `:sigma`, `:green`, or `:freeEnergy`. - `order` (Int): The order of the diagrams without counterterms. -- `VerOrder` (Int, optional): The order of interaction counterterms (defaults to 0). - `GOrder` (Int, optional): The order of self-energy counterterms (defaults to 0). -- `dim` (Int, optional): The dimension of the system (defaults to 3). +- `VerOrder` (Int, optional): The order of interaction counterterms (defaults to 0). +- `labelProd` (Union{Nothing,LabelProduct}=nothing, optional): The initial cartesian QuantumOperator.label product (defaults to `nothing`). - `spinPolarPara` (Float64, optional): The spin-polarization parameter (n_up - n_down) / (n_up + n_down) (defaults to `0.0`). -- `loopPool` (Union{LoopPool,Nothing}=nothing, optional): The initial pool of loop momenta (defaults to `nothing`). - `tau_labels`(Union{Nothing, Vector{Int}}, optional): The labels for the discrete time of each vertex. (defaults to `nothing`). -- `GTypes`: The types of fermion propagators `G` in the diagrams (defaults to `collect(0:GOrder)`). -- `VTypes`: The types of boson static interaction `V` in the diagrams (defaults to `collect(0:VerOrder)`). # Returns A tuple `(diagrams, fermi_labelProd, bose_labelProd, extT_labels)` where - `diagrams` is a `Vector{FeynmanGraph}` object representing the diagrams, -- `fermi_labelProd` is a `LabelProduct` object containing the labels for the fermionic `G` objects in the diagrams, -- `bose_labelProd` is a `LabelProduct` object containing the labels for the bosonic `W` objects in the diagrams. +- `labelProd` is a `LabelProduct` object containing the labels for the leaves of graphs, - `extT_labels` is a `Vector{Vector{Int}}` object containing the external tau labels for each `FeynmanGraph` in `diagrams`. """ -function eachorder_diag(type::Symbol, order::Int, GOrder::Int=0, VerOrder::Int=0; dim::Int=3, spinPolarPara::Float64=0.0, - loopPool::Union{LoopPool,Nothing}=nothing, tau_labels::Union{Nothing,Vector{Int}}=nothing, - GTypes::Union{Nothing,Vector{Int}}=nothing, VTypes::Union{Nothing,Vector{Int}}=nothing) +function eachorder_diag(type::Symbol, order::Int, GOrder::Int=0, VerOrder::Int=0; + labelProd::Union{Nothing,LabelProduct}=nothing, spinPolarPara::Float64=0.0, tau_labels::Union{Nothing,Vector{Int}}=nothing) diagtype = :polar if type == :spinPolar filename = string(@__DIR__, "/GV_diagrams/groups_spin/Polar$(order)_$(VerOrder)_$(GOrder).diag") @@ -61,40 +56,37 @@ function eachorder_diag(type::Symbol, order::Int, GOrder::Int=0, VerOrder::Int=0 end # println("Reading ", filename) - if isnothing(GTypes) - GTypes = collect(0:GOrder) - type == :sigma_old && append!(GTypes, [-2, -3]) - # type == :green && push!(GTypes, -2) - type in [:green, :sigma] && push!(GTypes, -2) + if isnothing(labelProd) + return read_diagrams(filename; tau_labels=tau_labels, diagType=diagtype, spinPolarPara=spinPolarPara) + else + return read_diagrams(filename; labelProd=labelProd, diagType=diagtype, spinPolarPara=spinPolarPara) end - isnothing(VTypes) && (VTypes = collect(0:VerOrder)) - return read_diagrams(filename; dim=dim, loopPool=loopPool, tau_labels=tau_labels, GTypes=GTypes, VTypes=VTypes, - diagType=diagtype, spinPolarPara=spinPolarPara) end """ - function diagdictGV(type::Symbol, MaxOrder::Int, has_counterterm::Bool=false, dim::Int=3) + function diagdictGV(type::Symbol, MaxOrder::Int, has_counterterm::Bool=false; + MinOrder::Int=1, spinPolarPara::Float64=0.0) - Generates a FeynmanGraph Dict: the `dim`-dimensional spin/charge polarization or self-energy diagrams with static interactions in a given `type`, to a given maximum order `MaxOrder`, with switchable couterterms. - Generates fermionic/bosonic `LabelProduct`: `fermi_labelProd`/`bose_labelProd` for these FeynmanGraphs. + Generates a FeynmanGraph Dict: the Feynman diagrams with static interactions in a given `type`, and + spin-polarizaition parameter `spinPolarPara`, to given minmimum/maximum orders `MinOrder/MaxOrder`, with switchable couterterms. + Generates a `LabelProduct`: `labelProd` for these FeynmanGraphs. Generates a leafMap for mapping `g.id` to the index of unique leaf. # Arguments: - `type` (Symbol): The type of the Feynman diagrams, including `:spinPolar`, `:chargePolar`, `:sigma_old`, `:green`, or `:freeEnergy`. - `Maxorder` (Int): The maximum actual order of the diagrams. - `has_counterterm` (Bool): `false` for G0W0, `true` for GW with self-energy and interaction counterterms (defaults to `false`). -- `dim` (Int): The dimension of the system (defaults to 3). +- `MinOrder` (Int, optional): The minmimum actual order of the diagrams (defaults to `1`). - `spinPolarPara` (Float64, optional): The spin-polarization parameter (n_up - n_down) / (n_up + n_down) (defaults to `0.0`). # Returns A tuple `(dict_graphs, fermi_labelProd, bose_labelProd, leafMap)` where - `dict_graphs` is a `Dict{Tuple{Int,Int,Int},Tuple{Vector{FeynmanGraph},Vector{Vector{Int}}}}` object representing the diagrams. The key is (order, Gorder, Vorder). The element is a Tuple (graphVector, extT_labels). -- `fermi_labelProd` is a `LabelProduct` object containing the labels for the fermionic `G` objects in the diagrams, -- `bose_labelProd` is a `LabelProduct` object containing the labels for the bosonic `W` objects in the diagrams. +- `labelProd` is a `LabelProduct` object containing the labels for the leaves of graphs, - `leafMap` maps `g.id` to the index of unique leaf. """ -function diagdictGV(type::Symbol, MaxOrder::Int, has_counterterm::Bool=false, dim::Int=3; +function diagdictGV(type::Symbol, MaxOrder::Int, has_counterterm::Bool=false; MinOrder::Int=1, spinPolarPara::Float64=0.0) dict_graphs = Dict{Tuple{Int,Int,Int},Tuple{Vector{FeynmanGraph{_dtype.factor,_dtype.weight}},Vector{Vector{Int}}}}() if type == :sigma_old @@ -116,71 +108,62 @@ function diagdictGV(type::Symbol, MaxOrder::Int, has_counterterm::Bool=false, di else error("no support for $type diagram") end - loopPool = LoopPool(:K, dim, MaxLoopNum, Float64) + loopbasis = [vcat([1.0], [0.0 for _ in 2:MaxLoopNum])] + # Create label product + labelProd = LabelProduct(tau_labels, loopbasis) leafMap = Dict{Tuple{Int,Int,Int},Dict{Int,Int}}() if has_counterterm - GTypes = collect(0:MaxOrder-MinOrder) - type == :sigma_old && append!(GTypes, [-2, -3]) - type in [:green, :sigma] && push!(GTypes, -2) - type == :freeEnergy && push!(GTypes, -1) - VTypes = collect(0:MaxOrder-1) + Gorders = 0:MaxOrder-MinOrder + Vorders = 0:MaxOrder-1 for order in MinOrder:MaxOrder - for VerOrder in VTypes + for VerOrder in Vorders type in [:chargePolar, :spinPolar] && order == 1 && VerOrder > 0 && continue order == 0 && VerOrder > 0 && continue - for GOrder in collect(0:MaxOrder-MinOrder) + for GOrder in Gorders order + VerOrder + GOrder > MaxOrder && continue - gvec, fermi_labelProd, bose_labelProd, extT_labels = eachorder_diag(type, order, GOrder, VerOrder; - dim=dim, loopPool=loopPool, tau_labels=tau_labels, GTypes=GTypes, VTypes=VTypes, spinPolarPara=spinPolarPara) + gvec, labelProd, extT_labels = eachorder_diag(type, order, GOrder, VerOrder; + labelProd=labelProd, spinPolarPara=spinPolarPara) key = (order, GOrder, VerOrder) dict_graphs[key] = (gvec, extT_labels) - loopPool = fermi_labelProd.labels[3] leafMap[key] = IR.optimize!(gvec) end end end else - GTypes, VTypes = [0], [0] - type == :sigma_old && append!(GTypes, [-2, -3]) - type in [:green, :sigma] && push!(GTypes, -2) for order in 1:MaxOrder - gvec, fermi_labelProd, bose_labelProd, extT_labels = eachorder_diag(type, order; - loopPool=loopPool, tau_labels=tau_labels, GTypes=GTypes, VTypes=VTypes, spinPolarPara=spinPolarPara) + gvec, labelProd, extT_labels = eachorder_diag(type, order; + labelProd=labelProd, spinPolarPara=spinPolarPara) key = (order, 0, 0) dict_graphs[key] = (gvec, extT_labels) - loopPool = fermi_labelProd.labels[3] leafMap[key] = IR.optimize!(gvec) end end - fermi_labelProd = LabelProduct(tau_labels, GTypes, loopPool) - bose_labelProd = LabelProduct(tau_labels, VTypes, loopPool) - return dict_graphs, fermi_labelProd, bose_labelProd, leafMap + return dict_graphs, labelProd, leafMap end """ - function diagdictGV(type::Symbol, MaxOrder::Int, has_counterterm::Bool=false, dim::Int=3) + function diagdictGV(type::Symbol, gkeys::Vector{Tuple{Int,Int,Int}}; spinPolarPara::Float64=0.0) - Generates a FeynmanGraph Dict: the `dim`-dimensional spin/charge polarization or self-energy diagrams with static interactions in a given `type`, to a given maximum order `MaxOrder`, with switchable couterterms. - Generates fermionic/bosonic `LabelProduct`: `fermi_labelProd`/`bose_labelProd` for these FeynmanGraphs. + Generates a FeynmanGraph Dict: the Feynman diagrams with static interactions in the given `type` and + spin-polarizaition parameter `spinPolarPara`, with given couterterm-orders (from `gkeys`). + Generates a `LabelProduct`: `labelProd` for these FeynmanGraphs. Generates a leafMap for mapping `g.id` to the index of unique leaf. # Arguments: - `type` (Symbol): The type of the Feynman diagrams, including `:spinPolar`, `:chargePolar`, `:sigma_old`, `:green`, or `:freeEnergy`. - `gkeys` (Vector{Tuple{Int,Int,Int}}): The (order, Gorder, Vorder) of the diagrams. Gorder is the order of self-energy counterterms, and Vorder is the order of interaction counterterms. -- `dim` (Int): The dimension of the system (defaults to 3). - `spinPolarPara` (Float64, optional): The spin-polarization parameter (n_up - n_down) / (n_up + n_down) (defaults to `0.0`). # Returns A tuple `(dict_graphs, fermi_labelProd, bose_labelProd, leafMap)` where - `dict_graphs` is a `Dict{Tuple{Int,Int,Int},Tuple{Vector{FeynmanGraph},Vector{Vector{Int}}}}` object representing the diagrams. The key is (order, Gorder, Vorder). The element is a Tuple (graphVector, extT_labels). -- `fermi_labelProd` is a `LabelProduct` object containing the labels for the fermionic `G` objects in the diagrams, -- `bose_labelProd` is a `LabelProduct` object containing the labels for the bosonic `W` objects in the diagrams. +- `labelProd` is a `LabelProduct` object containing the labels for the leaves of graphs, - `leafMap` maps `g.id` to the index of unique leaf. """ -function diagdictGV(type::Symbol, gkeys::Vector{Tuple{Int,Int,Int}}, dim::Int=3; spinPolarPara::Float64=0.0) +function diagdictGV(type::Symbol, gkeys::Vector{Tuple{Int,Int,Int}}; spinPolarPara::Float64=0.0) dict_graphs = Dict{Tuple{Int,Int,Int},Tuple{Vector{FeynmanGraph{_dtype.factor,_dtype.weight}},Vector{Vector{Int}}}}() if type == :sigma_old MaxLoopNum = maximum([key[1] for key in gkeys]) + 2 @@ -201,56 +184,45 @@ function diagdictGV(type::Symbol, gkeys::Vector{Tuple{Int,Int,Int}}, dim::Int=3; else error("no support for $type diagram") end - MaxGOrder = maximum([key[2] for key in gkeys]) - MaxVerOrder = maximum([key[3] for key in gkeys]) - loopPool = LoopPool(:K, dim, MaxLoopNum, Float64) - GTypes = collect(0:MaxGOrder) - type == :sigma_old && append!(GTypes, [-2, -3]) - type in [:green, :sigma] && push!(GTypes, -2) - type == :freeEnergy && push!(GTypes, -1) - VTypes = collect(0:MaxVerOrder) + loopbasis = [vcat([1.0], [0.0 for _ in 2:MaxLoopNum])] + # Create label product + labelProd = LabelProduct(tau_labels, loopbasis) # graphvector = Vector{_dtype.factor,_dtype.weight}() leafMap = Dict{eltype(gkeys),Dict{Int,Int}}() for key in gkeys - gvec, fermi_labelProd, bose_labelProd, extT_labels = eachorder_diag(type, key...; - dim=dim, loopPool=loopPool, tau_labels=tau_labels, GTypes=GTypes, VTypes=VTypes, spinPolarPara=spinPolarPara) + gvec, labelProd, extT_labels = eachorder_diag(type, key...; + labelProd=labelProd, spinPolarPara=spinPolarPara) dict_graphs[key] = (gvec, extT_labels) - loopPool = fermi_labelProd.labels[3] + # loopPool = fermi_labelProd.labels[3] leafMap[key] = IR.optimize!(gvec) # append!(graphvector, gvec) end # IR.optimize!(graphvector) - fermi_labelProd = LabelProduct(tau_labels, GTypes, loopPool) - bose_labelProd = LabelProduct(tau_labels, VTypes, loopPool) - return dict_graphs, fermi_labelProd, bose_labelProd, leafMap + return dict_graphs, labelProd, leafMap end """ - function leafstates( - FeynGraphs::Dict{T, Tuple{Vector{G}, Vector{Vector{Int}}}}, - FermiLabel::LabelProduct, BoseLabel::LabelProduct, - graph_keys::Vector{T} - ) where {T, G<:FeynmanGraph} + function leafstates(FeynGraphs::Dict{T,Tuple{Vector{G},Vector{Vector{Int}}}}, + labelProd::LabelProduct, graph_keys::Vector{T}) where {T,G<:FeynmanGraph} Extracts leaf information from a Dict collection of Feynman graphs (`FeynGraphs` with its keys `graph_keys`) - and their associated LabelProduct data (`FermiLabel` and `BoseLabel`). + and their associated LabelProduct data (`labelProd`). The information includes their initial value, type, in/out time, and loop momenta. # Arguments: - `FeynGraphs`: A dictionary mapping keys of type T to tuples containing a vector of `FeynmanGraph` objects and a vector of external time labels. -- `FermiLabel`: A LabelProduct used to label the fermionic `G` objects in the graphs. -- `BoseLabel`: A LabelProduct used to label bosonic `W` objects in the graphs. +- `labelProd`: A LabelProduct used to label the leaves of graphs. - `graph_keys`: A vector containing keys of type `T`, specifying which graphs to analyze. # Returns -- A tuple of vectors containing information about the leaves in the graphs, including their initial values, types, input and output time indexes, and loop-momenta indexes. +- A tuple of vectors containing information about the leaves of graphs, including their initial values, types, input and output time indexes, and loop-momenta indexes. - A Vector{Vector{Int}} representing the external tau variables of each vector of graph corresponding to each key of type `T`. """ function leafstates(FeynGraphs::Dict{T,Tuple{Vector{G},Vector{Vector{Int}}}}, - FermiLabel::LabelProduct, BoseLabel::LabelProduct, graph_keys::Vector{T}) where {T,G<:FeynmanGraph} + labelProd::LabelProduct, graph_keys::Vector{T}) where {T,G<:FeynmanGraph} #read information of each leaf from the generated graph and its LabelProduct, the information include type, loop momentum, imaginary time. num_g = length(graph_keys) ExtT_index = [Vector{Vector{Int}}() for _ in 1:num_g] @@ -278,27 +250,22 @@ function leafstates(FeynGraphs::Dict{T,Tuple{Vector{G},Vector{Vector{Int}}}}, push!(leafType[ikey], 0) In = Out = vertices[1][1].label push!(leafLoopIndex[ikey], 1) - push!(leafInTau[ikey], FermiLabel[In][1]) - push!(leafOutTau[ikey], FermiLabel[Out][1]) + push!(leafInTau[ikey], labelProd[In][1]) + push!(leafOutTau[ikey], labelProd[Out][1]) push!(leafValue[ikey], 1.0) elseif IR.diagram_type(g) == IR.Propagator if (Op.isfermionic(vertices[1])) In, Out = vertices[2][1].label, vertices[1][1].label - if FermiLabel[In][2] in [-2, -3] - push!(leafType[ikey], 0) - push!(leafLoopIndex[ikey], 1) - else - push!(leafType[ikey], FermiLabel[In][2] * 2 + 1) - push!(leafLoopIndex[ikey], FrontEnds.linear_to_index(FermiLabel, In)[end]) #the label of LoopPool for each fermionic leaf - end - push!(leafInTau[ikey], FermiLabel[In][1]) - push!(leafOutTau[ikey], FermiLabel[Out][1]) + push!(leafType[ikey], g.orders[1] * 2 + 1) + push!(leafLoopIndex[ikey], FrontEnds.linear_to_index(labelProd, In)[end]) #the label of LoopPool for each fermionic leaf + push!(leafInTau[ikey], labelProd[In][1]) + push!(leafOutTau[ikey], labelProd[Out][1]) else In, Out = vertices[2][1].label, vertices[1][1].label - push!(leafType[ikey], BoseLabel[In][2] * 2 + 2) - push!(leafLoopIndex[ikey], FrontEnds.linear_to_index(BoseLabel, In)[end]) #the label of LoopPool for each bosonic leaf - push!(leafInTau[ikey], BoseLabel[In][1]) - push!(leafOutTau[ikey], BoseLabel[Out][1]) + push!(leafType[ikey], g.orders[2] * 2 + 2) + push!(leafLoopIndex[ikey], FrontEnds.linear_to_index(labelProd, In)[end]) #the label of LoopPool for each bosonic leaf + push!(leafInTau[ikey], labelProd[In][1]) + push!(leafOutTau[ikey], labelProd[Out][1]) end push!(leafValue[ikey], 1.0) end diff --git a/src/frontend/GV_diagrams/readfile.jl b/src/frontend/GV_diagrams/readfile.jl index 6509890a..333dc164 100644 --- a/src/frontend/GV_diagrams/readfile.jl +++ b/src/frontend/GV_diagrams/readfile.jl @@ -71,9 +71,8 @@ A tuple `(diagrams, fermi_labelProd, bose_labelProd)` where - `fermi_labelProd` is a `LabelProduct` object containing the labels for the fermionic `G` objects in the diagrams, - `bose_labelProd` is a `LabelProduct` object containing the labels for the bosonic `W` objects in the diagrams. """ -function read_diagrams(filename::AbstractString; loopPool::Union{LoopPool,Nothing}=nothing, spinPolarPara::Float64=0.0, - dim::Int=3, tau_labels::Union{Nothing,Vector{Int}}=nothing, GTypes=[0, 1], VTypes=[0, 1, 2], - # keywords::Vector{String}=["Polarization", "DiagNum", "Order", "GNum", "Ver4Num", "LoopNum", "ExtLoopIndex", +function read_diagrams(filename::AbstractString; labelProd::Union{Nothing,LabelProduct}=nothing, + spinPolarPara::Float64=0.0, tau_labels::Union{Nothing,Vector{Int}}=nothing, keywords::Vector{String}=["SelfEnergy", "DiagNum", "Order", "GNum", "Ver4Num", "LoopNum", "ExtLoopIndex", "DummyLoopIndex", "TauNum", "ExtTauIndex", "DummyTauIndex"], diagType=:polar ) @@ -85,7 +84,6 @@ function read_diagrams(filename::AbstractString; loopPool::Union{LoopPool,Nothin extIndex = Int[] GNum = 2 lineNum = 1 - # filename[1:5] == "Sigma" && keywords[1] = "SelfEnergy" while true line = readline(io) length(line) == 0 && break @@ -110,37 +108,26 @@ function read_diagrams(filename::AbstractString; loopPool::Union{LoopPool,Nothin if isnothing(tau_labels) tau_labels = collect(1:tauNum) end - # current_labels = CurrentLabels(loopNum) - # innerlabels = [] - # GTypeNum >1 && push!(innerlabels, collect(1:GTypeNum)) - # WTypeNum >1 && push!(innerlabels, collect(1:WTypeNum)) - # labelProd = LabelProduct(tau_labels, current_labels, innerlabels...) - - # Create label product - fermi_labelProd = LabelProduct(tau_labels, GTypes) - bose_labelProd = LabelProduct(tau_labels, VTypes) - - # Create loop pool if not provided - if isnothing(loopPool) - loopPool = LoopPool(:K, dim, loopNum, Float64) + if isnothing(labelProd) + loopbasis = [vcat([1.0], [0.0 for _ in 2:loopNum])] + # Create label product + labelProd = LabelProduct(tau_labels, loopbasis) + maxloopNum = loopNum + else + maxloopNum = length(labelProd[1][end]) end # Read one diagram at a time diagrams = FeynmanGraph{_dtype.factor,_dtype.weight}[] extT_labels = Vector{Int}[] offset_ver4 = diagType == :sigma ? 1 : 0 - for i in 1:diagNum - diag, loopPool, extTlabel = read_onediagram(IOBuffer(readuntil(io, "\n\n")), - GNum, verNum, loopNum, extIndex, fermi_labelProd, bose_labelProd, loopPool, spinPolarPara; - offset_ver4=offset_ver4, diagType=diagType) + for _ in 1:diagNum + diag, labelProd, extTlabel = read_onediagram!(IOBuffer(readuntil(io, "\n\n")), + GNum, verNum, loopNum, extIndex, labelProd, spinPolarPara; maxLoopNum=maxloopNum, offset_ver4=offset_ver4, diagType=diagType) push!(diagrams, diag) push!(extT_labels, extTlabel) end - - # Create new label products with loop pool close(io) - fermi_labelProd = LabelProduct(tau_labels, GTypes, loopPool) - bose_labelProd = LabelProduct(tau_labels, VTypes, loopPool) if diagType in [:sigma, :sigma_old] @assert length(extIndex) == 2 @@ -151,18 +138,17 @@ function read_diagrams(filename::AbstractString; loopPool::Union{LoopPool,Nothin for key in extT_labels push!(graphvec, IR.linear_combination(gr[key], ones(_dtype.factor, length(gr[key])))) end - return graphvec, fermi_labelProd, bose_labelProd, extT_labels + return graphvec, labelProd, extT_labels else unique!(extT_labels) @assert length(extT_labels) == 1 - # return IR.linear_combination(diagrams, ones(_dtype.factor, diagNum)), fermi_labelProd, bose_labelProd - return [IR.linear_combination(diagrams, ones(_dtype.factor, diagNum))], fermi_labelProd, bose_labelProd, extT_labels + return [IR.linear_combination(diagrams, ones(_dtype.factor, diagNum))], labelProd, extT_labels end end -function read_onediagram(io::IO, GNum::Int, verNum::Int, loopNum::Int, extIndex::Vector{Int}, - fermi_labelProd::LabelProduct, bose_labelProd::LabelProduct, loopPool::LoopPool, spinPolarPara::Float64=0.0; - splitter="|", offset::Int=-1, offset_ver4::Int=0, diagType=:polar, staticBose::Bool=true) +function read_onediagram!(io::IO, GNum::Int, verNum::Int, loopNum::Int, extIndex::Vector{Int}, + labelProd::LabelProduct, spinPolarPara::Float64=0.0; diagType=:polar, maxLoopNum::Int=loopNum, + splitter="|", offset::Int=-1, offset_ver4::Int=0, staticBose::Bool=true) extIndex = extIndex .- offset extNum = length(extIndex) @@ -180,13 +166,10 @@ function read_onediagram(io::IO, GNum::Int, verNum::Int, loopNum::Int, extIndex: @assert occursin("VertexBasis", readline(io)) tau_labels = _StringtoIntVector(readline(io)) .- offset - # tau_labels = _StringtoIntVector(readline(io)) - # unique_values = sort(unique(tau_labels)) - # tau_labels = [findfirst(x -> x == tau, unique_values) for tau in tau_labels] .- (1 + offset) readline(io) @assert occursin("LoopBasis", readline(io)) - currentBasis = zeros(Int, (GNum, loopNum)) + currentBasis = zeros(Int, (GNum, maxLoopNum)) for i in 1:loopNum x = parse.(Int, split(readline(io))) @assert length(x) == GNum @@ -227,38 +210,23 @@ function read_onediagram(io::IO, GNum::Int, verNum::Int, loopNum::Int, extIndex: permu, ver4Legs_ex = _exchange(permutation, ver4Legs, iex, extNum, offset_ver4=offset_ver4) ######################## Create Feynman diagram ######################### - # current_labels = labelProd.labels[dim] vertices = [𝜙(0) for i in 1:GNum] connected_operators = Op.OperatorProduct[] - - GTypes = fermi_labelProd.labels[2] - VTypes = bose_labelProd.labels[2] - fermi_dims = fermi_labelProd.dims - bose_dims = bose_labelProd.dims - # if staticBose - # tau_labels = [collect(eachindex(extIndex)); repeat(extIndex+1:tauNum, inner=2)] - # else - # @assert tauNum == GNum - # tau_labels = collect(1:GNum) - # end + connected_operators_orders = Vector{Vector{Int}}() # create all fermionic operators for (ind1, ind2) in enumerate(permu) - # current_index = _current_to_index(currentBasis[ind1, :]) - current_index = FrontEnds.append(loopPool, currentBasis[ind1, :]) - ind_GType = findfirst(p -> p == opGType[ind1], GTypes) - - # label1 = index_to_linear(fermi_labelProd, tau_labels[ind1], current_index, ind_GType) - # label2 = index_to_linear(fermi_labelProd, tau_labels[ind2], current_index, ind_GType) - # label1 = index_to_linear((fermi_dims..., length(loopPool)), tau_labels[ind1], ind_GType, current_index) - # label2 = index_to_linear((fermi_dims..., length(loopPool)), tau_labels[ind2], ind_GType, current_index) - labelProd_size = (fermi_dims..., length(loopPool)) - label1 = LinearIndices(labelProd_size)[tau_labels[ind1], ind_GType, current_index] - label2 = LinearIndices(labelProd_size)[tau_labels[ind2], ind_GType, current_index] + current_index = FrontEnds.push_labelat!(labelProd, currentBasis[ind1, :], 2) + + label1 = FrontEnds.index_to_linear(labelProd, tau_labels[ind1], current_index) + label2 = FrontEnds.index_to_linear(labelProd, tau_labels[ind2], current_index) vertices[ind1][1].label == 0 ? vertices[ind1] = 𝑎⁺(label1) : vertices[ind1] *= 𝑎⁺(label1) vertices[ind2][1].label == 0 ? vertices[ind2] = 𝑎⁻(label2) : vertices[ind2] *= 𝑎⁻(label2) + + opGType[ind1] < 0 && continue push!(connected_operators, 𝑎⁻(label2)𝑎⁺(label1)) + push!(connected_operators_orders, [opGType[ind1], 0]) end # normal order each OperatorProduct of vertices @@ -271,43 +239,24 @@ function read_onediagram(io::IO, GNum::Int, verNum::Int, loopNum::Int, extIndex: for (iVer, verLeg) in enumerate(ver4Legs_ex) current = currentBasis[verLeg[1]-offset, :] - currentBasis[verLeg[2]-offset, :] @assert current == currentBasis[verLeg[4]-offset, :] - currentBasis[verLeg[3]-offset, :] # momentum conservation - # current_index = _current_to_index(current) - current_index = FrontEnds.append(loopPool, current) + current_index = FrontEnds.push_labelat!(labelProd, current, 2) ind1, ind2 = 2 * (iVer - offset_ver4) - 1 + extNum, 2 * (iVer - offset_ver4) + extNum - ind1_WType = findfirst(p -> p == opWType[2iVer-1], VTypes) - ind2_WType = findfirst(p -> p == opWType[2iVer], VTypes) - - # label1 = index_to_linear(bose_labelProd, tau_labels[ind1], current_index, ind1_WType) - # label2 = index_to_linear(bose_labelProd, tau_labels[ind2], current_index, ind2_WType) - # label1 = index_to_linear((bose_dims..., length(loopPool)), tau_labels[ind1], ind1_WType, current_index) - # label2 = index_to_linear((bose_dims..., length(loopPool)), tau_labels[ind2], ind2_WType, current_index) - labelProd_size = (bose_dims..., length(loopPool)) - label1 = LinearIndices(labelProd_size)[tau_labels[ind1], ind1_WType, current_index] - label2 = LinearIndices(labelProd_size)[tau_labels[ind2], ind2_WType, current_index] + label1 = FrontEnds.index_to_linear(labelProd, tau_labels[ind1], current_index) + label2 = FrontEnds.index_to_linear(labelProd, tau_labels[ind2], current_index) vertices[ind1][1].label == 0 ? vertices[ind1] = 𝜙(label1) : vertices[ind1] *= 𝜙(label1) vertices[ind2][1].label == 0 ? vertices[ind2] = 𝜙(label2) : vertices[ind2] *= 𝜙(label2) push!(connected_operators, 𝜙(label1)𝜙(label2)) + push!(connected_operators_orders, [0, opWType[2iVer]]) end # add external operators in each external vertices if extNum > 0 && diagType != :sigma - external_current = append!([1], zeros(Int, loopNum - 1)) - extcurrent_index = FrontEnds.append(loopPool, external_current) - # if diagType == :sigma - # for (i, ind) in enumerate(extIndex) - # labelProd_size = (fermi_dims..., length(loopPool)) - # label = LinearIndices(labelProd_size)[tau_labels[ind], 1, extcurrent_index] - # if i == 1 - # vertices[ind] *= 𝑎⁻(label) - # else - # vertices[ind] *= 𝑎⁺(label) - # end - # end + external_current = append!([1], zeros(Int, maxLoopNum - 1)) + extcurrent_index = FrontEnds.push_labelat!(labelProd, external_current, 2) for ind in extIndex - labelProd_size = (bose_dims..., length(loopPool)) - label = LinearIndices(labelProd_size)[tau_labels[ind], 1, extcurrent_index] + label = FrontEnds.index_to_linear(labelProd, tau_labels[ind], 1, extcurrent_index) vertices[ind] *= 𝜙(label) end end @@ -319,8 +268,7 @@ function read_onediagram(io::IO, GNum::Int, verNum::Int, loopNum::Int, extIndex: push!(contraction, [findfirst(x -> x == connection[1], operators), findlast(x -> x == connection[2], operators)]) end - push!(graphs, IR.feynman_diagram(IR.interaction.(vertices), contraction, factor=symfactor, is_signed=true)) - # return IR.feynman_diagram(IR.interaction.(vertices), contraction, factor=symfactor * spinFactor), loopPool + push!(graphs, IR.feynman_diagram(IR.interaction.(vertices), contraction, contraction_orders=connected_operators_orders, factor=symfactor, is_signed=true)) end # create a graph as a linear combination from all subgraphs and subgraph_factors (spinFactors), loopPool, and external-tau variables @@ -334,6 +282,5 @@ function read_onediagram(io::IO, GNum::Int, verNum::Int, loopNum::Int, extIndex: else extT = tau_labels[extIndex] end - # return IR.linear_combination(graphs, filter(!iszero, spinFactors)), loopPool, extT - return IR.linear_combination(graphs, spinfactors_existed), loopPool, extT + return IR.linear_combination(graphs, spinfactors_existed), labelProd, extT end \ No newline at end of file diff --git a/src/frontend/LabelProduct.jl b/src/frontend/LabelProduct.jl index 99114962..357b91aa 100644 --- a/src/frontend/LabelProduct.jl +++ b/src/frontend/LabelProduct.jl @@ -13,14 +13,14 @@ The cartesian QuantumOperator.label product: - 'labels' : The list of labels in the LabelProduct - 'dims' : A tuple of the length of the label factors """ -struct LabelProduct{LT,N} +mutable struct LabelProduct{LT,N} labels::LT dims::NTuple{N,Int} function LabelProduct(vargs...) - #@assert all(v -> (v isa Mesh), vargs) "all arguments should variables" - mprod = Tuple(v for v in vargs) - mnew = new{typeof(mprod),length(mprod)}(mprod, Tuple(length(v) for v in vargs)) - return mnew + @assert all(v -> (v isa AbstractVector || v isa Tuple), vargs) "all arguments should be vectors or tuples." + # labels = Tuple(unique(v) for v in vargs) + labels = Tuple(v for v in vargs) + return new{typeof(labels),length(labels)}(labels, Tuple(length(v) for v in vargs)) end end @@ -52,29 +52,32 @@ Base.eachindex(obj::LabelProduct) = Base.eachindex(obj.labels) # rank(obj::LabelProduct{LT,N}) where {LT,N} = N """ - function index_to_linear(obj::LabelProduct, index...) -Convert a tuple of the indexes of each label to a single linear index of the LabelProduct. + @generated function index_to_linear(obj::LabelProduct{LT,N}, I...) where {LT,N} + + Convert a tuple of the indexes of each label to a single linear index of the LabelProduct. # Argument: - 'obj': The LabelProduct object - 'index...': N indexes of the label factor, where N is the number of label factor """ -function index_to_linear(obj::LabelProduct{LT,N}, I...) where {LT,N} - return LinearIndices(obj.dims)[I...] +@generated function index_to_linear(obj::LabelProduct{LT,N}, I...) where {LT,N} + ex = :(I[$N] - 1) + for i = (N-1):-1:1 + ex = :(I[$i] - 1 + obj.dims[$i] * $ex) + end + return :($ex + 1) end -# @generated function index_to_linear(obj::LabelProduct{LT,N}, I...) where {LT,N} -# ex = :(I[$N] - 1) -# for i = (N-1):-1:1 -# ex = :(I[$i] - 1 + obj.dims[$i] * $ex) -# end -# return :($ex + 1) -# end -# @generated function index_to_linear(dims::NTuple{N,Int}, I...) where {N} -# ex = :(I[$N] - 1) -# for i = (N-1):-1:1 -# ex = :(I[$i] - 1 + dims[$i] * $ex) -# end -# return :($ex + 1) + +@generated function index_to_linear(dims::NTuple{N,Int}, I...) where {N} + ex = :(I[$N] - 1) + for i = (N-1):-1:1 + ex = :(I[$i] - 1 + dims[$i] * $ex) + end + return :($ex + 1) +end + +# function index_to_linear(obj::LabelProduct{LT,N}, I...) where {LT,N} +# return LinearIndices(obj.dims)[I...] # end """ @@ -134,6 +137,38 @@ Print the LabelProduct. """ Base.show(io::IO, obj::LabelProduct) = print(io, "LabelProduct of: $(obj.labels)") +function push_labelat!(lp::LabelProduct{LT,N}, new_label, dim::Int) where {LT,N} + @assert dim <= N + loc = findfirst(isequal(new_label), lp.labels[dim]) + if isnothing(loc) + push!(lp.labels[dim], new_label) + lp.dims = Tuple(i == dim ? d + 1 : d for (i, d) in enumerate(lp.dims)) + return size(lp, dim) + end + return loc +end + +function append_label!(lp::LabelProduct{LT,N}, new_label::Union{Tuple,AbstractVector}) where {LT,N} + # Ensure that the length of new_label matches the existing dimensions + if length(new_label) != N + throw(ArgumentError("Length of new_label must match the existing number of dimensions (N)")) + end + + locs = collect(lp.dims) + # Update the labels field by appending the new_label + for (dim, label) in enumerate(new_label) + loc = findfirst(isequal(label), lp.labels[dim]) + if isnothing(loc) + push!(lp.labels[dim], label) + locs[dim] += 1 + else + locs[dim] = loc + end + end + lp.dims = Tuple(d > lp.dims[i] ? d : lp.dims[i] for (i, d) in enumerate(locs)) + return Tuple(locs) +end + @generated function _find_label(::Type{LT}, ::Type{M}) where {LT,M} for (i, t) in enumerate(fieldtypes(LT)) # type equality is implemented as t<:M and M<:t, diff --git a/src/frontend/pool.jl b/src/frontend/pool.jl index 36b0f449..65983466 100644 --- a/src/frontend/pool.jl +++ b/src/frontend/pool.jl @@ -79,7 +79,7 @@ loop(pool::LoopPool, idx) = view(pool.loops, :, idx) hasloop(pool::LoopPool) = (pool.dim > 0) && (pool.loopNum > 0) -function append(pool::LoopPool, basis::AbstractVector) +function append!(pool::LoopPool, basis::AbstractVector) @assert pool.loopNum >= length(basis) if pool.loopNum > length(basis) append!(basis, zeros(eltype(basis), pool.loopNum - length(basis))) diff --git a/src/utility.jl b/src/utility.jl index 26bcf668..aa8241d9 100644 --- a/src/utility.jl +++ b/src/utility.jl @@ -139,15 +139,15 @@ end - `label::Tuple{LabelProduct,LabelProduct}` A Tuple fermi (first element) and bose LabelProduct (second element). - `taylormap::Dict{Int,TaylorSeries}` A dicitonary that maps id of each node of target diagram to its correponding taylor series. """ -function taylorexpansion!(graph::FeynmanGraph{F,W}, propagator_var::Tuple{Vector{Bool},Vector{Bool}}, label::Tuple{LabelProduct,LabelProduct}; taylormap::Dict{Int,TaylorSeries{Graph{F,W}}}=Dict{Int,TaylorSeries{Graph{F,W}}}()) where {F,W} +function taylorexpansion!(graph::FeynmanGraph{F,W}, propagator_var::Tuple{Vector{Bool},Vector{Bool}}; taylormap::Dict{Int,TaylorSeries{Graph{F,W}}}=Dict{Int,TaylorSeries{Graph{F,W}}}()) where {F,W} var_dependence = Dict{Int,Vector{Bool}}() for leaf in Leaves(graph) if ComputationalGraphs.diagram_type(leaf) == ComputationalGraphs.Propagator - In = leaf.properties.vertices[2][1].label + # In = leaf.properties.vertices[2][1].label if isfermionic(leaf.properties.vertices[1]) - if label[1][In][2] >= 0 #For fake propagator, this label is smaller than zero, and those propagators should not be differentiated. - var_dependence[leaf.id] = [propagator_var[1][idx] ? true : false for idx in 1:get_numvars()] - end + # if label[1][In][2] >= 0 #For fake propagator, this label is smaller than zero, and those propagators should not be differentiated. + var_dependence[leaf.id] = [propagator_var[1][idx] ? true : false for idx in 1:get_numvars()] + # end else var_dependence[leaf.id] = [propagator_var[2][idx] ? true : false for idx in 1:get_numvars()] end diff --git a/test/front_end.jl b/test/front_end.jl index 2d78101e..f05a585c 100644 --- a/test/front_end.jl +++ b/test/front_end.jl @@ -13,11 +13,11 @@ basis1 = [1.0, 0.0, 0.0, 1.0] basis2 = [1.0, 1.0, 0.0, 0.0] basis3 = [1.0, 0.0, -1.0, 1.0] - idx1 = FrontEnds.append(loopPool, basis1) - idx2 = FrontEnds.append(loopPool, basis2) - idx3 = FrontEnds.append(loopPool, basis2) - idx4 = FrontEnds.append(loopPool, basis1) - idx5 = FrontEnds.append(loopPool, basis3) + idx1 = FrontEnds.append!(loopPool, basis1) + idx2 = FrontEnds.append!(loopPool, basis2) + idx3 = FrontEnds.append!(loopPool, basis2) + idx4 = FrontEnds.append!(loopPool, basis1) + idx5 = FrontEnds.append!(loopPool, basis3) @test length(loopPool) == 3 @test idx1 == idx4 @test idx2 == idx3 @@ -34,8 +34,9 @@ end tau_labels = collect(1:5) loopbasis = [[1.0, 1.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0], [1.0, 0.0, -1.0, 0.0]] - loopPool = FrontEnds.LoopPool(:K, 3, loopbasis) - labelProd = LabelProduct(flavors, tau_labels, loopPool) + labelProd = LabelProduct(flavors, tau_labels, loopbasis) + # loopPool = FrontEnds.LoopPool(:K, 3, loopbasis) + # labelProd = LabelProduct(flavors, tau_labels, loopPool) @test length(labelProd) == 3 * 5 * 5 @test size(labelProd) == (3, 5, 5) @@ -44,6 +45,18 @@ end @test FrontEnds.linear_to_index(labelProd.dims, 41) == (2, 4, 3) @test labelProd[38] == labelProd[2, 3, 3] == (2, 3, [0.0, 0.0, 1.0, 0.0]) - @test eltype(typeof(labelProd)) == (eltype(typeof(flavors)), eltype(typeof(tau_labels)), eltype(typeof(loopPool))) - @test FrontEnds._find_label(typeof(labelProd.labels), FrontEnds.LoopPool) == 3 + @test FrontEnds.push_labelat!(labelProd, 6, 2) == 6 + @test labelProd.labels[2] == collect(1:6) + @test FrontEnds.push_labelat!(labelProd, [1.0, 0.0, 1.0, 0.0], 3) == 6 + @test labelProd.labels[end][end] == [1.0, 0.0, 1.0, 0.0] + @test FrontEnds.push_labelat!(labelProd, [1.0, 0.0, -1.0, 0.0], 3) == 5 + @test labelProd.labels[end][end] == [1.0, 0.0, 1.0, 0.0] + @test FrontEnds.append_label!(labelProd, [4, 2, [1.0, 0.0, 0.0, 0.0]]) == (4, 2, 7) + @test labelProd.labels[1] == collect(1:4) + @test labelProd.labels[2] == collect(1:6) + @test labelProd.labels[3] == [[1.0, 1.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0], [1.0, 0.0, -1.0, 0.0], [1.0, 0.0, 1.0, 0.0], [1.0, 0.0, 0.0, 0.0]] + + @test eltype(typeof(labelProd)) == (eltype(typeof(flavors)), eltype(typeof(tau_labels)), eltype(typeof(loopbasis))) + @test FrontEnds._find_label(typeof(labelProd.labels), typeof(loopbasis)) == 3 end \ No newline at end of file diff --git a/test/taylor.jl b/test/taylor.jl index 812daf03..6320e62b 100644 --- a/test/taylor.jl +++ b/test/taylor.jl @@ -76,13 +76,13 @@ end @testset "Taylor AD of Sigma FeynmanGraph" begin - dict_g, fl, bl, leafmap = diagdictGV(:sigma, [(2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 2, 0), (2, 1, 2), (2, 2, 2)], 3) + dict_g, lp, leafmap = diagdictGV(:sigma, [(2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 2, 0), (2, 1, 2), (2, 2, 2)]) g = dict_g[(2, 0, 0)] set_variables("x y", orders=[2, 2]) propagator_var = ([true, false], [false, true]) # Specify variable dependence of fermi (first element) and bose (second element) particles. - t, taylormap = taylorexpansion!(g[1][1], propagator_var, (fl, bl)) + t, taylormap = taylorexpansion!(g[1][1], propagator_var) for (order, graph) in dict_g if graph[2][1] == g[2][1]