From 286cbbc36efa8547185716de7a87dc228a4d223a Mon Sep 17 00:00:00 2001 From: houpc Date: Wed, 10 Jan 2024 20:42:24 +0800 Subject: [PATCH] remove the archived codes --- archived/src/FeynmanDiagram.jl | 217 -------- archived/src/common.jl | 251 --------- archived/src/diagram_tree/DiagTree.jl | 46 -- archived/src/diagram_tree/common.jl | 64 --- archived/src/diagram_tree/eval.jl | 95 ---- archived/src/diagram_tree/io.jl | 227 -------- archived/src/diagram_tree/operation.jl | 147 ----- archived/src/diagram_tree/optimize.jl | 126 ----- archived/src/diagram_tree/traits.jl | 255 --------- archived/src/diagram_tree/tree.jl | 275 --------- archived/src/diagtree.jl | 91 --- .../src/expression_tree/ExpressionTree.jl | 29 - archived/src/expression_tree/build.jl | 65 --- archived/src/expression_tree/common.jl | 61 -- archived/src/expression_tree/eval.jl | 103 ---- archived/src/expression_tree/io.jl | 141 ----- archived/src/expression_tree/pool.jl | 232 -------- archived/src/expression_tree/tree.jl | 197 ------- archived/src/parquet.jl | 112 ---- .../parquet_builder/benchmark/benchmark.jl | 24 - .../benchmark/diagram_count.jl | 124 ----- .../src/parquet_builder/benchmark/vertex4.jl | 288 ---------- .../parquet_builder/benchmark/vertex4_eval.jl | 142 ----- .../parquet_builder/benchmark/vertex4_io.jl | 224 -------- archived/src/parquet_builder/common.jl | 182 ------ archived/src/parquet_builder/ep_coupling.jl | 144 ----- archived/src/parquet_builder/filter.jl | 78 --- archived/src/parquet_builder/green.jl | 115 ---- archived/src/parquet_builder/parquet.jl | 34 -- archived/src/parquet_builder/polarization.jl | 140 ----- archived/src/parquet_builder/sigma.jl | 138 ----- archived/src/parquet_builder/sigmaGV.jl | 134 ----- archived/src/parquet_builder/vertex3.jl | 127 ----- archived/src/parquet_builder/vertex4.jl | 482 ---------------- archived/test/common.jl | 22 - archived/test/diagram_tree.jl | 246 --------- archived/test/expression_tree.jl | 150 ----- archived/test/parquet_builder.jl | 521 ------------------ 38 files changed, 6049 deletions(-) delete mode 100644 archived/src/FeynmanDiagram.jl delete mode 100644 archived/src/common.jl delete mode 100644 archived/src/diagram_tree/DiagTree.jl delete mode 100644 archived/src/diagram_tree/common.jl delete mode 100644 archived/src/diagram_tree/eval.jl delete mode 100644 archived/src/diagram_tree/io.jl delete mode 100644 archived/src/diagram_tree/operation.jl delete mode 100644 archived/src/diagram_tree/optimize.jl delete mode 100644 archived/src/diagram_tree/traits.jl delete mode 100644 archived/src/diagram_tree/tree.jl delete mode 100644 archived/src/diagtree.jl delete mode 100644 archived/src/expression_tree/ExpressionTree.jl delete mode 100644 archived/src/expression_tree/build.jl delete mode 100644 archived/src/expression_tree/common.jl delete mode 100644 archived/src/expression_tree/eval.jl delete mode 100644 archived/src/expression_tree/io.jl delete mode 100644 archived/src/expression_tree/pool.jl delete mode 100644 archived/src/expression_tree/tree.jl delete mode 100644 archived/src/parquet.jl delete mode 100644 archived/src/parquet_builder/benchmark/benchmark.jl delete mode 100644 archived/src/parquet_builder/benchmark/diagram_count.jl delete mode 100644 archived/src/parquet_builder/benchmark/vertex4.jl delete mode 100644 archived/src/parquet_builder/benchmark/vertex4_eval.jl delete mode 100644 archived/src/parquet_builder/benchmark/vertex4_io.jl delete mode 100644 archived/src/parquet_builder/common.jl delete mode 100644 archived/src/parquet_builder/ep_coupling.jl delete mode 100644 archived/src/parquet_builder/filter.jl delete mode 100644 archived/src/parquet_builder/green.jl delete mode 100644 archived/src/parquet_builder/parquet.jl delete mode 100644 archived/src/parquet_builder/polarization.jl delete mode 100644 archived/src/parquet_builder/sigma.jl delete mode 100644 archived/src/parquet_builder/sigmaGV.jl delete mode 100644 archived/src/parquet_builder/vertex3.jl delete mode 100644 archived/src/parquet_builder/vertex4.jl delete mode 100644 archived/test/common.jl delete mode 100644 archived/test/diagram_tree.jl delete mode 100644 archived/test/expression_tree.jl delete mode 100644 archived/test/parquet_builder.jl diff --git a/archived/src/FeynmanDiagram.jl b/archived/src/FeynmanDiagram.jl deleted file mode 100644 index 3ebfa82b..00000000 --- a/archived/src/FeynmanDiagram.jl +++ /dev/null @@ -1,217 +0,0 @@ -module FeynmanDiagram -using Random, LinearAlgebra, Parameters, AbstractTrees, RuntimeGeneratedFunctions - -macro todo() - return :(error("Not yet implemented!")) -end - -@enum DiagramType begin - VacuumDiag #vaccum diagram for the free energy - SigmaDiag #self-energy - GreenDiag #green's function - PolarDiag #polarization - Ver3Diag #3-point vertex function - Ver4Diag #4-point vertex function - GnDiag #n-point Green's function - GcDiag #n-point connected Green's function -end -Base.length(r::DiagramType) = 1 -Base.iterate(r::DiagramType) = (r, nothing) -function Base.iterate(r::DiagramType, ::Nothing) end - -abstract type DiagType end -abstract type Vacuum <: DiagType end -abstract type Tadpole <: DiagType end -abstract type FermiPropagator <: DiagType end -abstract type BosePropagator <: DiagType end -abstract type FermiSelfEnergy <: DiagType end -abstract type BoseSelfEnergy <: DiagType end -abstract type VertexDiag <: DiagType end -abstract type GncDiag <: DiagType end -abstract type GndDiag <: DiagType end - -@enum Filter begin - Wirreducible #remove all polarization subdiagrams - Girreducible #remove all self-energy inseration - NoHartree - NoFock - NoBubble # true to remove all bubble subdiagram - Proper #ver4, ver3, and polarization diagrams may require to be irreducible along the transfer momentum/frequency - DirectOnly # only direct interaction, this can be useful for debug purpose -end - -Base.length(r::Filter) = 1 -Base.iterate(r::Filter) = (r, nothing) -function Base.iterate(r::Filter, ::Nothing) end - -@enum Response begin - Composite - ChargeCharge - SpinSpin - ProperChargeCharge - ProperSpinSpin - UpUp - UpDown -end - -Base.length(r::Response) = 1 -Base.iterate(r::Response) = (r, nothing) -function Base.iterate(r::Response, ::Nothing) end - -@enum AnalyticProperty begin - Instant - Dynamic - D_Instant #derivative of instant interaction - D_Dynamic #derivative of the dynamic interaction -end - -Base.length(r::AnalyticProperty) = 1 -Base.iterate(r::AnalyticProperty) = (r, nothing) -function Base.iterate(r::AnalyticProperty, ::Nothing) end - -export SigmaDiag, PolarDiag, Ver3Diag, Ver4Diag, GreenDiag -export VacuumDiag, GnDiag, GcDiag -export Wirreducible, Girreducible, NoBubble, NoHartree, NoFock, Proper, DirectOnly -export Response, ChargeCharge, SpinSpin, UpUp, UpDown -export AnalyticProperty, Instant, Dynamic, D_Instant, D_Dynamic - -export DiagType -export FermiPropagator, BosePropagator, FermiSelfEnergy, BoseSelfEnergy, VertexDiag -export Vacuum, Tadpole, GncDiag, GndDiag - -include("common.jl") -export DiagPara, DiagParaF64 -export Interaction, interactionTauNum, innerTauNum - -include("common_new.jl") -export DiagramPara, DiagramParaF64 -# export Interaction, interactionTauNum, innerTauNum - -include("quantum_operator/QuantumOperators.jl") - -using .QuantumOperators -export QuantumOperators -export QuantumOperator, OperatorProduct, isfermionic -export 𝑓⁻, 𝑓⁺, 𝑓, 𝑏⁻, 𝑏⁺, πœ™ -# export 𝑓⁻ₑ, 𝑓⁺ₑ, 𝑓ₑ, 𝑏⁻ₑ, 𝑏⁺ₑ, πœ™β‚‘ -export fermionic_annihilation, fermionic_creation, majorana -export bosonic_annihilation, bosonic_creation, real_classic -export correlator_order, normal_order - - - - -include("computational_graph/ComputationalGraph.jl") -using .ComputationalGraphs -export ComputationalGraphs -export labelreset, parity -# export AbstractOperator, Prod, Sum - -export AbstractGraph, AbstractOperator -export Graph, FeynmanGraph, FeynmanProperties - -export isequiv, drop_topology, is_external, is_internal, diagram_type, orders, vertices, topology -export external_legs, external_indices, external_operators, external_labels -export multi_product, linear_combination, feynman_diagram, propagator, interaction, external_vertex -# export DiagramType, Interaction, ExternalVertex, Propagator, SelfEnergy, VertexDiag, GreenDiag, GenericDiag - -# export standardize_order! -# export reducibility, connectivity -# export 𝐺ᢠ, 𝐺ᡇ, 𝐺ᡠ, π‘Š, Green2, Interaction -# export Coupling_yukawa, Coupling_phi3, Coupling_phi4, Coupling_phi6 -export haschildren, onechild, isleaf, isbranch, ischain, isfactorless, has_zero_subfactors, eldest -export relabel!, standardize_labels!, replace_subgraph!, merge_linear_combination!, merge_multi_product!, merge_chains! -export relabel, standardize_labels, replace_subgraph, merge_linear_combination, merge_multi_product, merge_chains -export open_parenthesis, open_parenthesis!, flatten_prod!, flatten_prod, flatten_sum!, flatten_sum -export optimize!, optimize, merge_all_chains!, merge_all_linear_combinations!, remove_duplicated_leaves! - -include("TaylorSeries/TaylorSeries.jl") -using .Taylor -export Taylor - -include("diagram_tree/DiagTree.jl") -using .DiagTree -export DiagTree -export TwoBodyChannel, Alli, PHr, PHEr, PPr, AnyChan -export Permutation, Di, Ex, DiEx -export Diagram, addSubDiagram!, toDataFrame -export evalDiagNode!, evalDiagTree!, evalDiagTreeKT! -export Operator, Sum, Prod -export DiagramId, GenericId, Ver4Id, Ver3Id, GreenId, SigmaId, PolarId -export PropagatorId, BareGreenId, BareInteractionId -export BareGreenNId, BareHoppingId, GreenNId, ConnectedGreenNId -export uidreset, toDataFrame, mergeby, plot_tree - - -include("parquet_builder/parquet.jl") -using .Parquet -export Parquet -export ParquetBlocks - -include("strong_coupling_expansion_builder/strong_coupling_expansion") -using .SCE -export SCE -export Gn - -include("expression_tree/ExpressionTree.jl") -using .ExprTree -export ExprTree -export Component, ExpressionTree -# export Propagator -export addpropagator!, addnode! -export setroot!, addroot! -export evalNaive, showTree - -include("utility.jl") -using .Utility -export Utility -export taylorexpansion! - -include("frontend/frontends.jl") -using .FrontEnds -export FrontEnds -export LabelProduct - -include("frontend/GV.jl") -using .GV -export GV -export diagdictGV, diagdict_parquet, leafstates, leafstates_diagtree - -include("backend/compiler.jl") -using .Compilers -export Compilers - - -##################### precompile ####################### -# precompile as the final step of the module definition: -if ccall(:jl_generating_output, Cint, ()) == 1 # if we're precompiling the package - let - para = DiagParaF64(type=Ver4Diag, innerLoopNum=2, hasTau=true) - # ver4 = Parquet.vertex4(para) # this will force precompilation - ver4 = Parquet.build(para) # this will force precompilation - - mergeby(ver4, [:response]) - mergeby(ver4.diagram) - mergeby(ver4.diagram, [:response]; idkey=[:extT, :response]) - - para = DiagParaF64(type=SigmaDiag, innerLoopNum=2, hasTau=true) - Parquet.build(para) # this will force precompilation - para = DiagParaF64(type=GreenDiag, innerLoopNum=2, hasTau=true) - Parquet.green(para) # this will force precompilation - para = DiagParaF64(type=PolarDiag, innerLoopNum=2, hasTau=true) - # Parquet.polarization(para) # this will force precompilation - Parquet.build(para) # this will force precompilation - para = DiagParaF64(type=Ver3Diag, innerLoopNum=2, hasTau=true) - # Parquet.vertex3(para) # this will force precompilation - Parquet.build(para) # this will force precompilation - - DiagTree.removeHartreeFock!(ver4.diagram) - DiagTree.derivative(ver4.diagram, BareGreenId) - DiagTree.derivative(ver4.diagram, BareInteractionId) - # DiagTree.removeHartreeFock!(ver4.diagram) - ExprTree.build(ver4.diagram, 3) - end -end - - -end \ No newline at end of file diff --git a/archived/src/common.jl b/archived/src/common.jl deleted file mode 100644 index 70a0ee76..00000000 --- a/archived/src/common.jl +++ /dev/null @@ -1,251 +0,0 @@ -struct Interaction - response::Response - type::Set{AnalyticProperty} - function Interaction(response, type) - return new(response, Set(type)) - end - function Interaction(response, type::AnalyticProperty) - return new(response, Set([type,])) - end -end - -Base.isequal(a::Interaction, b::Interaction) = (a.response == b.response) && issetequal(a.type, b.type) -Base.:(==)(a::Interaction, b::Interaction) = Base.isequal(a, b) - -function short(inter::Interaction) - return "$(short(inter.response))_$(reduce(*, [short(t) for t in inter.type]))" -end - -function short(name::Response) - if name == ChargeCharge - return "cc" - elseif name == SpinSpin - return "σσ" - elseif name == UpUp - return "↑↑" - elseif name == UpDown - return "↑↓" - else - @error("$name is not implemented!") - end -end - -function short(type::AnalyticProperty) - if type == Instant - return "Ins" - elseif type == Dynamic - return "Dyn" - elseif type == D_Instant - return "dIns" - elseif type == D_Dynamic - return "dDyn" - else - @error("$type is not implemented!") - end -end - -function symbol(name::Response, type::AnalyticProperty, addition=nothing) - if isnothing(addition) - return Symbol("$(short(name))$(short(type))") - else - return Symbol("$(short(name))$(short(type))$(addition)") - end - -end - -@with_kw struct DiagPara{W} - type::DiagramType - innerLoopNum::Int - - isFermi::Bool = true - spin::Int = 2 - # loopDim::Int = 3 - interaction::Vector{Interaction} = [Interaction(ChargeCharge, [Instant,]),] # :ChargeCharge, :SpinSpin, ... - - firstLoopIdx::Int = firstLoopIdx(type) - totalLoopNum::Int = firstLoopIdx + innerLoopNum - 1 - - #### turn the following parameters on if there is tau variables ######## - hasTau::Bool = false - firstTauIdx::Int = firstTauIdx(type) - totalTauNum::Int = firstTauIdx + innerTauNum(type, innerLoopNum, interactionTauNum(hasTau, interaction)) - 1 - #if there is no imaginary-time at all, then set this number to zero! - ######################################################################## - filter::Vector{Filter} = [NoHartree,] #usually, the Hartree subdiagram should be removed - transferLoop::Vector{Float64} = [] #Set it to be the transfer momentum/frequency if you want to check the diagrams are proper or not - extra::Any = Nothing -end - -const DiagParaF64 = DiagPara{Float64} - -@inline interactionTauNum(para::DiagPara) = interactionTauNum(para.hasTau, para.interaction) -@inline innerTauNum(para::DiagPara) = innerTauNum(para.type, para.innerLoopNum, para.interactionTauNum) - -""" - Parameters.reconstruct(p::DiagPara; kws...) - - Type-stable version of the Parameters.reconstruct -""" -function Parameters.reconstruct(::Type{DiagPara{W}}, p::DiagPara{W}, di) where {W} - di = !isa(di, AbstractDict) ? Dict(di) : copy(di) - get(p, di, key) = pop!(di, key, getproperty(p, key)) - return DiagPara{W}( - # type = pop!(di, :type, p.type), - type=get(p, di, :type), - innerLoopNum=get(p, di, :innerLoopNum), - isFermi=get(p, di, :isFermi), - spin=get(p, di, :spin), - # loopDim=get(p, di, :loopDim), - interaction=get(p, di, :interaction), - firstLoopIdx=get(p, di, :firstLoopIdx), - totalLoopNum=get(p, di, :totalLoopNum), - hasTau=get(p, di, :hasTau), - firstTauIdx=get(p, di, :firstTauIdx), - totalTauNum=get(p, di, :totalTauNum), - filter=get(p, di, :filter), - transferLoop=get(p, di, :transferLoop), - extra=get(p, di, :extra) - ) - length(di) != 0 && error("Fields $(keys(di)) not in type $T") -end - -function derivepara(p::DiagPara{W}; kwargs...) where {W} - di = !isa(kwargs, AbstractDict) ? Dict(kwargs) : copy(kwargs) - get(p, di, key) = pop!(di, key, getproperty(p, key)) - return DiagPara{W}( - # type = pop!(di, :type, p.type), - type=get(p, di, :type), - innerLoopNum=get(p, di, :innerLoopNum), - isFermi=get(p, di, :isFermi), - spin=get(p, di, :spin), - # loopDim=get(p, di, :loopDim), - interaction=get(p, di, :interaction), - firstLoopIdx=get(p, di, :firstLoopIdx), - totalLoopNum=get(p, di, :totalLoopNum), - hasTau=get(p, di, :hasTau), - firstTauIdx=get(p, di, :firstTauIdx), - totalTauNum=get(p, di, :totalTauNum), - filter=get(p, di, :filter), - transferLoop=get(p, di, :transferLoop), - extra=get(p, di, :extra) - ) - length(di) != 0 && error("Fields $(keys(di)) not in type $T") -end - -function Base.isequal(p::DiagPara{W}, q::DiagPara{W}) where {W} - for field in fieldnames(typeof(p)) #fieldnames doesn't include user-defined entries in Base.getproperty - if field == :filter - if Set(p.filter) != Set(q.filter) - return false - end - elseif field == :transferLoop - if (isempty(p.transferLoop) && isempty(q.transferLoop) == false) || (isempty(p.transferLoop) == false && isempty(q.transferLoop)) - return false - elseif isempty(p.transferLoop) == false && isempty(q.transferLoop) == false - if (p.transferLoop β‰ˆ q.transferLoop) == false - return false - end - end - elseif field == :interaction - if (p.interaction βŠ† q.interaction) == false || (q.interaction βŠ† p.interaction) == false - return false - end - else - if Base.getproperty(p, field) != Base.getproperty(q, field) - return false - end - end - end - return true -end - -Base.:(==)(a::DiagPara{W}, b::DiagPara{W}) where {W} = Base.isequal(a, b) - -""" - function innerTauNum(type::DiagramType, innerLoopNum, interactionTauNum) - - internal imaginary-time degrees of freedom for a given diagram type and internal loop number. - For the vertex functions (self-energy, polarization, vertex3, and vertex4), innerTauNum is equivalent to tauNum. - For the Green function, tauNum = innerTauNum + external tauNum -""" -function innerTauNum(type::DiagramType, innerLoopNum, interactionTauNum) - if type == Ver4Diag - return (innerLoopNum + 1) * interactionTauNum - elseif type == SigmaDiag - return innerLoopNum * interactionTauNum - elseif type == GreenDiag - return innerLoopNum * interactionTauNum - elseif type == VacuumDiag - return (innerLoopNum - 1) * interactionTauNum - elseif type == PolarDiag - return 1 + innerTauNum(Ver3Diag, innerLoopNum - 1, interactionTauNum) - elseif type == Ver3Diag - return 1 + innerTauNum(Ver4Diag, innerLoopNum - 1, interactionTauNum) - else - error("not implemented!") - end -end - -function interactionTauNum(hasTau::Bool, interactionSet) - if hasTau == false - return 0 - end - for interaction in interactionSet - if Dynamic in interaction.type || D_Dynamic in interaction.type - return 2 - end - end - return 1 -end - -function firstTauIdx(type::DiagramType, offset::Int=0) - if type == GreenDiag - return 3 + offset - elseif type == Ver3Diag - return 1 + offset - elseif type == PolarDiag - return 1 + offset - else - return 1 + offset - end -end - -function firstLoopIdx(type::DiagramType, offset::Int=0) - if type == Ver4Diag #three extK - return 4 + offset - elseif type == SigmaDiag #one extK - return 2 + offset - elseif type == GreenDiag #one extK - return 2 + offset - elseif type == PolarDiag #one extK - return 2 + offset - elseif type == Ver3Diag #two extK - return 3 + offset - elseif type == VacuumDiag #no extK - return 1 + offset - else - error("not implemented!") - end -end - -function totalTauNum(type::DiagramType, innerLoopNum, interactionTauNum, offset::Int=0) - return firstTauIdx(type, offset) + innerTauNum(type, innerLoopNum, interactionTauNum) - 1 -end - -function totalLoopNum(type::DiagramType, innerLoopNum, offset::Int=0) - return firstLoopIdx(type, offset) + innerLoopNum - 1 -end - -function totalTauNum(para, type::Symbol=:none) - return para.totalTauNum - # if type == :Ver4 - # return (para.internalLoopNum + 1) * para.interactionTauNum - # else - # error("not implemented!") - # end -end - -function totalLoopNum(para, type::Symbol=:none) - return para.totalLoopNum -end - diff --git a/archived/src/diagram_tree/DiagTree.jl b/archived/src/diagram_tree/DiagTree.jl deleted file mode 100644 index d1f0070b..00000000 --- a/archived/src/diagram_tree/DiagTree.jl +++ /dev/null @@ -1,46 +0,0 @@ -module DiagTree - -# if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@optlevel")) -# @eval Base.Experimental.@optlevel 1 -# end - -using AbstractTrees -using Printf, PyCall, DataFrames - -@enum TwoBodyChannel Alli = 1 PHr PHEr PPr AnyChan -@enum Permutation Di = 1 Ex DiEx - -export TwoBodyChannel, Alli, PHr, PHEr, PPr, AnyChan -export Permutation, Di, Ex, DiEx - -Base.length(r::TwoBodyChannel) = 1 -Base.iterate(r::TwoBodyChannel) = (r, nothing) -function Base.iterate(r::TwoBodyChannel, ::Nothing) end - -Base.length(r::Permutation) = 1 -Base.iterate(r::Permutation) = (r, nothing) -function Base.iterate(r::Permutation, ::Permutation) end - -include("common.jl") -include("traits.jl") -include("tree.jl") -include("operation.jl") -include("io.jl") -include("eval.jl") -include("optimize.jl") - -const INL, OUTL, INR, OUTR = 1, 2, 3, 4 - -export Diagram -export addSubDiagram! -export toDataFrame -export evalDiagTree! -export evalDiagTreeKT! -export Operator, Sum, Prod -export DiagramId, GenericId, Ver4Id, Ver3Id, GreenId, SigmaId, PolarId -export PropagatorId, BareGreenId, BareInteractionId -export BareGreenNId, BareHoppingId, GreenNId, ConnectedGreenNId -export uidreset, toDataFrame, mergeby, plot_tree -export isleaf - -end \ No newline at end of file diff --git a/archived/src/diagram_tree/common.jl b/archived/src/diagram_tree/common.jl deleted file mode 100644 index 11836f9b..00000000 --- a/archived/src/diagram_tree/common.jl +++ /dev/null @@ -1,64 +0,0 @@ -import ..Filter -import ..Wirreducible #remove all polarization subdiagrams -import ..Girreducible #remove all self-energy inseration -import ..NoHartree -import ..NoFock -import ..NoBubble # true to remove all bubble subdiagram -import ..Proper #ver4, ver3, and polarization diagrams may require to be irreducible along the transfer momentum/frequency - -import ..DiagramType -import ..GreenDiag -import ..SigmaDiag -import ..PolarDiag -import ..Ver3Diag -import ..Ver4Diag -import ..GnDiag -import ..GcDiag - -import ..Composite -import ..ChargeCharge -import ..SpinSpin -import ..UpUp -import ..UpDown -import ..Response - -import ..Instant -import ..Dynamic -import ..D_Instant -import ..D_Dynamic -import ..AnalyticProperty - -import ..symbol -import ..short - -import ..Interaction - -import ..DiagPara - -import ..innerTauNum - -# unique id -# uid() = abs(rand(Int)) % 10000 - -# let z = 0 -# global function uid() -# z += 1 -# return z -# end -# end -const _counter = [0,] - -function uid() - _counter[1] += 1 - return _counter[1] -end - -function uidreset() - _counter[1] = 0 -end - -function getK(loopNum::Int, loopIdx::Int) - k = zeros(loopNum) - k[loopIdx] = 1.0 - return k -end diff --git a/archived/src/diagram_tree/eval.jl b/archived/src/diagram_tree/eval.jl deleted file mode 100644 index 4e8d9bb0..00000000 --- a/archived/src/diagram_tree/eval.jl +++ /dev/null @@ -1,95 +0,0 @@ -@inline apply(o::Sum, diags::Vector{Diagram{W}}) where {W<:Number} = sum(d.weight for d in diags) -@inline apply(o::Prod, diags::Vector{Diagram{W}}) where {W<:Number} = prod(d.weight for d in diags) -@inline apply(o::Sum, diag::Diagram{W}) where {W<:Number} = diag.weight -@inline apply(o::Prod, diag::Diagram{W}) where {W<:Number} = diag.weight - -@inline eval(d::DiagramId) = error("eval for $d has not yet implemented!") - -######################### evaluator for KT representation ######################### -function evalDiagNodeKT!(diag::Diagram, varK, varT, additional=nothing; eval=DiagTree.eval) - if length(diag.subdiagram) == 0 - # if hasproperty(diag.id, :extK) - if (isnothing(varK) == false) && (isnothing(varT) == false) - K = varK * diag.id.extK - if isnothing(additional) - diag.weight = eval(diag.id, K, diag.id.extT, varT) * diag.factor - else - diag.weight = eval(diag.id, K, diag.id.extT, varT, additional) * diag.factor - end - elseif isnothing(varK) - if isnothing(additional) - diag.weight = eval(diag.id, diag.id.extT, varT) * diag.factor - else - diag.weight = eval(diag.id, diag.id.extT, varT, additional) * diag.factor - end - elseif isnothing(varT) - K = varK * diag.id.extK - if isnothing(additional) - diag.weight = eval(diag.id, K) * diag.factor - else - diag.weight = eval(diag.id, K, additional) * diag.factor - end - else - if isnothing(additional) - diag.weight = eval(diag.id) * diag.factor - else - diag.weight = eval(diag.id, additional) * diag.factor - end - end - else - diag.weight = apply(diag.operator, diag.subdiagram) * diag.factor - end - return diag.weight -end - -function evalKT!(diag::Diagram, varK, varT; eval=DiagTree.eval) - for d in PostOrderDFS(diag) - evalDiagNodeKT!(d, varK, varT; eval=eval) - end - return diag.weight -end - -function evalKT!(diags::Vector{Diagram{W}}, varK, varT; eval=DiagTree.eval) where {W} - for d in diags - evalKT!(d, varK, varT; eval=eval) - end - # return W[d.weight for d in diags] -end - -function evalKT!(df::DataFrame, varK, varT; eval=DiagTree.eval) - for d in df[!, :diagram] - evalKT!(d, varK, varT; eval=eval) - end - # return W[d.weight for d in df[!, :Diagram]] -end - -######################### generic evaluator ######################### -function evalDiagNode!(diag::Diagram, vargs...; eval=DiagTree.eval) - if length(diag.subdiagram) == 0 - diag.weight = eval(diag.id, vargs...) * diag.factor - else - diag.weight = apply(diag.operator, diag.subdiagram) * diag.factor - end - return diag.weight -end - -function eval!(diag::Diagram, vargs...; eval=DiagTree.eval) - for d in PostOrderDFS(diag) - evalDiagNode!(d, vargs...; eval=eval) - end - return diag.weight -end - -function eval!(diags::Vector{Diagram{W}}, vargs...; eval=DiagTree.eval) where {W} - for d in diags - eval!(d, vargs...; eval=eval) - end - # return W[d.weight for d in diags] -end - -function eval!(df::DataFrame, vargs...; eval=DiagTree.eval) - for d in df[!, :diagram] - eval!(d, vargs...; eval=eval) - end - # return W[d.weight for d in df[!, :Diagram]] -end \ No newline at end of file diff --git a/archived/src/diagram_tree/io.jl b/archived/src/diagram_tree/io.jl deleted file mode 100644 index 0ea1f4f6..00000000 --- a/archived/src/diagram_tree/io.jl +++ /dev/null @@ -1,227 +0,0 @@ -# function toDict(diag::Diagram; maxdepth::Int) -# @assert maxdepth == 1 "deep convert has not yet been implemented!" - -# d = Dict{Symbol,Any}() -# d[:hash] = diag.hash -# d[:id] = diag.id -# d[:name] = diag.name -# d[:diagram] = diag -# d[:subdiagram] = Tuple(d.hash for d in diag.subdiagram) -# d[:operator] = diag.operator -# d[:factor] = diag.factor -# d[:weight] = diag.weight - -# return d -# end - -function _addkey!(dict, key, val) - @assert haskey(dict, key) == false "key already exists!" - dict[key] = val -end - -function _DiagtoDict!(dict::Dict{Symbol,Any}, diagVec::Vector{Diagram{W}}; maxdepth::Int) where {W} - @assert maxdepth == 1 "deep convert has not yet been implemented!" - _addkey!(dict, :hash, [diag.hash for diag in diagVec]) - _addkey!(dict, :id, [diag.id for diag in diagVec]) - _addkey!(dict, :name, [diag.name for diag in diagVec]) - _addkey!(dict, :diagram, diagVec) - _addkey!(dict, :subdiagram, [Tuple(d.hash for d in diag.subdiagram) for diag in diagVec]) - _addkey!(dict, :operator, [diag.operator for diag in diagVec]) - _addkey!(dict, :factor, [diag.factor for diag in diagVec]) - _addkey!(dict, :weight, [diag.weight for diag in diagVec]) - return dict -end - -# function toDict(v::DiagramId) -# d = Dict{Symbol,Any}() -# for field in fieldnames(typeof(v)) -# data = getproperty(v, field) -# #DataFrame will expand a vector into multiple rows. To prevent it, we transform all vectors into tuples -# d[field] = data isa AbstractVector ? Tuple(data) : data -# end -# return d -# end - -function _vec2tup(data) - return data isa AbstractVector ? Tuple(data) : data -end - -function _IdstoDict!(dict::Dict{Symbol,Any}, diagVec::Vector{Diagram{W}}, idkey::Symbol) where {W} - sameId = all(x -> (typeof(x.id) == typeof(diagVec[1].id)), diagVec) - if sameId - data = [_vec2tup(getproperty(diagVec[1].id, idkey)),] - for idx in 2:length(diagVec) - push!(data, _vec2tup(getproperty(diagVec[idx].id, idkey))) - end - else - data = Vector{Any}() - for diag in diagVec - if hasproperty(diag.id, idkey) - tup = _vec2tup(getproperty(diag.id, idkey)) - # println(tup) - push!(data, tup) - else - push!(data, missing) - end - end - end - _addkey!(dict, idkey, data) - return dict -end - -function toDataFrame(diagVec::AbstractVector, idkey::Symbol; maxdepth::Int=1) - if idkey == :all || idkey == :All - names = Set{Symbol}() - for diag in diagVec - for field in fieldnames(typeof(diag.id)) - push!(names, field) - end - end - return toDataFrame(diagVec, collect(names); maxdepth=maxdepth) - else - return toDataFrame(diagVec, [idkey,]; maxdepth=maxdepth) - end -end - -function toDataFrame(diagVec::AbstractVector, idkey=Vector{Symbol}(); maxdepth::Int=1) - if isempty(diagVec) - return DataFrame() - end - d = Dict{Symbol,Any}() - _DiagtoDict!(d, diagVec, maxdepth=maxdepth) - - idkey = isnothing(idkey) ? Vector{Symbol}() : collect(idkey) - if isempty(idkey) == false - for _key in idkey - _IdstoDict!(d, diagVec, _key) - end - end - df = DataFrame(d, copycols=false) - # df = DataFrame(d) - return df -end - -# function toDataFrame(diagVec::AbstractVector; expand::Bool=false, maxdepth::Int=1) -# vec_of_diag_dict = [toDict(d, maxdepth=maxdepth) for d in diagVec] -# names = Set(reduce(union, keys(d) for d in vec_of_diag_dict)) -# if expand -# vec_of_id_dict = [toDict(d.id) for d in diagVec] -# idnames = Set(reduce(union, keys(d) for d in vec_of_id_dict)) -# @assert isempty(intersect(names, idnames)) "collision of diagram names $names and id names $idnames" -# names = union(names, idnames) - -# for (di, d) in enumerate(vec_of_diag_dict) -# merge!(d, vec_of_id_dict[di]) #add id dict into the diagram dict -# end -# end -# # println(names) -# df = DataFrame([name => [] for name in names]) - -# for dict in vec_of_diag_dict -# append!(df, dict, cols=:union) -# end -# return df -# end - -function _summary(diag::Diagram{W}, color=true) where {W} - - function short(factor, ignore=nothing) - if isnothing(ignore) == false && applicable(isapprox, factor, ignore) && factor β‰ˆ ignore - return "" - end - str = "$(factor)" - if factor isa Float64 - return length(str) <= 4 ? str : @sprintf("%6.3e", factor) - elseif factor isa Vector{Float64} - return length(str) <= 4 ? str : reduce(*, [@sprintf("%6.3e", f) for f in factor]) - else - return str - end - end - - namestr = diag.name == :none ? "" : "$(diag.name) " - idstr = "$namestr$(diag.id)" - fstr = short(diag.factor, one(diag.factor)) - wstr = short(diag.weight) - # =$(node.weight*(2Ο€)^(3*node.id.para.innerLoopNum)) - - if length(diag.subdiagram) == 0 - return isempty(fstr) ? "$idstr=$wstr" : "$(idstr)β‹…$(fstr)=$wstr" - else - return "$idstr=$wstr=$fstr$(diag.operator) " - end -end - -function Base.show(io::IO, diag::Diagram) - if length(diag.subdiagram) == 0 - typestr = "" - else - subdiag = prod(["$(d.hash), " for d in diag.subdiagram[1:end-1]]) - subdiag *= "$(diag.subdiagram[end].hash)" - typestr = "($subdiag)" - end - print(io, "$(diag.hash):$(_summary(diag, true))$typestr") -end - -""" - function plot_tree(diag::Diagram; verbose = 0, maxdepth = 6) - - Visualize the diagram tree using ete3 python package - -#Arguments -- `diag` : the Diagram struct to visualize -- `verbose=0` : the amount of information to show -- `maxdepth=6` : deepest level of the diagram tree to show -""" -function plot_tree(diag::Diagram; verbose=0, maxdepth=20) - - # pushfirst!(PyVector(pyimport("sys")."path"), @__DIR__) #comment this line if no need to load local python module - ete = PyCall.pyimport("ete3") - - function treeview(node, level, t=ete.Tree(name=" ")) - if level > maxdepth - return - end - nt = t.add_child(name="$(node.hash): $(_summary(node, false))") - - if length(node.subdiagram) > 0 - name_face = ete.TextFace(nt.name, fgcolor="black", fsize=10) - nt.add_face(name_face, column=0, position="branch-top") - for child in node.subdiagram - treeview(child, level + 1, nt) - end - end - - return t - end - - t = treeview(diag, 1) - - # NOTE: t.set_style does not update the original PyObject as expected, i.e., - # `t.set_style(ete.NodeStyle(bgcolor="Khaki"))` does not modify t. - # - # The low-level approach circumvents this by directly updating the original PyObject `t."img_style"` - PyCall.set!(t."img_style", "bgcolor", "Khaki") - - ts = ete.TreeStyle() - ts.show_leaf_name = true - # ts.show_leaf_name = True - # ts.layout_fn = my_layout - ####### show tree vertically ############ - # ts.rotation = 90 #show tree vertically - - ####### show tree in an arc ############# - # ts.mode = "c" - # ts.arc_start = -180 - # ts.arc_span = 180 - # t.write(outfile="/home/kun/test.txt", format=8) - t.show(tree_style=ts) -end -function plot_tree(diags::Vector{Diagram{W}}; kwargs...) where {W} - for diag in diags - plot_tree(diag; kwargs...) - end -end -function plot_tree(df::DataFrame; kwargs...) - plot_tree(df.diagram; kwargs...) -end \ No newline at end of file diff --git a/archived/src/diagram_tree/operation.jl b/archived/src/diagram_tree/operation.jl deleted file mode 100644 index eeeb863a..00000000 --- a/archived/src/diagram_tree/operation.jl +++ /dev/null @@ -1,147 +0,0 @@ -function oneOrderHigher(diag::Diagram{W}, ::Type{Id}, subdiagram=[]; - index::Int=index(Id), #which index to increase the order - operator::Operator=diag.operator, - name::Symbol=diag.name, factor::W=diag.factor) where {W,Id} - # if diag.id isa PropagatorId && (diag.id isa Id) == false - # #for bare propagator, a derivative of different id vanishes - # return nothing - # end - id = deepcopy(diag.id) - @assert index <= length(id.order) "$(id) only supports derivatives up to the index $(length(id.order))!" - id.order[index] += 1 - d = Diagram{W}(id, operator, subdiagram; name=name, factor=factor) - return d -end - -function hasOrderHigher(diag::Diagram{W}, ::Type{ID}) where {W,ID<:PropagatorId} - if diag.id isa ID - #for bare propagator, a derivative of different id vanishes - return true - else - return false - end -end - -""" - function derivative(diags::Union{Tuple,AbstractVector}, ::Type{ID}; index::Int=index(ID)) where {W,ID<:PropagatorId} - function derivative(diags::Vector{Diagram{W}}, ::Type{ID}; index::Int=index(ID)) where {W,ID<:PropagatorId} - - Automatic differentiation derivative on the diagrams - -# Arguments -- diags : diagrams to take derivative -- ID : DiagramId to apply the differentiation -- index : index of the id.order array element to increase the order -""" -function derivative(diags::Union{Tuple,AbstractVector}, ::Type{ID}; index::Int=index(ID)) where {ID<:PropagatorId} - if isempty(diags) - return diags - else - diags = collect(diags) - diags = derivative(diags, ID; index=index) - return diags - end -end - -function derivative(diags::Vector{Diagram{W}}, ::Type{ID}; index::Int=index(ID)) where {W,ID<:PropagatorId} - # use a dictionary to host the dual diagram of a diagram for a given hash number - # a dual diagram is defined as the derivative of the original diagram - - dual = Dict{Int,Diagram{W}}() - for diag in diags - for d::Diagram{W} in PostOrderDFS(diag) # postorder traversal will visit all subdiagrams of a diagram first - if haskey(dual, d.hash) - continue - end - if d.id isa PropagatorId - # for propagators like bare Green's function and interaction, derivative simply means increase an order by one - if hasOrderHigher(d, ID) - dual[d.hash] = oneOrderHigher(d, ID; index=index) - end - else # composite diagram - if d.operator isa Sum - # for a diagram which is a sum of subdiagrams, derivative means a sub of derivative subdiagrams - children = [dual[sub.hash] for sub in d.subdiagram if haskey(dual, sub.hash)] - if isempty(children) == false - dual[d.hash] = oneOrderHigher(d, ID, children; index=index) - end - elseif d.operator isa Prod - # d = s1xs2x... = s1'xs2x... + s1xs2'x... + ... - terms = Vector{Diagram{W}}() - for (si, sub) in enumerate(d.subdiagram) - if haskey(dual, sub.hash) == false - continue - end - children = [si == sj ? dual[sub.hash] : sub for (sj, sub) in enumerate(d.subdiagram)] - if isempty(children) == false - push!(terms, oneOrderHigher(d, ID, children; index=index)) - end - end - - if isempty(terms) == false - # !the summed dual diagram must have factor = 1.0 - dual[d.hash] = oneOrderHigher(d, ID, terms; index=index, name=Symbol("$(d.name)'"), factor=W(1), operator=Sum()) - end - else - error("not implemented!") - end - end - end - end - return [dual[diag.hash] for diag in diags if haskey(dual, diag.hash)] -end - -""" - function derivative(diags::Union{Diagram,Tuple,AbstractVector}, ::Type{ID}, order::Int) where {ID<:PropagatorId} - - Automatic differentiation derivative on the diagrams - -# Arguments -- diags : diagrams to take derivative -- ID : DiagramId to apply the differentiation -- order::Int : derivative order -""" -function derivative(diags::Union{Tuple,AbstractVector}, ::Type{ID}, order::Int; index::Int=index(ID)) where {ID<:PropagatorId} - @assert order >= 0 - if order == 0 - return diags - end - result = diags - for o in 1:order - result = derivative(result, ID; index=index) - end - return result -end - -""" - function removeHartreeFock!(diag::Diagram{W}) where {W} - function removeHartreeFock!(diags::Union{Tuple,AbstractVector}) - - Remove the Hartree-Fock insertions that without any derivatives on the propagator and the interaction. - -# Arguments -- diags : diagrams to remove the Fock insertion - -# Remarks -- The operations removeHartreeFock! and taking derivatives doesn't commute with each other! -- If the input diagram is a Hartree-Fock diagram, then the overall weight will become zero! -- The return value is always nothing -""" -function removeHartreeFock!(diag::Diagram{W}) where {W} - for d in PreOrderDFS(diag) - # for subdiag in d.subdiagram - if d.id isa SigmaId - # println(d, " with ", d.id.para.innerLoopNum) - if isempty(d.id.order) || all(x -> x == 0, d.id.order) #eithr order is empty or a vector of zeros - if d.id.para.innerLoopNum == 1 - d.factor = 0.0 - end - end - end - end -end -function removeHartreeFock!(diags::Union{Tuple,AbstractVector}) - for diag in diags - removeHartreeFock!(diag) - end -end \ No newline at end of file diff --git a/archived/src/diagram_tree/optimize.jl b/archived/src/diagram_tree/optimize.jl deleted file mode 100644 index 2b0d6bbf..00000000 --- a/archived/src/diagram_tree/optimize.jl +++ /dev/null @@ -1,126 +0,0 @@ -function optimize!(diag::Union{Tuple,AbstractVector}, optlevel=1; verbose=0, normalize=nothing) - if isempty(diag) - return diag - else - diag = collect(diag) - removeOneChildParent!(diag, verbose=verbose) - removeDuplicatedLeaves!(diag, verbose=verbose, normalize=normalize) - return diag - end -end - -""" - removeOneChildParent!(diags::AbstractVector; verbose = 0) - - remove duplicated nodes such as: ---> ver4 ---> InteractionId. Leaf will not be touched! -""" -function removeOneChildParent!(diags::Vector{Diagram{W}}; verbose=0) where {W} - verbose > 0 && println("remove nodes with only one child.") - for diag in diags - #deep first search, remove one-child parent from the leaf level first - removeOneChildParent!(diag.subdiagram) - #then remove the one-child subdiagram of the current diagram - for (si, subdiag) in enumerate(diag.subdiagram) - if length(subdiag.subdiagram) == 1 - subdiag.subdiagram[1].factor *= subdiag.factor - diag.subdiagram[si] = subdiag.subdiagram[1] - end - end - end - return diags -end - -""" - removeDuplicatedLeaves!(diags::AbstractVector; verbose = 0) - - remove duplicated nodes such as: ---> ver4 ---> InteractionId. Leaf will not be touched! -""" -function removeDuplicatedLeaves!(diags::Vector{Diagram{W}}; verbose=0, normalize=nothing, kwargs...) where {W} - verbose > 0 && println("remove duplicated leaves.") - leaves = Vector{Diagram{W}}() - for diag in diags - #leaves must be the propagators - append!(leaves, collect(Leaves(diag))) - end - # println([d.hash for d in leaves]) - if isnothing(normalize) == false - @assert normalize isa Function "a function call is expected for normalize" - for leaf in leaves - normalize(leaf.id) - end - end - sort!(leaves, by=x -> x.hash) #sort the hash of the leaves in an asscend order - unique!(x -> x.hash, leaves) #filter out the leaves with the same hash number - - for l in leaves - #make sure all leaves are either Green's functions or interactions - @assert l.id isa PropagatorId - end - - function uniqueLeaves(_diags::Vector{Diagram{W}}) where {W} - ############### find the unique Leaves ##################### - uniqueDiag = [] - mapping = Dict{Int,Any}() - for diag in _diags - flag = true - for (ei, e) in enumerate(uniqueDiag) - if e.factor β‰ˆ diag.factor && e.id == diag.id - mapping[diag.hash] = e - flag = false - break - end - end - if flag - push!(uniqueDiag, diag) - # push!(mapping, length(uniqueDiag)) - mapping[diag.hash] = diag - end - end - return uniqueDiag, mapping - end - - # println(leaves) - green = [l for l in leaves if l.id isa BareGreenId] - interaction = [l for l in leaves if l.id isa BareInteractionId] - greenN = [l for l in leaves if l.id isa BareGreenNId] - hopping = [l for l in leaves if l.id isa BareHoppingId] - # println(green) - # println(interaction) - - uniqueGreen, greenMap = uniqueLeaves(green) - uniqueGreenN, greenNMap = uniqueLeaves(greenN) - uniqueInteraction, interactionMap = uniqueLeaves(interaction) - uniqueHopping, hoppingMap = uniqueLeaves(hopping) - # println(uniqueInteraction) - # display(greenMap) - - verbose > 0 && length(green) > 0 && println("Number of independent Greens $(length(green)) β†’ $(length(uniqueGreen))") - verbose > 0 && length(greenN) > 0 && println("Number of independent GreenNs $(length(greenN)) β†’ $(length(uniqueGreenN))") - verbose > 0 && length(interaction) > 0 && println("Number of independent Interactions $(length(interaction)) β†’ $(length(uniqueInteraction))") - verbose > 0 && length(hopping) > 0 && println("Number of independent Hopping $(length(hopping)) β†’ $(length(uniqueHopping))") - - for diag in diags - for n in PreOrderDFS(diag) - for (si, subdiag) in enumerate(n.subdiagram) - @assert (n.id isa PropagatorId) == false "the diagram $n with subdiagrams cannot be a proapgator!" - - if subdiag.id isa PropagatorId - if subdiag.id isa BareGreenId - n.subdiagram[si] = greenMap[subdiag.hash] - elseif subdiag.id isa BareInteractionId - n.subdiagram[si] = interactionMap[subdiag.hash] - elseif subdiag.id isa BareGreenNId - n.subdiagram[si] = greenNMap[subdiag.hash] - elseif subdiag.id isa BareHoppingId - n.subdiagram[si] = hoppingMap[subdiag.hash] - else - error("not implemented!") - end - end - end - end - end - - return uniqueGreen, uniqueInteraction - # return diags -end \ No newline at end of file diff --git a/archived/src/diagram_tree/traits.jl b/archived/src/diagram_tree/traits.jl deleted file mode 100644 index 1cf382af..00000000 --- a/archived/src/diagram_tree/traits.jl +++ /dev/null @@ -1,255 +0,0 @@ -abstract type Operator end -struct Sum <: Operator end -struct Prod <: Operator end -Base.isequal(a::Operator, b::Operator) = (typeof(a) == typeof(b)) -Base.:(==)(a::Operator, b::Operator) = Base.isequal(a, b) -apply(o::Operator, diags) = error("not implemented!") - -Base.show(io::IO, o::Operator) = print(io, typeof(o)) -Base.show(io::IO, o::Sum) = print(io, "⨁") -Base.show(io::IO, o::Prod) = print(io, "Ⓧ") - -""" - abstract type DiagramId end - - The abstract type of all diagrams/subdiagrams/bare propagators -""" -abstract type DiagramId end - -""" - abstract type PropagatorId <: DiagramId end - - The abstract type of all bare propagators -""" -abstract type PropagatorId <: DiagramId end - -# Base.Dict(x::DiagramId) = Dict{Symbol,Any}([fn => getfield(x, fn) for fn ∈ fieldnames(typeof(x))]) -# Base.show(io::IO, d::DiagramId) = error("Base.show not implemented!") -# Base.isequal(a::DiagramId, b::DiagramId) = error("Base.isequal not implemented!") -Base.:(==)(a::DiagramId, b::DiagramId) = Base.isequal(a, b) - -struct BareGreenId <: PropagatorId - para::DiagPara - type::AnalyticProperty #Instant, Dynamic, D_Instant, D_Dynamic - extK::Vector{Float64} - extT::Tuple{Int,Int} #all possible extT from different interactionType - order::Vector{Int} - function BareGreenId(para::DiagPara, type::AnalyticProperty=Dynamic, order=[0, 0, 0, 0]; k, t) - return new(para, type, k, Tuple(t), order) - end -end -Base.show(io::IO, v::BareGreenId) = print(io, "$(short(v.type))#$(v.order), k$(v.extK), t$(v.extT)") - -struct BareInteractionId <: PropagatorId - para::DiagPara - response::Response #UpUp, UpDown, ... - type::AnalyticProperty #Instant, Dynamic, D_Instant, D_Dynamic - permutation::Permutation - extK::Vector{Float64} - extT::Tuple{Int,Int} #all possible extT from different interactionType - order::Vector{Int} - function BareInteractionId(para::DiagPara, response::Response, type::AnalyticProperty=Instant, order=[0, 0, 0, 0]; k, t=(0, 0), permu::Permutation=DiEx) - return new(para, response, type, permu, k, Tuple(t), order) - end -end -Base.show(io::IO, v::BareInteractionId) = print(io, "$(short(v.response))$(short(v.type))$(v.permutation)#$(v.order), k$(v.extK), t$(v.extT)") - -struct GenericId <: DiagramId - para::DiagPara - extra::Any - order::Vector{Int} - GenericId(para::DiagPara, extra=Nothing, order=[0, 0, 0, 0]) = new(para, extra, order) -end -Base.show(io::IO, v::GenericId) = print(io, v.extra == Nothing ? "#$(v.order)" : "$(v.extra)#$(v.order)") - -struct GreenId <: DiagramId - para::DiagPara - type::AnalyticProperty #Instant, Dynamic, D_Instant, D_Dynamic - extK::Vector{Float64} - extT::Tuple{Int,Int} #all possible extT from different interactionType - order::Vector{Int} - function GreenId(para::DiagPara, type::AnalyticProperty=Dynamic, order=[0, 0, 0, 0]; k, t) - return new(para, type, k, Tuple(t), order) - end -end -Base.show(io::IO, v::GreenId) = print(io, "$(short(v.type))#$(v.order), k$(v.extK), t$(v.extT)") - -struct SigmaId <: DiagramId - para::DiagPara - type::AnalyticProperty #Instant, Dynamic, D_Instant, D_Dynamic - extK::Vector{Float64} - extT::Tuple{Int,Int} #all possible extT from different interactionType - order::Vector{Int} - function SigmaId(para::DiagPara, type::AnalyticProperty, order=[0, 0, 0, 0]; k, t=(0, 0)) - return new(para, type, k, t, order) - end -end -Base.show(io::IO, v::SigmaId) = print(io, "$(short(v.type))#$(v.order), t$(v.extT)") - -struct PolarId <: DiagramId - para::DiagPara - response::Response #UpUp, UpDown, ... - extK::Vector{Float64} - extT::Tuple{Int,Int} #all possible extT from different interactionType - order::Vector{Int} - function PolarId(para::DiagPara, response::Response, order=[0, 0, 0, 0]; k, t=(0, 0)) - return new(para, response, k, t, order) - end -end -Base.show(io::IO, v::PolarId) = print(io, "$(short(v.response))#$(v.order), k$(v.extK), t$(v.extT)") - -struct Ver3Id <: DiagramId - para::DiagPara - response::Response #UpUp, UpDown, ... - extK::Vector{Vector{Float64}} - extT::Tuple{Int,Int,Int} #all possible extT from different interactionType - order::Vector{Int} - function Ver3Id(para::DiagPara, response::Response, order=[0, 0, 0, 0]; k, t=(0, 0, 0)) - return new(para, response, k, Tuple(t), order) - end -end -Base.show(io::IO, v::Ver3Id) = print(io, "$(short(v.response))#$(v.order),t$(v.extT)") - -struct Ver4Id <: DiagramId - para::DiagPara - response::Response #UpUp, UpDown, ... - type::AnalyticProperty #Instant, Dynamic, D_Instant, D_Dynamic - channel::TwoBodyChannel # particle-hole, particle-hole exchange, particle-particle, irreducible - extK::Vector{Vector{Float64}} - extT::Tuple{Int,Int,Int,Int} #all possible extT from different interactionType - order::Vector{Int} - function Ver4Id(para::DiagPara, response::Response, type::AnalyticProperty=Dynamic, order=[0, 0, 0, 0]; k, t=(0, 0, 0, 0), chan::TwoBodyChannel=AnyChan) - return new(para, response, type, chan, k, Tuple(t), order) - end -end -Base.show(io::IO, v::Ver4Id) = print(io, (v.channel == AnyChan ? "" : "$(v.channel) ") * "$(short(v.response))$(short(v.type))#$(v.order),t$(v.extT)") - -function vstr(r, c) - N = length(r) - # cstr(x) = x ? "⁺" : "⁻" - s = "" - for i = 1:N-1 - s *= "$(r[i])$c" - end - s *= "$(r[end])$c" - return s -end - -function vcstr(r, creation) - N = length(r) - # cstr(x) = x ? "⁺" : "⁻" - s = "" - for i = 1:N-1 - if creation[i] - s *= "$(r[i])⁺" - else - s *= "$(r[i])⁻" - end - end - if creation[end] - s *= "$(r[end])⁺" - else - s *= "$(r[end])⁻" - end - return s -end - -""" -hopping function c⁺c⁻ -""" -struct BareHoppingId <: PropagatorId - para::DiagPara - site::Tuple{Int,Int} - orbital::Tuple{Int,Int} - extT::Tuple{Int,Int} - function BareHoppingId(para::DiagPara, orbital, t, r) - return new(para, r, orbital, t) - end -end -Base.show(io::IO, v::BareHoppingId) = print(io, "($(vstr(v.site, "α΅£"))|$(vstr(v.orbital, "β‚’"))|$(vcstr(v.extT, [true, false])))") - -""" -time-ordered N-point Bare Green's function -""" -struct BareGreenNId <: PropagatorId - para::DiagPara - site::Int - creation::Vector{Bool} - orbital::Vector{Int} - extT::Vector{Int} - N::Int - function BareGreenNId(para::DiagPara; orbital=[], t=[], creation=[], r=0) - @assert length(orbital) == length(t) == length(creation) - return new(para, r, creation, orbital, t, length(orbital)) - end -end -Base.show(io::IO, v::BareGreenNId) = print(io, "($(v.site)α΅£|$(vstr(v.orbital, "β‚’"))|$(vcstr(v.extT, v.creation)))") - -""" -time-ordered N-point Composite Green's function -""" -struct GreenNId <: DiagramId - para::DiagPara - site::Vector{Int} - creation::Vector{Bool} - orbital::Vector{Int} - extT::Vector{Int} - N::Int - function GreenNId(para::DiagPara; orbital=[], t=[], creation=[], r=[]) - @assert length(orbital) == length(t) == length(r) == length(creation) - return new(para, r, creation, orbital, t, length(orbital)) - end -end -Base.show(io::IO, v::GreenNId) = print(io, "($(vstr(v.site, "α΅£"))|$(vstr(v.orbital, "β‚’"))|$(vcstr(v.extT, v.creation)))") - -""" -time-ordered N-point Composite Green's function -""" -struct ConnectedGreenNId <: DiagramId - para::DiagPara - site::Vector{Int} - creation::Vector{Bool} - orbital::Vector{Int} - extT::Vector{Int} - N::Int - function ConnectedGreenNId(para::DiagPara; orbital=[], t=[], creation=[], r=[]) - @assert length(orbital) == length(t) == length(r) == length(creation) - return new(para, r, creation, orbital, t, length(orbital)) - end -end -Base.show(io::IO, v::ConnectedGreenNId) = print(io, "($(vstr(v.site, "α΅£"))|$(vstr(v.orbital, "β‚’"))|$(vcstr(v.extT, v.creation)))") - -function Base.isequal(a::DiagramId, b::DiagramId) - if typeof(a) != typeof(b) - return false - end - for field in fieldnames(typeof(a)) - field in [:para, :permutation] && continue - if field == :extK - if !(getproperty(a, :extK) β‰ˆ getproperty(b, :extK)) && !(getproperty(a, :extK) β‰ˆ -getproperty(b, :extK)) - return false - end - continue - end - if getproperty(a, field) != getproperty(b, field) - return false - end - end - return true -end - -function index(type) - if type == BareGreenId - return 1 - elseif type == BareInteractionId - return 2 - elseif type == BareGreenNId - return 3 - elseif type == BareHoppingId - return 4 - else - error("Not Implemented!") - end -end - - diff --git a/archived/src/diagram_tree/tree.jl b/archived/src/diagram_tree/tree.jl deleted file mode 100644 index fc30a5c1..00000000 --- a/archived/src/diagram_tree/tree.jl +++ /dev/null @@ -1,275 +0,0 @@ -# Base.hash(d::DiagramId) = hash(d) % 1000000 -""" - mutable struct Diagram{W} - - struct of a diagram. A diagram of a sum or produce of various subdiagrams. - -# Members -- hash::Int : the unique hash number to identify the diagram -- name::Symbol : name of the diagram -- id::DiagramId : diagram id -- operator::Operator : operation, support Sum() and Prod() -- factor::W : additional factor of the diagram -- subdiagram::Vector{Diagram{W}} : vector of sub-diagrams -- weight::W : weight of the diagram -""" -mutable struct Diagram{W} - hash::Int - name::Symbol - id::DiagramId - operator::Operator - factor::W - subdiagram::Vector{Diagram{W}} - - weight::W - # parent::Diagram - - """ - function Diagram{W}(id::DiagramId, operator::Operator = Sum(), subdiagram = []; name = :none, factor = W(1), weight = W(0)) where {W} - - construct Diagram struct. - - # Arguments - - id : DiagramId of the diagram - - operator : Sum() or Prod() - - subdiagram : subdiagrams of the diagram, it should be a vector of Diagram struct - - name : name of the diaram - - factor : the additional factor of the diagram - - weight : the initial weight - """ - function Diagram{W}(id::DiagramId, operator::Operator=Sum(), subdiagram=[]; - name=:none, factor=W(1), weight=W(0)) where {W} - # return new{W}(uid(), name, id, operator, factor, deepcopy(subdiagram), weight) - return new{W}(uid(), name, id, operator, factor, subdiagram, weight) - end - # function Diagram(id::DiagramId, operator::Operator=Sum(), subdiagram=[]; type::DataType=id.para.weightType, - # name=:none, factor=one(type), weight=zero(type)) - # # return new{type}(uid(), name, id, operator, factor, deepcopy(subdiagram), weight) - # return new{type}(uid(), name, id, operator, factor, subdiagram, weight) - # end -end - -isbare(diag::Diagram) = isempty(diag.subdiagram) - -# function addSubDiagram!(parent::Diagram, child::Diagram) -# for c in parent.subdiagram -# if c.id == child.id -# return false -# end -# end -# push!(parent.subdiagram, deepcopy(child)) -# end - -# function addSubDiagram!(parent::Diagram, child::Vector{Diagram{W}}) where {W} -# for d in child -# addSubDiagram!(parent, d) -# end -# end - -# _diagram(df, index) = df[index, :Diagram] - -function _combinegroups(groups, getid, factor, operator, name) - # combine diagrams in a group into one composite diagram - gdf = combine(groups) do group # for each group in groups - # check the documentation of ``combine" for details https://dataframes.juliadata.org/stable/man/split_apply_combine/ - # id = isnothing(getid) ? GenericId(group.diagram[1].id.para, Tuple(group[1, fields])) : getid(group) - id = getid(group) - - if nrow(group) == 1 - # if there is only one diagram in df, and the new id is either GenericId or the id of the existing diagram, - # then simply return the current df without creating a new diagram - # ! the new factor will be multiplied to the factor of the exisiting diagram! - if id isa GenericId || typeof(id) == typeof(group.diagram[1].id) - # diag = deepcopy(group[1, :diagram]) - diag = group.diagram[1] - diag.factor *= factor - return (diagram=diag, hash=diag.hash) - end - end - W = typeof(group.diagram[1].weight) - diag = Diagram{W}(id, operator, group.diagram, name=name, factor=factor) - return (diagram=diag, hash=diag.hash) - end - return gdf -end - -function _mergediag(::Type{W}, group, factor, id, operator, name) where {W} - if nrow(group) == 1 - # if there is only one diagram in df, and the new id is either GenericId or the id of the existing diagram, - # then simply return the current df without creating a new diagram - # ! the new factor will be multiplied to the factor of the exisiting diagram! - if id isa GenericId || typeof(id) == typeof(group.diagram[1].id) - # diag = deepcopy(group[1, :diagram]) - diag::Diagram{W} = group.diagram[1] - diag.factor *= factor - return diag - end - end - return Diagram{W}(id, operator, group.diagram, name=name, factor=factor) -end - -function _combine(::Type{W}, groups, factor, getid, operator, name) where {W} - """ - # if fields = [:response, :extT], then - - # 1. groups.cols is like: Vector{Symbol}[:response, :extT] - - # 2. groups.keymap is like: - - # Dict{Any, Int64} with 2 entries: - # (UpDown, (1, 1, 1, 1)) => 2 - # (UpUp, (1, 1, 1, 1)) => 1 - # """ - d = Dict{Symbol,Any}() - _keys = keys(groups) - for col in groupcols(groups) - d[col] = [key[col] for key in _keys] - end - d[:diagram] = [_mergediag(W, groups[key], factor, getid(groups[key]), operator, name) for key in _keys] - d[:hash] = [diag.hash for diag in d[:diagram]] - return DataFrame(d, copycols=false) -end - -function mergeby(df::DataFrame, fields=Vector{Symbol}(); - operator=Sum(), name::Symbol=:none, factor=1.0, - getid::Function=g -> GenericId(g[1, :diagram].id.para, Tuple(g[1, fields])) -) - if isempty(df) - return df - else - W = typeof(df.diagram[1].weight) - return mergeby(W, df, fields; operator=operator, name=name, factor=factor, getid=getid) - end -end - -function mergeby(::Type{W}, df::DataFrame, fields=Vector{Symbol}(); - operator=Sum(), name::Symbol=:none, factor=1.0, - getid::Function=g -> GenericId(g[1, :diagram].id.para, Tuple(g[1, fields])) -) where {W} - if isempty(df) - return df - else - if all(x -> typeof(x.id) == typeof(df.diagram[1].id), df[!, :diagram]) == false - @warn "Not all DiagramIds in $df are the same!" - end - groups = DataFrames.groupby(df, fields, sort=true) - ######## less memory usage but can not pass the test right now ############## - d = _combine(W, groups, factor, getid, operator, name) - ######## alternative approach (more memory) ################## - # d = _combinegroups(groups, getid, factor, operator, name) - # println("old\n$d \n new\n$cd") - return d - end -end - -function mergeby(diags::Union{Diagram,Tuple,AbstractVector}, fields=nothing; idkey=nothing, kwargs...) - if diags isa Diagram - return diags - else - if isempty(diags) - return diags - else - W = typeof(diags[1].weight) - @assert all(x -> (x.weight isa W), diags) "all diagrams should be of the same type. \n$diags" - diags = collect(diags) - if isnothing(fields) && isnothing(idkey) - return mergeby(diags; kwargs...) - else - return mergeby(diags, fields; idkey=idkey, kwargs...) - end - end - end -end - -# function mergeby(diags::AbstractVector, fields=[]; idkey::Vector{Symbol}=[], kwargs...) -function mergeby(diags::Vector{Diagram{W}}, fields; idkey=Vector{Symbol}(), kwargs...) where {W} - if isempty(diags) - return diags - else - df = toDataFrame(diags, idkey) - mergedf = mergeby(df, fields; kwargs...) - return Vector{Diagram{W}}(mergedf.diagram) - end -end - -function mergeby(diags::Vector{Diagram{W}}; - operator=Sum(), name::Symbol=:none, factor=1.0, - getid::Function=d -> GenericId(d[1].id.para::DiagPara{W}) -) where {W} - if isempty(diags) - return diags - else - id = getid(diags) - if length(diags) == 1 && (id isa GenericId || typeof(id) == typeof(diags[1].id)) - # if there is only one diagram, and the new id is either GenericId or the id of the existing diagram, - # then simply return the current diagram without creating a new diagram - # ! the new factor will be multiplied to the factor of the exisiting diagram! - diags[1].factor *= factor - return diags - end - diag = Diagram{W}(id, operator, diags, name=name, factor=factor) - return [diag,] - end -end -# mergeby(df::DataFrame; kwargs...) = mergeby(df, []; kwargs...) -# mergeby(diags::Vector{Diagram{W}}; kwargs...) where {W} = mergeby(diags, []; kwargs...) - - - -##################### interface to AbstractTrees ########################### -function AbstractTrees.children(diag::Diagram) - return diag.subdiagram -end - -## Things that make printing prettier -AbstractTrees.printnode(io::IO, diag::Diagram) = print(io, "\u001b[32m$(diag.hash)\u001b[0m : $diag") -# AbstractTrees.printnode(io::IO, diag::Diagram) = print(io, "$(diag)") - -######### define the following for the type stability ######################### -# AbstractTrees.childrentype(diag::Diagram{W}) where {W} = Vector{Diagram{W}} - -# AbstractTrees.NodeType(::Diagram{W}) where {W} = HasNodeType() -AbstractTrees.nodetype(::Diagram{W}) where {W} = Diagram{W} - -## Optional enhancements -# These next two definitions allow inference of the item type in iteration. -# (They are not sufficient to solve all internal inference issues, however.) -Base.eltype(::Type{<:TreeIterator{Diagram{W}}}) where {W} = Diagram{W} -Base.IteratorEltype(::Type{<:TreeIterator{Diagram{W}}}) where {W} = Base.HasEltype() - -function count_operation(g::T) where {T<:Diagram} - totalsum = 0 - totalprod = 0 - for node in PreOrderDFS(g) - #print(node.hash) - if length(node.subdiagram) > 0 - if node.operator isa Prod - totalprod += length(node.subdiagram) - 1 - elseif node.operator isa Sum - totalsum += length(node.subdiagram) - 1 - end - end - end - return [totalsum, totalprod] -end - -function count_operation(g::Vector{T}) where {T<:Diagram} - visited = Set{Int}() - totalsum = 0 - totalprod = 0 - for graph in g - for node in PreOrderDFS(graph) - if !(node.hash in visited) - push!(visited, node.hash) - if length(node.subdiagram) > 0 - if node.operator isa Prod - totalprod += length(node.subdiagram) - 1 - elseif node.operator isa Sum - totalsum += length(node.subdiagram) - 1 - end - end - end - end - end - return [totalsum, totalprod] -end diff --git a/archived/src/diagtree.jl b/archived/src/diagtree.jl deleted file mode 100644 index 01b38a07..00000000 --- a/archived/src/diagtree.jl +++ /dev/null @@ -1,91 +0,0 @@ -""" - function Graph!(d::DiagTree.Diagram{W}; map=Dict{Int,DiagTree.DiagramId}()) where {W} - -Converts a DiagTree `d` into a Graph, storing the diagram information (which is a DiagramId object) in a Graph.id to DiagramId dictionary ``map". - -# Arguments: -- `d`: DiagTree.Diagram object. -- `map`: map between the Graph.id and DiagramId. It will be updated with the new nodes and leaves contained in the DiagTree.Diagram `d`. - - -# Example: -```julia-repl -julia> para = DiagParaF64(type = Ver4Diag, innerLoopNum=2); - -julia> ver4=Parquet.build(para) -2Γ—5 DataFrame - Row β”‚ diagram extT hash response type - β”‚ Diagram… Tuple… Int64 Response Analytic… -─────┼───────────────────────────────────────────────────────────────────────────── - 1 β”‚ 5978:↑↑Dyn#[0, 0, 0, 0],t(1, 1, … (1, 1, 1, 1) 5978 UpUp Dynamic - 2 β”‚ 5979:↑↓Dyn#[0, 0, 0, 0],t(1, 1, … (1, 1, 1, 1) 5979 UpDown Dynamic - -julia> d = ver4.diagram[1] # take the first diagram -5978:↑↑Dyn#[0, 0, 0, 0],t(1, 1, 1, 1)=0.0=⨁ (5026, 5071, 5137, 5146, 5175, 5220, 5312, 5321, 5350, 5396, 5463, 5473, 5503, 5549, 5642, 5652, 5682, 5793, 5831, 5968) - -julia> root = FrontEnds.Graph!(d) -``` - -""" -# function Graph!(d::DiagTree.Diagram{W}; map=Dict{Int,DiagTree.DiagramId}()) where {W} -function Graph!(d::DiagTree.Diagram{W}) where {W} - - function op(o) - if o isa DiagTree.Sum - return ComputationalGraphs.Sum() - elseif o isa DiagTree.Prod - return ComputationalGraphs.Prod() - else - error("Unknown operator: $o") - end - end - - subgraphs = ComputationalGraphs.Graph{W,W}[] - for g in d.subdiagram - # res, map = Graph!(g; map=map) - res = Graph!(g) - push!(subgraphs, res) - end - - # if isempty(subgraphs) - # root = ComputationalGraphs.Graph(subgraphs; subgraph_factors=ones(W, length(subgraphs)), factor=d.factor, name=String(d.name), - # operator=op(d.operator), orders=d.id.order, ftype=W, wtype=W, weight=d.weight, properties=d.id) - # else - # tree = ComputationalGraphs.Graph(subgraphs; subgraph_factors=ones(W, length(subgraphs)), - # operator=op(d.operator), orders=d.id.order, ftype=W, wtype=W, weight=d.weight) - # root = ComputationalGraphs.Graph([tree,]; subgraph_factors=[d.factor,], orders=tree.orders, - # ftype=W, wtype=W, weight=d.weight * d.factor) - # end - - root = ComputationalGraphs.Graph(subgraphs; subgraph_factors=ones(W, length(subgraphs)), factor=d.factor, name=String(d.name), - operator=op(d.operator), orders=d.id.order, ftype=W, wtype=W, weight=d.weight, properties=d.id) - return root - # @assert haskey(map, root.id) == false "DiagramId already exists in map: $(root.id)" - # @assert haskey(map, tree.id) == false "DiagramId already exists in map: $(tree.id)" - # map[root.id] = d.id - # map[tree.id] = d.id - - # return root, map -end - -""" - function extract_var_dependence(map::Dict{Int,DiagTree.DiagramId}, ::Type{ID}, numvars::Int) - - Given a map between graph id and DiagramId, extract the variable dependence of all graphs. - -# Arguments: -- `map::Dict{Int,DiagTree.DiagramId}`: A dictionary mapping graph ids to DiagramIds. DiagramId stores the diagram information of the corresponding graph. -- `ID`: The particular type of ID that has the given variable dependence. -- `numvars`: The number of variables which the diagram depends on. -""" -function extract_var_dependence(map::Dict{Int,DiagTree.DiagramId}, ::Type{ID}; numvars::Int=1) where {ID<:PropagatorId} - var_dependence = Dict{Int,Vector{Bool}}() - for (id, diagID) in map - if diagID isa ID - var_dependence[id] = [true for _ in 1:numvars] - else - var_dependence[id] = [false for _ in 1:numvars] - end - end - return var_dependence -end \ No newline at end of file diff --git a/archived/src/expression_tree/ExpressionTree.jl b/archived/src/expression_tree/ExpressionTree.jl deleted file mode 100644 index f669ce2e..00000000 --- a/archived/src/expression_tree/ExpressionTree.jl +++ /dev/null @@ -1,29 +0,0 @@ -module ExprTree -using AbstractTrees, LinearAlgebra, StaticArrays -import LinearAlgebra: BlasInt -using ..DiagTree -# using Unrolled -# using InteractiveUtils - -using Printf, PyCall - -const ADD, MUL = 1, 2 -export ADD, MUL - -include("common.jl") - -# struct Cache and struct Pool -include("pool.jl") - -include("tree.jl") -export ExpressionTree - -# IO operations -include("io.jl") - -# diagram evaluation -include("eval.jl") - -include("build.jl") - -end \ No newline at end of file diff --git a/archived/src/expression_tree/build.jl b/archived/src/expression_tree/build.jl deleted file mode 100644 index 49a43ac7..00000000 --- a/archived/src/expression_tree/build.jl +++ /dev/null @@ -1,65 +0,0 @@ -function build(diags::Union{Diagram,Tuple,AbstractVector}, loopDim::Int, hasLoop=true; verbose::Int=0, normalize=nothing) - if isempty(diags) - return nothing - else - diags = collect(diags) - @assert eltype(diags) <: Diagram "Diagram struct expected for $diags" - return _build(diags, loopDim, hasLoop; verbose=verbose, normalize=normalize) - end -end - -function _build(diags::Vector{Diagram{W}}, loopDim::Int, hasLoop=true; verbose::Int=0, normalize=nothing) where {W} - # println(diags) - @assert all(d -> (d.id.para == diags[1].id.para), diags) "Parameters of all diagrams shoud be the same!" - - DiagTree.optimize!(diags, verbose=verbose, normalize=normalize) - - tree = newExprTree(diags[1].id.para::DiagPara{W}, loopDim, :none, hasLoop) - - # nodepool = CachedPool(:node, Node{DiagramId,W}, W) - - verbose > 0 && println("Constructing expression tree...") - nodes = Dict{Int,Any}() - for diag in diags - for d::Diagram{W} in PostOrderDFS(diag) - if haskey(nodes, d.hash) == false - id = d.id - if isempty(d.subdiagram) - K = hasLoop ? id.extK : nothing - nodes[d.hash] = addpropagator!(tree, d.name, d.factor; site=collect(id.extT), loop=K, para=id) - else - children = [nodes[sub.hash] for sub in d.subdiagram] - nodes[d.hash] = addnode!(tree, operator(d.operator), d.name, children, d.factor, para=id) - end - end - end - end - - setroot!(tree, collect([nodes[d.hash] for d in diags])) - initialize!(tree.node) - return tree -end -# function build(diag::Diagram{W}; verbose::Int=0) where {W} -# diag = build([diag,], verbose=verbose) -# return diag -# end - -function operator(op::Operator) - if op isa Sum - return ADD - elseif op isa Prod - return MUL - else - error("$op not implemented!") - end -end - -function newExprTree(para::DiagPara{W}, loopDim::Int, name::Symbol=:none, hasLoop=true) where {W} - if hasLoop - Kpool = LoopPool(:K, loopDim, para.totalLoopNum, Float64) - else - Kpool = LoopPool(:K, 0, para.totalLoopNum, Float64) - end - return ExpressionTree{W,DiagramId}(loopBasis=Kpool, name=name) - # return ExpressionTree{W,Any}(loopBasis=Kpool, name=name) -end \ No newline at end of file diff --git a/archived/src/expression_tree/common.jl b/archived/src/expression_tree/common.jl deleted file mode 100644 index cca0e00f..00000000 --- a/archived/src/expression_tree/common.jl +++ /dev/null @@ -1,61 +0,0 @@ -import ..Filter -import ..Wirreducible #remove all polarization subdiagrams -import ..Girreducible #remove all self-energy inseration -import ..NoHartree -import ..NoFock -import ..NoBubble # true to remove all bubble subdiagram -import ..Proper #ver4, ver3, and polarization diagrams may require to be irreducible along the transfer momentum/frequency - -import ..DiagramType -import ..GreenDiag -import ..SigmaDiag -import ..PolarDiag -import ..Ver3Diag -import ..Ver4Diag - -import ..Composite -import ..ChargeCharge -import ..SpinSpin -import ..UpUp -import ..UpDown -import ..Response - -import ..Instant -import ..Dynamic -import ..D_Instant -import ..D_Dynamic -import ..AnalyticProperty - -import ..symbol -import ..short - -import ..Interaction -import ..DiagPara -import ..innerTauNum - -import ..Diagram - -import ..DiagramId -import ..Ver4Id -import ..Ver3Id -import ..GreenId -import ..SigmaId -import ..PolarId -import ..BareInteractionId -import ..BareGreenId - -import ..TwoBodyChannel -import ..Alli -import ..PHr -import ..PHEr -import ..PPr -import ..AnyChan - -import ..Permutation -import ..Di -import ..Ex -import ..DiEx - -import ..uidreset -import ..toDataFrame -import ..mergeby \ No newline at end of file diff --git a/archived/src/expression_tree/eval.jl b/archived/src/expression_tree/eval.jl deleted file mode 100644 index f69caa58..00000000 --- a/archived/src/expression_tree/eval.jl +++ /dev/null @@ -1,103 +0,0 @@ -# function warn_type(diag::Diagrams, loopVar, siteVar, evalPropagator, evalNodeFactor = nothing, root = diag.root) -# @code_warntype evalNaive!(diag, loopVar, siteVar, evalPropagator, evalNodeFactor, root) -# end - -function evalKT!(diag::ExpressionTree, additional=nothing; K=nothing, T=nothing, eval=DiagTree.eval) - evalKT!(diag, K, T, additional; eval=eval) -end - -function evalNaive!(diag::ExpressionTree, loopVar, siteVar, additional=nothing; eval=DiagTree.eval) - evalKT!(diag, loopVar, siteVar, additional; eval=eval) -end - -@inbounds function evalKT!(diag::ExpressionTree, loopVar, siteVar, additional=nothing; eval=DiagTree.eval) - loopPool = diag.loopBasis - tree = diag.node - tweight = tree.current - - # calculate new loop - if hasloop(loopPool) && (isnothing(loopVar) == false) - update(loopPool, loopVar) - end - - #calculate diagram tree - @inbounds for (ni, node) in enumerate(tree.object) - # for (ni, node) in enumerate(tree.object) - children = node.children - idpara = node.para - # println(node.children, " , ", node.para) - # if isempty(children) - if node.isleaf - # if node.para isa PropagatorId - if hasloop(loopPool) && (isnothing(siteVar) == false) - if isnothing(additional) - @inbounds tweight[ni] = eval(idpara, current(loopPool, node.loopidx), node.siteidx, siteVar) - # if idpara isa BareGreenId - # @inbounds tweight[ni] = eval(idpara::BareGreenId, current(loopPool, node.loopidx), node.siteidx, siteVar) - # elseif idpara isa BareInteractionId - # @inbounds tweight[ni] = eval(idpara::BareInteractionId, current(loopPool, node.loopidx), node.siteidx, siteVar) - # else - # error("not implemented") - # end - else - @inbounds tweight[ni] = eval(idpara, current(loopPool, node.loopidx), node.siteidx, siteVar, additional) - end - elseif hasloop(loopPool) - if isnothing(additional) - @inbounds tweight[ni] = eval(idpara, node.siteidx, siteVar) - else - @inbounds tweight[ni] = eval(idpara, node.siteidx, siteVar, additional) - end - elseif isnothing(siteVar) == false - if isnothing(additional) - @inbounds tweight[ni] = eval(idpara, current(loopPool, node.loopidx)) - else - @inbounds tweight[ni] = eval(idpara, current(loopPool, node.loopidx), additional) - end - else - if isnothing(additional) - @inbounds tweight[ni] = eval(idpara) - else - @inbounds tweight[ni] = eval(idpara, additional) - end - end - @inbounds tweight[ni] *= node.factor - else - if node.operation == MUL - # @inbounds tweight[ni] = node.factor - # @inbounds for nidx in children - # @inbounds tweight[ni] *= tweight[nidx] - # end - - # f = node.factor - # @inbounds for nidx in children - # @inbounds f *= tweight[nidx] - # end - # tweight[ni] = f - - @inbounds tweight[ni] = reduce(*, tweight[nidx] for nidx in children) * node.factor - - elseif node.operation == ADD - # @inbounds tweight[ni] = 0.0 - # for nidx in children - # @inbounds tweight[ni] += tweight[nidx] - # end - # @inbounds tweight[ni] *= node.factor - - # f = 0.0 - # @inbounds for nidx in children - # @inbounds f += tweight[nidx] - # end - # @inbounds tweight[ni] = f * node.factor - - # @inbounds tweight[ni] = reduce(+, tweight[ni] for ni in children) * node.factor - @inbounds tweight[ni] = sum(tweight[nidx] for nidx in children) * node.factor - else - error("not implemented!") - end - end - end -end - -# @inline function _eval(idpara, loop, siteIdx, siteVar, additional; eval) -# tweight[ni] = eval(idpara, current(loopPool, node.loopidx), node.siteidx, siteVar) \ No newline at end of file diff --git a/archived/src/expression_tree/io.jl b/archived/src/expression_tree/io.jl deleted file mode 100644 index a18d6361..00000000 --- a/archived/src/expression_tree/io.jl +++ /dev/null @@ -1,141 +0,0 @@ -function printBasisPool(diag, io=Base.stdout) - printstyled(io, "Loop Basis ($(length(diag.loopBasis)) in total)\n", color=:blue) - title = @sprintf("%5s%40s\n", "index", "loopBasis") - printstyled(io, title, color=:green) - for i = 1:length(diag.loopBasis) - b = diag.loopBasis.basis[:, i] - @printf(io, "%5i%40s\n", i, "$b") - end - println(io) -end - -function printNodes(diag, io=Base.stdout) - printstyled(io, "Node ($(length(diag.node)) in total)\n", color=:blue) - title = @sprintf("%5s%5s%40s%40s\n", "index", "name", "para", "child") - printstyled(io, title, color=:green) - for (idx, n) in enumerate(diag.node.object) - # site = isempty(p.siteBasis) ? "" : "$(p.siteBasis)" - # loop = p.loopIdx <= 0 ? "" : "$(diag.basisPool[p.loopIdx])" - # loop = p.loopIdx <= 0 ? "" : "$(p.loopIdx)" - if n isa Propagator - site = isempty(n.siteBasis) ? "" : "$(n.siteBasis)" - loop = n.loopIdx <= 0 ? "" : "$(diag.loopBasis[n.loopIdx])" - @printf(io, "%5i%5s%40s%40s%40s\n", idx, "$(n.name)", "$(n.para)", loop, site) - else - @printf(io, "%5i%5s%40s%40s\n", idx, "$(n.name)", "$(n.para)", "$(n.childNodes)") - end - end - println(io) -end - -function Base.show(io::IO, tree::ExpressionTree) - print(io, "ExprTree: $(tree.name) with root $(tree.root)") - # print(io, "$(short(v.response))#$(v.order), k$(v.extK), t$(v.extT)") -end - - -""" - showTree(diag::Diagrams, _root = diag.root[end]; verbose = 0, depth = 999) - - Visualize the diagram tree using ete3 python package - -#Arguments -- `diag`: the Diagrams struct to visualize -- `_root`: the index of the root node to visualize -- `verbose=0`: the amount of information to show -- `depth=999`: deepest level of the diagram tree to show -""" -function showTree(tree::ExpressionTree, _root::Int; verbose=0, depth=999) - - # pushfirst!(PyVector(pyimport("sys")."path"), @__DIR__) #comment this line if no need to load local python module - ete = PyCall.pyimport("ete3") - - function name_para(p) - name = (p.name == :none) ? "" : " $(p.name)" - para = isnothing(p.para) ? "" : " $(p.para)" - return name * para - end - - function factor(f) - if f β‰ˆ 1 - return "" - end - s = "$f" - if length(s) <= 4 - return s - else - return @sprintf("%6.3e", f) - end - end - - function info(node, idx) - s = "N$(idx)$(name_para(node)) = $(tree.node.current[idx])" - # s *= sprint(show, node.para) - # s *= ": " - - if node.operation == MUL - s *= " = $(factor(node.factor))x" - elseif node.operation == ADD - s *= " = $(factor(node.factor))+" - else - error("not implemented!") - end - return s - end - - - function treeview(idx::Int, level, t=nothing) - if isnothing(t) - t = ete.Tree(name=" ") - end - - if tree.node.object[idx] isa PropagatorId - p = tree.node.object[idx] #Propagator - site = isempty(p.siteBasis) ? "" : " t$(p.siteBasis)," - loop = p.loopIdx <= 0 ? "" : "k$(tree.loopBasis[p.loopIdx])" - # loop = p.loopIdx <= 0 ? "" : "$(p.loopIdx)" - nnt = t.add_child(name="P$(idx)$(name_para(p)): $loop,$site $(factor(p.factor))") - else # composite node - nt = t.add_child(name=info(tree.node.object[idx], idx)) - name_face = ete.TextFace(nt.name, fgcolor="black", fsize=10) - nt.add_face(name_face, column=0, position="branch-top") - - for child in tree.node.object[idx].children - if child != -1 - treeview(child, level + 1, nt) - else - nnt = nt.add_child(name="0") - end - end - end - - return t - end - - t = treeview(_root, 1) - - # NOTE: t.set_style does not update the original PyObject as expected, i.e., - # `t.set_style(ete.NodeStyle(bgcolor="Khaki"))` does not modify t. - # - # The low-level approach circumvents this by directly updating the original PyObject `t."img_style"` - PyCall.set!(t."img_style", "bgcolor", "Khaki") - - - ts = ete.TreeStyle() - ts.show_leaf_name = true - # ts.show_leaf_name = True - # ts.layout_fn = my_layout - ####### show tree vertically ############ - # ts.rotation = 90 #show tree vertically - - ####### show tree in an arc ############# - # ts.mode = "c" - # ts.arc_start = -180 - # ts.arc_span = 180 - # t.write(outfile="/home/kun/test.txt", format=8) - t.show(tree_style=ts) -end -# function showTree(diag::ExpressionTree, _root::Component; kwargs...) -# @assert _root.isNode "Can not visualize $_root, because it is not a Node!" -# return showTree(diag, _root.index; kwargs...) -# end \ No newline at end of file diff --git a/archived/src/expression_tree/pool.jl b/archived/src/expression_tree/pool.jl deleted file mode 100644 index c7ac55f6..00000000 --- a/archived/src/expression_tree/pool.jl +++ /dev/null @@ -1,232 +0,0 @@ -""" - struct CachedPool{O,T} - - Use this pool to host the objects that are heavy to evaluate so that one wants to cache their status. - The user should defines a compare - -# Members -- name::Symbol : name of the pool -- object::O : object -- current::T : current status -- new::T : the new status wants to assign later -- version::Int128 : the current version -- excited::Bool : if set to excited, then the current status needs to be replaced with the new status -""" -# mutable struct CachedPool{O,T} -struct CachedPool{O,T} - name::Symbol - object::Vector{O} - current::Vector{T} - new::Vector{T} - version::Vector{Int128} - excited::Vector{Bool} - - function CachedPool(name::Symbol, objType::DataType, weightType::DataType) - object = Vector{objType}(undef, 0) - current = Vector{weightType}(undef, 0) - _new = Vector{weightType}(undef, 0) - version = Vector{Int128}(undef, 0) - excited = Vector{Bool}(undef, 0) - return new{objType,weightType}(name, object, current, _new, version, excited) - end - # function CachedPool{T}(obj::Vector{O}) where {O,T} - # weight = zeros(5, length(obj)) - # return new{O,T}(obj, weight) - # end -end - -Base.length(pool::CachedPool) = length(pool.object) -Base.size(pool::CachedPool) = size(pool.object) -Base.show(io::IO, pool::CachedPool) = print(io, pool.object) -# Base.view(pool::Pool, inds...) = Base.view(pool.pool, inds...) - -#index interface for Pool -Base.getindex(pool::CachedPool, i) = pool.object[i] -Base.setindex!(pool::CachedPool, v, i) = setindex!(pool.object, v, i) -Base.firstindex(pool::CachedPool) = 1 -Base.lastindex(pool::CachedPool) = length(pool) - -# iterator interface -function Base.iterate(pool::CachedPool) - if length(pool) == 0 - return nothing - else - return (pool.object[1], 1) - end -end - -function Base.iterate(pool::CachedPool, state) - if state >= length(pool) || length(pool) == 0 - return nothing - else - return (pool.object[state+1], state + 1) - end -end - - -function append(pool::CachedPool, object) - #ExprTree should not take care of the optimization problem - # that's why we comment out the following lines - - # @assert para isa eltype(pool.pool) - # for (oi, o) in enumerate(pool.object) - # if o == object - # return oi #existing obj - # end - # end - - id = length(pool.object) + 1 - push!(pool.object, object) - - return id #new momentum -end - -function initialize!(pool::CachedPool{O,T}) where {O,T} - N = length(pool) - resize!(pool.current, N) - fill!(pool.current, zero(T)) - - resize!(pool.new, N) - fill!(pool.new, zero(T)) - - resize!(pool.version, N) - fill!(pool.version, one(T)) - - resize!(pool.excited, N) - fill!(pool.excited, zero(T)) -end - -function updateAll(pool::CachedPool, ignoreCache::Bool, eval::Function; kwargs...) - N = length(pool.object) - if ignoreCache - T = eltype(pool.current) - for (idx, o) in enumerate(pool.object) - pool.current[idx] = T(eval(obj; kwargs...)) - end - else - error("not implemented!") - # pool.version .= 1 - # pool.excited .= false - end -end - -""" - struct LoopPool{T} - - Pool of loop basis. Each loop basis corresponds to a loop variable. - A loop variable is a linear combination of N independent loops. The combination coefficients is what we call a loop basis. - For example, if a loop is a momentum K, then - - varibale_i = K_1*basis[1, i] + K_2*basis[2, i] + K_3*basis[3, i] + ... - -# Members -- name::Symbol : name of the pool -- dim::Int : dimension of a loop variable (for example, the dimension of a momentum-frequency loop variable is (d+1) where d is the spatial dimension) -- N::Int : number of independent loops (dimension of loop basis) -- basis::Matrix{T} : Matrix of (N x Nb) that stores the loop basis, where Nb is the number of loop basis (or number of loop variables). -- current::Matrix{T} : Matrix of (dim x Nb) that stores the loop variables, where Nb is the number of loop basis (or number of loop variables). -""" -mutable struct LoopPool{T} - name::Symbol - dim::Int #dimension - loopNum::Int #number of independent loops - # N::Int #number of basis - basis::Matrix{T} # loopNum x N - current::Matrix{T} # dim x loopNum - - function LoopPool(name::Symbol, dim::Int, loopNum::Int, type::DataType=Float64) - basis = Matrix{type}(undef, loopNum, 0) # Nx0 matrix - current = Matrix{type}(undef, dim, 0) # dimx0 matrix - return new{type}(name, dim, loopNum, basis, current) - end - function LoopPool(name::Symbol, dim::Int, basis::AbstractVector{Vector{T}}) where {T} - @assert isempty(basis) == false - loopNum = length(basis[1]) - N = length(basis) #number of basis - @assert all(x -> length(x) == loopNum, basis) - current = rands(T, (dim, N)) - return new{T}(name, dim, loopNum, basis, current) - end -end - -Base.length(pool::LoopPool) = size(pool.basis)[2] -Base.size(pool::LoopPool) = length(pool) -Base.show(io::IO, pool::LoopPool) = print(io, pool.basis) -# Base.view(pool::Pool, inds...) = Base.view(pool.pool, inds...) - -#index interface for Pool -Base.getindex(pool::LoopPool, i) = pool.basis[:, i] -Base.setindex!(pool::LoopPool, v, i) = setindex!(pool.basis, v, i) -Base.firstindex(pool::LoopPool) = 1 -Base.lastindex(pool::LoopPool) = length(pool) - -# iterator interface -function Base.iterate(pool::LoopPool) - if length(pool) == 0 - return nothing - else - return (pool.basis[:, 1], 1) - end -end - -function Base.iterate(pool::LoopPool, state) - if state >= length(pool) || length(pool) == 0 - return nothing - else - return (pool.basis[:, state+1], state + 1) - end -end - -function update(pool::LoopPool, variable=rand(eltype(pool.current), pool.dim, pool.loopNum)) - @assert size(variable)[1] == pool.dim - # loopNum = size(pool.basis)[1] - loopNum = pool.loopNum - - ############ naive implementation, one allocation for each call ################ - # pool.current = view(variable, :, 1:loopNum) * pool.basis - - ############# BLAS call, no allocation, but takes ~1.6ΞΌs ######################## - #varK : M x (1:loopNum) - #basis : loopNum x N - #pool.current : M x N - # M, N = size(variable)[1], size(pool.basis)[2] - # ccall(("dgemm"), Cvoid, - # (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, - # Ref{BlasInt}, Ref{Float64}, Ptr{Float64}, Ref{BlasInt}, - # Ptr{Float64}, Ref{BlasInt}, Ref{Float64}, Ptr{Float64}, - # Ref{BlasInt}), - # 'N', 'N', M, N, loopNum, 1.0, variable, M, pool.basis, loopNum, 0.0, pool.current, M) - - ############### higher level BLAS call, no allocation, takes ~0.8ΞΌs ################ - # BLAS.gemm!('N', 'N', 1.0, view(variable, :, 1:loopNum), pool.basis, 0.0, pool.current) - - ############### higher level LinearAlgebra call, no allocation, takes ~0.8ΞΌs ################ - mul!(pool.current, view(variable, :, 1:loopNum), pool.basis) #use view will use less memory than variable[:, 1:loopNum] - - # B = view(pool.basis, 1:loopNum, :) - # B = view(pool.basis, 1:loopNum, :) - # C = pool.current[:, 1:length(pool)] - # LinearAlgebra.mul!(pool.current, A, pool.basis) - # LinearAlgebra.BLAS.gemm!('N', 'N', false, variable[:, 1:loopNum], pool.basis[1:loopNum, 1:length(pool)], false, pool.current[:, 1:length(pool)]) -end - -# current(pool::LoopPool, idx) = pool.current[:, idx] -current(pool::LoopPool, idx) = view(pool.current, :, idx) - -hasloop(pool::LoopPool) = (pool.dim > 0) && (pool.loopNum > 0) - -function append(pool::LoopPool, basis::AbstractVector) - for bi in 1:length(pool) - if pool.basis[:, bi] β‰ˆ basis - # if (pool.basis[:, bi] β‰ˆ basis) || (pool.basis[:, bi] β‰ˆ -basis) - return bi - end - end - - pool.basis = hcat(pool.basis, basis) - pool.current = hcat(pool.current, rand(eltype(pool.current), pool.dim)) - # pool.size += 1 - # @assert pool.size <= size(pool.basis)[2] "Too many loop basis!. Increase maxSize when creates the LoopPool!" - # pool.basis[:, pool.size] = basis - return length(pool) -end diff --git a/archived/src/expression_tree/tree.jl b/archived/src/expression_tree/tree.jl deleted file mode 100644 index 00561561..00000000 --- a/archived/src/expression_tree/tree.jl +++ /dev/null @@ -1,197 +0,0 @@ -""" - mutable struct Node{PARA,F} - - Node Object, which is the building block of the diagram tree. Each node is a collection of CACHED proapgator objects and other child CACHED node objects - -# Members -- para::PARA : user-defined parameters, which will be used to evaluate the factor and the weight of the node (e.g., if the node represents a vertex function, then the parameter may be the momentum basis of the external legs) -- operation::Int : #1: multiply, 2: add, ... -- factor::F : additional factor of the node -- components::Vector{Vector{Int}} : Index to the cached propagators stored in certain pools. Each Vector{Int} is for one kind of propagator. -- childNodes::Vector{Int} : Indices to the cached nodes stored in certain pool. They are the child of the current node in the diagram tree. -- parent::Int : Index to the cached nodes which is the parent of the current node. -""" -struct Node{PARA,F} - name::Symbol - para::PARA - operation::Int #1: multiply, 2: add, ... - factor::F - loopidx::Int - siteidx::Vector{Int} - children::Vector{Int} - isleaf::Bool - function Node{P,F}(name::Symbol, para; loopidx=0, siteidx=[], operator=ADD, children=[], factor=1.0) where {F,P} - # @assert typeof(para) == P - return new{P,F}(name, para, operator, F(factor), loopidx, siteidx, children, isempty(children)) - end -end - -# function Base.show(io::IO, node::Node) -# print(io, "Node#$(node.name):$(node.para)") -# end - -function Base.isequal(a::Node{P}, b::Node{P}) where {P} - # only parent is allowed to be different - if (isequal(a.para, b.para) == false) || (a.operation != b.operation) || (Set(a.children) != Set(b.children)) || (a.factor β‰ˆ b.factor) == false || a.loopidx != b.loopidx || a.siteidx != b.siteidx - return false - else - return true - end -end -Base.:(==)(a::Node{P}, b::Node{P}) where {P} = Base.isequal(a, b) - -""" - mutable struct ExpressionTree{V,PARA,F,W} - - Diagram Object represents a set of Feynman diagrams in an experssion tree (forest) structure - -# Members -- name::Symbol : Name of the tree -- loopBasis::V : Tuple of pools of cached basis in a format of (BasisPool1, BasisPool2, ...) -- node::CachedPool{Node{PARA,F},W} : Pool of the nodes in the diagram tree -- root::Vector{Int} : indices of the cached nodes that are the root(s) of the diagram tree. Each element corresponds to one root. -""" -# mutable struct ExpressionTree{V,PARA,F,W} -struct ExpressionTree{V,PARA,F,W} - name::Symbol - loopBasis::V - node::CachedPool{Node{PARA,F},W} - root::Vector{Int} - function ExpressionTree{W,PARA}(; loopBasis::V, name=:none) where {V,W,PARA} - nodePool = CachedPool(:node, Node{PARA,W}, W) - return new{V,PARA,W,W}(name, loopBasis, nodePool, []) - end - function ExpressionTree(; loopBasis::V, weight::DataType, factor::DataType=weight, nodePara::DataType=Nothing, name=:none) where {V} - nodePool = CachedPool(:node, Node{nodePara,factor}, weight) - return new{V,nodePara,factor,weight}(name, loopBasis, nodePool, []) - end -end - -function setroot!(tree::ExpressionTree, root::AbstractVector) - resize!(tree.root, length(root)) - for (ri, r) in enumerate(root) - tree.root[ri] = r - end -end - -weight(tree::ExpressionTree) = tree.node.current - -Base.getindex(diag::ExpressionTree, i) = diag.node.current[diag.root[i]] -Base.firstindex(diag::ExpressionTree) = 1 -Base.lastindex(diag::ExpressionTree) = length(diag.root) - -""" - function addPropagator!(diag::ExpressionTree, name, factor = 1.0; site = [], loop = nothing, para = nothing, order::Int = 0) - - Add a propagator into the diagram tree. - -# Arguments -- diag : diagrammatic experssion tree. -- order::Int = 0 : Order of the propagator. -- name = :none : name of the propagator. -- factor = 1 : Factor of the propagator. -- site = [] : site basis (e.g, time and space coordinate) of the propagator. -- loop = nothing : loop basis (e.g, momentum and frequency) of the propagator. -- para = nothing : Additional paramenter required to evaluate the propagator. -""" -function addpropagator!(diag::ExpressionTree{V,PARA,F,W}, name, factor=1.0; site=[], loop=nothing, para=nothing, order::Int=0) where {V,PARA,F,W} - loopPool = diag.loopBasis - loopidx = 0 - if isnothing(loop) == false - @assert typeof(loop) <: AbstractVector "LoopBasis should be a Vector!" - loopidx = append(loopPool, loop) - end - # prop = Propagator{pPARA,F}(name, order, para, factor, loopidx, collect(site)) - prop = Node{PARA,F}(name, para; factor=factor, loopidx=loopidx, siteidx=collect(site)) - # pidx = append(diag.propagator, prop) - pidx = append(diag.node, prop) - # return component(pidx, false, propagatorPool[index].name) - return pidx -end - -""" - function addnode!(diag::ExpressionTree{V,PARA,F,W}, operator, name, children::Union{Tuple, AbstractVector}, factor = 1.0; para = nothing) where {V,PARA,F,W} - - Add a node into the expression tree. - -# Arguments -- diag::ExpressionTree : diagrammatic experssion tree. -- operator::Int : #1: multiply, 2: add, ... -- name : name of the node -- children : Indices to the cached nodes stored in certain pool. They are the child of the current node in the diagram tree. It should be in the format of Vector{Int}. -- factor = 1.0 : Factor of the node -- para = nothing : Additional paramenter required to evaluate the node. Set to nothing by default. -""" -function addnode!(diag::ExpressionTree{V,PARA,F,W}, operator, name, children::Union{Tuple,AbstractVector}, factor=1.0; para=nothing) where {V,PARA,F,W} - nodePool = diag.node - - for nidx in children - @assert nidx <= length(diag.node) "Failed to add node with propagator = $propagator, and child =$children. $nidx is not in nodePool." - end - - node = Node{PARA,F}(name, para; operator=operator, children=children, factor=factor) - - nidx = append(nodePool, node) - return nidx - # return component(nidx, true, :none) -end - -""" - function getNode(diag::Diagrams, nidx::Int) - - get Node in the diag with the index nidx. -""" -function getNode(diag, nidx::Int) - return diag.node.object[nidx] -end - -# function getPropagator(diag::Diagrams, pidx::Int) -# for p in diag.propagatorPool -# if p.name == poolName -# return p.object[pidx] -# end -# end -# error("$poolName propagator pool doesn't exist!") -# end - -""" - function getNodeWeight(tree, nidx::Int) - - get Node weight in the diagram experssion tree with the index nidx. -""" -function getNodeWeight(tree, nidx::Int) - return tree.node.current[nidx] -end - - -# function addpropagator!(diag, name, factor = 1.0; site = [], loop = nothing, para = nothing, order::Int = 0) -# pidx = addPropagator!(diag, name, factor; site = site, loop = loop, para = para, order = order) -# @assert pidx > 0 -# return Component(pidx, false, :propagator, diag.node.object[pidx]) -# end - -# function addnode!(diag, operator, name, components, factor = 1.0; para = nothing) -# _components = [c for c in components if c.index > 0] -# if operator == MUL -# if length(_components) < length(components) -# return zero(Component) #if some of the components doesn't exist, then product of the components doens't exist -# end -# elseif operator == ADD -# if length(_components) == 0 -# return zero(Component) #if all of the components doesn't exist, then sum of the components doens't exist -# end -# end - -# child = [] -# propagator = [] -# for c in collect(_components) -# @assert c isa Component "$c is not a DiagTree.Component" -# if c.isNode -# push!(child, c.index) -# else -# push!(propagator, c.index) -# end -# end -# nidx = addNode!(diag, operator, name, factor; propagator = propagator, child = child, para = para) -# return Component(nidx, true, diag.node.name, getNode(diag, nidx)) -# end \ No newline at end of file diff --git a/archived/src/parquet.jl b/archived/src/parquet.jl deleted file mode 100644 index 5517df5a..00000000 --- a/archived/src/parquet.jl +++ /dev/null @@ -1,112 +0,0 @@ -module Parquet -# import ..ComputationalGraphs -# import .._dtype -# import ..ComputationalGraphs -# import ComputationalGraphs._dtype: _dtype -import ..IR -import ..IR: _dtype -import ..Op - -π‘ŽβΊ(isFermi, i) = isFermi ? Op.𝑓⁺(i) : Op.𝑏⁺(i) -π‘Žβ»(isFermi, i) = isFermi ? Op.𝑓⁺(i) : Op.𝑏⁺(i) - -function _bubble(; left_label=[1, 2, 3, 4], right_label=[5, 6, 7, 8], external_indices=[1, 2, 7, 8], topology=Vector{Vector{Int}}([]), isFermi=true, factor=_dtype.factor(1)) - # default topology type should be given, otherwise feynman_diagram report error - if isFermi - a⁺, a⁻ = Op.𝑓⁺, Op.𝑓⁻ - ea⁺, ea⁻ = Op.𝑓⁺ₑ, Op.𝑓⁻ₑ - else - a⁺, a⁻ = Op.𝑏⁺, Op.𝑏⁻ - ea⁺, ea⁻ = Op.𝑏⁺ₑ, Op.𝑏⁻ₑ - end - l1, l2, l3, l4 = left_label - r1, r2, r3, r4 = right_label - # e1, e2, e3, e4 = external - - lver = a⁺(l1) * a⁺(l2) * a⁻(l3) * a⁻(l4) - rver = a⁺(r1) * a⁺(r2) * a⁻(r3) * a⁻(r4) - - g = IR.feynman_diagram([ea⁺(1), ea⁺(2), ea⁻(3), ea⁻(4), lver, rver], topology, external_indices=external_indices, factor=factor) - IR.standardize_order!(g) - return g -end - -""" - function particle_hole_bubble(left_label=[5, 6, 7, 8], right_label=[9, 10, 11, 12], isFermi=true) - -Create a particle-hole bubble diagram. - -3 4 -^ ^ -| | -7---8--->----9---12 -| | | | -| | | | -5---6---<----11--10 -| | -^ ^ -1 2 -""" -function particle_hole_bubble(left_label=[5, 6, 7, 8], right_label=[9, 10, 11, 12], isFermi=true) - l1, l2, l3, l4 = left_label - r1, r2, r3, r4 = right_label - external_indices = [l1, r2, l3, r4] # (5, 10| 7, 12) - topology = [[1, 5], [2, 10], [7, 3], [12, 4], [8, 9], [11, 6]] - factor = _dtype.factor(1) - return _bubble(left_label=left_label, right_label=right_label, external_indices=external_indices, topology=topology, isFermi=isFermi, factor=factor) -end - -""" - function particle_hole_exchange_bubble(left_label=[5, 6, 7, 8], right_label=[9, 10, 11, 12], isFermi=true) - -Create a particle-hole-exchange bubble diagram. It is the same as the particle-hole bubble diagram except that the external ghost operators are exchanged (3, 4) <-> (4, 3) - -4 3 -^ ^ -| | -7---8--->----9---12 -| | | | -| | | | -5---6---<----11--10 -| | -^ ^ -1 2 -""" -function particle_hole_exchange_bubble(left_label=[5, 6, 7, 8], right_label=[9, 10, 11, 12], isFermi=true) - l1, l2, l3, l4 = left_label - r1, r2, r3, r4 = right_label - external_indices = [l1, r2, l3, r4] # (5, 10| 7, 12) - topology = [[1, 5], [2, 10], [12, 3], [7, 4], [8, 9], [11, 6]] - factor = _dtype.factor(1) - return _bubble(left_label=left_label, right_label=right_label, external_indices=external_indices, topology=topology, isFermi=isFermi, factor=factor) -end - -""" - function particle_particle_bubble(left_label=[5, 6, 7, 8], right_label=[9, 10, 11, 12], isFermi=true) - -Create a particle-particle bubble diagram. One of the internal propagator (8->9) is the same as the particle-hole and particle-hole-exchange bubble diagram. The external ghost operators are exchanged (3, 4) <-> (4, 3) compared to the particle-hole bubble diagram. - -4 3 -^ ^ -12---11 -| | -10----9 -| | -^ ^ -| | -7-----8 -| | -5-----6 -^ ^ -1 2 -""" -function particle_particle_bubble(left_label=[5, 6, 7, 8], right_label=[9, 10, 11, 12], isFermi=true) - l1, l2, l3, l4 = left_label - r1, r2, r3, r4 = right_label - external_indices = [l1, l2, r3, r4] # (5, 10| 7, 12) - topology = [[1, 5], [2, 6], [11, 3], [12, 4], [7, 10], [8, 9]] - factor = _dtype.factor(1) / 2 - return _bubble(left_label=left_label, right_label=right_label, external_indices=external_indices, topology=topology, isFermi=isFermi, factor=factor) -end - -end \ No newline at end of file diff --git a/archived/src/parquet_builder/benchmark/benchmark.jl b/archived/src/parquet_builder/benchmark/benchmark.jl deleted file mode 100644 index 5aa5cdbc..00000000 --- a/archived/src/parquet_builder/benchmark/benchmark.jl +++ /dev/null @@ -1,24 +0,0 @@ -module Benchmark -using StaticArrays, PyCall -using AbstractTrees -using Parameters, Combinatorics - -import ..DiagPara -import ..interactionTauNum - -const DI, EX = 1, 2 -const INL, OUTL, INR, OUTR = 1, 2, 3, 4 -# orginal diagrams T, U, S; particle-hole counterterm Ts, Us; and their counterterm Tc, Uc, Sc, Tsc, Usc -const I, T, U, S, Ts, Us, Ic, Tc, Uc, Sc, Tsc, Usc = 1:12 -# const ChanName = ["I", "T", "U", "S", "Ts", "Us", "Ic", "Tc", "Uc", "Sc", "Tsc", "Usc"] -const SymFactor = [1.0, -1.0, 1.0, -0.5, +1.0, -1.0] - -# const Fchan = [I, U, S, Ts, Us, Ic, Uc, Sc, Tsc, Usc] -# const Vchan = [I, T, U, Ts, Us, Ic, Tc, Uc, Sc, Tsc, Usc] -# const Allchan = [I, T, U, S, Ts, Us, Ic, Tc, Uc, Sc, Tsc, Usc] - -include("vertex4.jl") -include("vertex4_eval.jl") -include("vertex4_io.jl") -include("diagram_count.jl") -end \ No newline at end of file diff --git a/archived/src/parquet_builder/benchmark/diagram_count.jl b/archived/src/parquet_builder/benchmark/diagram_count.jl deleted file mode 100644 index 2153c054..00000000 --- a/archived/src/parquet_builder/benchmark/diagram_count.jl +++ /dev/null @@ -1,124 +0,0 @@ -""" Count diagram numbers -see Ref. https://arxiv.org/pdf/cond-mat/0512342.pdf for details -We assume: -1. interaction is spin-symmetric. -2. the propagator conserves the spin. -""" - -function count_ver3_g2v(innerLoopNum, spin) - @assert innerLoopNum >= 0 - if innerLoopNum == 0 - return 1 - elseif innerLoopNum == 1 - return 1 - elseif innerLoopNum == 2 - return 3 * (2 + spin) - elseif innerLoopNum == 3 - return 5 * (10 + 9 * spin + spin^2) - else - error("not implemented!") - end -end - -function count_ver3_G2v(innerLoopNum, spin) - @assert innerLoopNum >= 0 - if innerLoopNum == 0 - return 1 - elseif innerLoopNum == 1 - return 1 - elseif innerLoopNum == 2 - return 4 + 3 * spin - elseif innerLoopNum == 3 - return 27 + 31 * spin + 5 * spin^2 - else - error("not implemented!") - end -end - -function count_ver3_G2W(innerLoopNum, spin) - @assert innerLoopNum >= 0 - if innerLoopNum == 0 - return 1 - elseif innerLoopNum == 1 - return 1 - elseif innerLoopNum == 2 - return 4 + 2 * spin - elseif innerLoopNum == 3 - return 27 + 22 * spin - else - error("not implemented!") - end -end - -function count_sigma_G2v(innerLoopNum, spin) - @assert innerLoopNum >= 1 - if innerLoopNum == 1 - return 1 - elseif innerLoopNum == 2 - return 1 + spin - elseif innerLoopNum == 3 - return 4 + 5 * spin + spin^2 - elseif innerLoopNum == 4 - return 27 + 40 * spin + 14 * spin^2 + spin^3 - else - error("not implemented!") - end -end - -function count_sigma_G2W(innerLoopNum, spin) - @assert innerLoopNum >= 1 - return count_ver3_G2W(innerLoopNum, spin) -end - -function count_polar_G2v(innerLoopNum, spin) - @assert innerLoopNum >= 1 - return spin * count_ver3_G2v(innerLoopNum - 1, spin) -end - -function count_polar_G2W(innerLoopNum, spin) - return spin * count_ver3_G2W(innerLoopNum - 1, spin) -end - -function count_polar_g2v_noFock_upup(innerLoopNum, spin) - #polarization for - @assert innerLoopNum >= 1 - @assert spin == 2 "only spin=2 has been implemented!" - if innerLoopNum == 1 - return 2 - elseif innerLoopNum == 2 - return 2 - elseif innerLoopNum == 3 - return 28 - elseif innerLoopNum == 4 - return 274 - elseif innerLoopNum == 5 - return 3586 - else - error("not implemented!") - end -end - -function count_polar_g2v_noFock_updown(innerLoopNum, spin) - #polarization for - @assert innerLoopNum >= 1 - @assert spin == 2 "only spin=2 has been implemented!" - if innerLoopNum == 1 - return 0 - elseif innerLoopNum == 2 - return 0 - elseif innerLoopNum == 3 - return 4 - elseif innerLoopNum == 4 - return 52 - elseif innerLoopNum == 5 - return 844 - else - error("not implemented!") - end -end - -function count_polar_g2v_noFock(innerLoopNum, spin) - return count_polar_g2v_noFock_upup(innerLoopNum, spin) + - count_polar_g2v_noFock_updown(innerLoopNum, spin) -end - diff --git a/archived/src/parquet_builder/benchmark/vertex4.jl b/archived/src/parquet_builder/benchmark/vertex4.jl deleted file mode 100644 index 516c81ed..00000000 --- a/archived/src/parquet_builder/benchmark/vertex4.jl +++ /dev/null @@ -1,288 +0,0 @@ -mutable struct Green - Tpair::Tuple{Int,Int} - weight::Float64 - function Green(inT, outT) - return new((inT, outT), 0.0) - end - function Green(tpair::Tuple{Int,Int}) - return new(tpair, 0.0) - end -end - -# add Tpairs to Green's function (in, out) or vertex4 (inL, outL, inR, outR) -function addTidx(obj, _Tidx) - for (i, Tidx) in enumerate(obj.Tpair) - if Tidx == _Tidx - return i - end - end - push!(obj.Tpair, _Tidx) - push!(obj.weight, zero(eltype(obj.weight))) # add zero to the weight table of the object - push!(obj.child, []) - return length(obj.Tpair) -end - -""" - struct IdxMap{_Ver4} - - Map left vertex Tpair[lidx], right vertex Tpair[ridx], the shared Green's function G0 and the channel specific Green's function Gx to the top level 4-vertex Tpair[vidx] - -# Arguments -- l::_Ver4 : left vertex -- r::_Ver4 : right vertex -- v::_Ver4 : composte vertex -- lidx::Int : left sub-vertex index -- ridx::Int : right sub-vertex index -- vidx::Int : composite vertex index -- G0::Green : shared Green's function index -- Gx::Green : channel specific Green's function index -""" -mutable struct IdxMap{_Ver4} - l::_Ver4 #left vertex - r::_Ver4 #right vertex - v::_Ver4 #composte vertex - lidx::Int # left sub-vertex index - ridx::Int # right sub-vertex index - vidx::Int # composite vertex index - G0::Green # shared Green's function index - Gx::Green # channel specific Green's function index - node::Any # useful for constructing DiagTree - function IdxMap(l::V, r::V, v::V, lidx, ridx, vidx, G0::Green, Gx::Green) where {V} - return new{V}(l, r, v, lidx, ridx, vidx, G0, Gx, nothing) - end -end - -struct Bubble{_Ver4} # template Bubble to avoid mutually recursive struct - id::Int - chan::Int - Lver::_Ver4 - Rver::_Ver4 - map::Vector{IdxMap{_Ver4}} - - function Bubble(ver4::_Ver4, chan::Int, oL::Int, level::Int, _id::Vector{Int}) where {_Ver4} - # @assert chan in para.chan "$chan isn't a bubble channels!" - @assert oL < ver4.loopNum "LVer loopNum must be smaller than the ver4 loopNum" - - idbub = _id[1] # id vector will be updated later, so store the current id as the bubble id - _id[1] += 1 - - oR = ver4.loopNum - 1 - oL # loopNum of the right vertex - lLpidxOffset = ver4.loopidxOffset + 1 - rLpidxOffset = lLpidxOffset + oL - LTidx = ver4.TidxOffset # the first Ο„ index of the left vertex - TauNum = interactionTauNum(ver4.para) # maximum tau number for each bare interaction - RTidx = LTidx + (oL + 1) * TauNum # the first Ο„ index of the right sub-vertex - - if chan == T || chan == U - LverChan = (level == 1) ? ver4.Fouter : ver4.F - RverChan = (level == 1) ? ver4.Allouter : ver4.All - elseif chan == S - LverChan = (level == 1) ? ver4.Vouter : ver4.V - RverChan = (level == 1) ? ver4.Allouter : ver4.All - else - error("chan $chan isn't implemented!") - end - - # println("left ver chan: ", LsubVer, ", loop=", oL) - # W = eltype(ver4.weight) - Lver = _Ver4(ver4.para, LverChan, ver4.F, ver4.V, ver4.All; - loopNum=oL, loopidxOffset=lLpidxOffset, tidxOffset=LTidx, - level=level + 1, id=_id) - - Rver = _Ver4(ver4.para, RverChan, ver4.F, ver4.V, ver4.All; - loopNum=oR, loopidxOffset=rLpidxOffset, tidxOffset=RTidx, - level=level + 1, id=_id) - - @assert Lver.TidxOffset == ver4.TidxOffset "Lver Tidx must be equal to vertex4 Tidx! LoopNum: $(ver4.loopNum), LverLoopNum: $(Lver.loopNum), chan: $chan" - - ############## construct IdxMap ######################################## - map = [] - for (lt, LvT) in enumerate(Lver.Tpair) - for (rt, RvT) in enumerate(Rver.Tpair) - VerTidx = 0 - - if chan == T - VerT = (LvT[INL], LvT[OUTL], RvT[INR], RvT[OUTR]) - GTx = (RvT[OUTL], LvT[INR]) - elseif chan == U - VerT = (LvT[INL], RvT[OUTR], RvT[INR], LvT[OUTL]) - GTx = (RvT[OUTL], LvT[INR]) - elseif chan == S - VerT = (LvT[INL], RvT[OUTL], LvT[INR], RvT[OUTR]) - GTx = (LvT[OUTL], RvT[INR]) - else - throw("This channel is invalid!") - end - - Gx = Green(GTx) - push!(ver4.G[Int(chan)], Gx) - - GT0 = (LvT[OUTR], RvT[INL]) - G0 = Green(GT0) - push!(ver4.G[1], G0) - - VerTidx = addTidx(ver4, VerT) - for tpair in ver4.Tpair - @assert tpair[1] == ver4.TidxOffset "InL Tidx must be the same for all Tpairs in the vertex4" - end - - ###### test if the internal + exteranl variables is equal to the total 8 variables of the left and right sub-vertices ############ - Total1 = vcat(collect(LvT), collect(RvT)) - Total2 = vcat(collect(GT0), collect(GTx), collect(VerT)) - # println(Total1) - # println(Total2) - @assert compare(Total1, Total2) "chan $(chan): G0=$GT0, Gx=$GTx, external=$VerT don't match with Lver4 $LvT and Rver4 $RvT" - - idxmap = IdxMap(Lver, Rver, ver4, lt, rt, VerTidx, G0, Gx) - push!(map, idxmap) - push!(ver4.child[VerTidx], idxmap) - end - end - return new{_Ver4}(idbub, chan, Lver, Rver, map) - end -end - -""" - function Ver4{W}(para::Para, loopNum = para.internalLoopNum, tidx = 1; chan = para.chan, F = para.F, V = para.V, level = 1, id = [1,]) where {W} - - Generate 4-vertex diagrams using Parquet Algorithm - -#Arguments -- `para`: parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `chan`: list of channels of the current 4-vertex. -- `F` : channels of left sub-vertex for the particle-hole and particle-hole-exchange bubbles -- `V` : channels of left sub-vertex for the particle-particle bubble -- `All` : channels of right sub-vertex of all channels -- `Fouter` : channels of left sub-vertex for the particle-hole and particle-hole-exchange bubbles, only take effect for the outermost bubble -- `Vouter` : channels of left sub-vertex for the particle-particle bubble, only take effect for the outermost bubble -- `Allouter` : channels of right sub-vertex of all channels -- `loopNum`: momentum loop degrees of freedom of the 4-vertex diagrams -- `tidx`: the first Ο„ variable index. It will be the Ο„ variable of the left incoming electron for all 4-vertex diagrams -- `level`: level in the diagram tree -- `id`: the first element will be used as the id of the Ver4. All nodes in the tree will be labeled in preorder depth-first search - -#Remark: -- AbstractTrees interface is implemented for Ver4. So one can use the API in https://juliacollections.github.io/AbstractTrees.jl/stable/ to manipulate/print the tree structre of Ver4. -- There are three different methods to print/visualize the tree structre: -1) `print_tree(ver4::Ver4)` or `print_tree(bub::Bubble)` to print the tree to terminal. This function is provided by AbstractTrees API. -2) `newick(ver4::Ver4)` or `newick(bub::Bubble)` to serilize the tree to a newick format string. You may save the string to a text file, then visualize it with a newick format visualizer application. -3) `showTree(ver4::Ver4)` to visualize the tree using the python package ete3. You have to install ete3 properly to use this function. -""" -struct Ver4{W} - para::Any - chan::Vector{Int} # list of channels - F::Vector{Int} - V::Vector{Int} - All::Vector{Int} - Fouter::Vector{Int} - Vouter::Vector{Int} - Allouter::Vector{Int} - - ###### vertex topology information ##################### - id::Int - level::Int - - ####### vertex properties ########################### - loopNum::Int - loopidxOffset::Int # offset of the loop index from the first internal loop - TidxOffset::Int # offset of the Tidx from the tau index of the left most incoming leg - - ###### components of vertex ########################## - G::SVector{16,Vector{Green}} # large enough to host all Green's function - bubble::Vector{Bubble{Ver4{W}}} - - ####### weight and tau table of the vertex ############### - Tpair::Vector{Tuple{Int,Int,Int,Int}} - child::Vector{Vector{IdxMap{Ver4{W}}}} - weight::Vector{W} - - function Ver4{W}(para, chan, F=[I, U, S], V=[I, T, U], All=union(F, V); - loopNum=para.innerLoopNum, loopidxOffset=0, tidxOffset=0, - Fouter=F, Vouter=V, Allouter=All, - level=1, id=[1,] - ) where {W} - - @assert para.totalTauNum >= (loopNum + 1) * interactionTauNum(para) "$para" - - if level > 1 - @assert Set(F) == Set(Fouter) - @assert Set(V) == Set(Vouter) - @assert Set(All) == Set(Allouter) - end - - @assert (T in F) == false "F vertex is particle-hole irreducible, so that T channel is not allowed in F" - @assert (S in V) == false "V vertex is particle-particle irreducible, so that S channel is not allowed in V" - @assert (T in Fouter) == false "F vertex is particle-hole irreducible, so that T channel is not allowed in F" - @assert (S in Vouter) == false "V vertex is particle-particle irreducible, so that S channel is not allowed in V" - - g = @SVector [Vector{Green}([]) for i = 1:16] - ver4 = new{W}(para, chan, F, V, All, Fouter, Vouter, Allouter, id[1], level, loopNum, loopidxOffset, tidxOffset, g, [], [], [[],], []) - id[1] += 1 - @assert loopNum >= 0 - - - if loopNum == 0 - tidx = tidxOffset - # bare interaction may have one, two or four independent tau variables - if interactionTauNum(para) == 1 # instantaneous interaction - addTidx(ver4, (tidx, tidx, tidx, tidx)) #direct instant intearction - addTidx(ver4, (tidx, tidx, tidx, tidx)) #exchange instant interaction - end - if interactionTauNum(para) == 2 # interaction with incoming and outing Ο„ varibales - addTidx(ver4, (tidx, tidx, tidx, tidx)) # direct and exchange instant interaction - addTidx(ver4, (tidx, tidx, tidx + 1, tidx + 1)) # direct dynamic interaction - addTidx(ver4, (tidx, tidx + 1, tidx + 1, tidx)) # exchange dynamic interaction - end - if interactionTauNum(para) == 4 # interaction with incoming and outing Ο„ varibales - error("Not implemented!") - # addTidx(ver4, (tidx, tidx + 1, tidx + 2, tidx + 3)) # direct dynamic interaction - # addTidx(ver4, (tidx, tidx + 3, tidx + 2, tidx + 1)) # exchange dynamic interaction - end - else # loopNum>0 - for c in chan - for ol = 0:loopNum-1 - bubble = Bubble(ver4, c, ol, level, id) - if length(bubble.map) > 0 # if zero, bubble diagram doesn't exist - push!(ver4.bubble, bubble) - end - end - end - # TODO: add envolpe diagrams - # for c in II - # end - test(ver4) # more test - end - return ver4 - end -end - -function compare(A, B) - # check if the elements of XY are the same as Z - XY, Z = copy(A), copy(B) - for e in XY - if (e in Z) == false - return false - end - Z = (idx = findfirst(x -> x == e, Z)) > 0 ? deleteat!(Z, idx) : Z - end - return length(Z) == 0 -end - -function test(ver4) - if length(ver4.bubble) == 0 - return - end - - G = ver4.G - for bub in ver4.bubble - Lver, Rver = bub.Lver, bub.Rver - @assert Rver.loopidxOffset + Rver.loopNum == ver4.loopidxOffset + ver4.loopNum "Rver loopidx offset = $(Rver.loopidxOffset) + loopNum = $(Rver.loopNum) is not equal to ver4 loopidx offset = $(ver4.loopidxOffset) + loopNum = $(ver4.loopNum)" - @assert Lver.loopNum + Rver.loopNum + 1 == ver4.loopNum - for map in bub.map - LverT, RverT = collect(Lver.Tpair[map.lidx]), collect(Rver.Tpair[map.ridx]) # 8 Ο„ variables relevant for this bubble - G1T, GxT = collect(map.G0.Tpair), collect(map.Gx.Tpair) # 4 internal variables - ExtT = collect(ver4.Tpair[map.vidx]) # 4 external variables - @assert compare(vcat(G1T, GxT, ExtT), vcat(LverT, RverT)) "chan $(bub.chan): G1=$G1T, Gx=$GxT, external=$ExtT don't match with Lver4 $LverT and Rver4 $RverT" - end - end -end \ No newline at end of file diff --git a/archived/src/parquet_builder/benchmark/vertex4_eval.jl b/archived/src/parquet_builder/benchmark/vertex4_eval.jl deleted file mode 100644 index c0171f80..00000000 --- a/archived/src/parquet_builder/benchmark/vertex4_eval.jl +++ /dev/null @@ -1,142 +0,0 @@ -mutable struct Weight <: FieldVector{2,Float64} - d::Float64 - e::Float64 - Weight() = new(0.0, 0.0) - Weight(d, e) = new(d, e) -end - -const Base.zero(::Type{Weight}) = Weight(0.0, 0.0) -const Base.abs(w::Weight) = abs(w.d) + abs(w.e) # define abs(Weight) - -function evalAllG!(G, K, T0idx, varT, evalG; kwargs...) - for g in G - tin, tout = g.Tpair - g.weight = evalG(K, varT[T0idx+tin], varT[T0idx+tout], kwargs...) - end -end - -# function phase(varT, Tpair, isF) -# tInL, tOutL, tInR, tOutR = varT[Tpair[INL]], varT[Tpair[OUTL]], varT[Tpair[INR]], -# varT[Tpair[OUTR]] -# if (isF) -# return cos(Ο€ / Ξ² * ((tInL + tOutL) - (tInR + tOutR))) -# else -# return cos(Ο€ / Ξ² * ((tInL - tOutL) + (tInR - tOutR))) -# end -# end - -function eval(para, ver4::Ver4, varK, varT, legK, evalG::Function, evalV::Function, fast=false; kwargs...) - KinL, KoutL, KinR, KoutR = legK - spin = para.spin - T0idx = para.firstTauIdx - Kidx = para.firstLoopIdx + ver4.loopidxOffset - - if ver4.loopNum == 0 - qd = KinL - KoutL - qe = KinL - KoutR - if interactionTauNum(para) == 1 - sign = para.isFermi ? -1 : 1 - ver4.weight[1].d = -evalV(qd) - ver4.weight[1].e = (-evalV(qe)) * sign - else - Tidx = para.firstTauIdx + ver4.TidxOffset - Ο„In, Ο„Out = varT[Tidx], varT[Tidx+1] - error("not implemented!") - # elseif ver4.interactionTauNum == 2 - # vd, wd, ve, we = vertexDynamic(para, qd, qe, Ο„In, Ο„Out) - - # ver4.weight[1].d = vd - # ver4.weight[1].e = ve - # ver4.weight[2].d = wd - # ver4.weight[2].e = 0.0 - # ver4.weight[3].d = 0.0 - # ver4.weight[3].e = we - end - return - end - - # LoopNum>=1 - for w in ver4.weight - w.d, w.e = 0.0, 0.0 # initialize all weights - end - G = ver4.G - K = varK[:, Kidx] - - evalAllG!(G[1], K, T0idx, varT, evalG, kwargs...) - - # PhaseFactor = 1.0 / (2Ο€)^para.loopDim - PhaseFactor = 1.0 - Kt, Ku, Ks = similar(K), similar(K), similar(K) #Kt, Ku and Ks will be re-created later, slow in performance - - for c in ver4.chan - if c == T - @. Kt = KoutL + K - KinL - evalAllG!(G[Int(c)], Kt, T0idx, varT, evalG, kwargs...) - # println("initializating", G[Int(c)]) - elseif c == U - # can not be in box! - @. Ku = KoutR + K - KinL - evalAllG!(G[Int(c)], Ku, T0idx, varT, evalG, kwargs...) - elseif c == S - # S channel, and cann't be in box! - @. Ks = KinL + KinR - K - evalAllG!(G[Int(c)], Ks, T0idx, varT, evalG, kwargs...) - else - error("not impossible!") - end - end - for b in ver4.bubble - c = b.chan - Factor = SymFactor[Int(c)] * PhaseFactor - if para.isFermi == false - Factor = abs(Factor) - end - - if c == T - eval(para, b.Lver, varK, varT, [KinL, KoutL, Kt, K], evalG, evalV; kwargs...) - eval(para, b.Rver, varK, varT, [K, Kt, KinR, KoutR], evalG, evalV; kwargs...) - elseif c == U - eval(para, b.Lver, varK, varT, [KinL, KoutR, Ku, K], evalG, evalV; kwargs...) - eval(para, b.Rver, varK, varT, [K, Ku, KinR, KoutL], evalG, evalV; kwargs...) - elseif c == S - # S channel - eval(para, b.Lver, varK, varT, [KinL, Ks, KinR, K], evalG, evalV; kwargs...) - eval(para, b.Rver, varK, varT, [K, KoutL, Ks, KoutR], evalG, evalV; kwargs...) - else - error("not implemented") - end - - rN = length(b.Rver.weight) - gWeight = 0.0 - for (l, Lw) in enumerate(b.Lver.weight) - for (r, Rw) in enumerate(b.Rver.weight) - map = b.map[(l-1)*rN+r] - - gWeight = map.G0.weight * map.Gx.weight * Factor - - if fast && ver4.level == 1 - # gWeight *= phase(varT, ver4.Tpair[map.ver]) - w = ver4.weight[1] - else - w = ver4.weight[map.vidx] - end - - if c == T - w.d += gWeight * (Lw.d * Rw.d * spin + Lw.d * Rw.e + Lw.e * Rw.d) - w.e += gWeight * Lw.e * Rw.e - elseif c == U - w.d += gWeight * Lw.e * Rw.e - w.e += gWeight * (Lw.d * Rw.d * spin + Lw.d * Rw.e + Lw.e * Rw.d) - elseif c == S - # S channel, see the note "code convention" - w.d += gWeight * (Lw.d * Rw.e + Lw.e * Rw.d) - w.e += gWeight * (Lw.d * Rw.d + Lw.e * Rw.e) - else - error("not implemented") - end - - end - end - - end -end \ No newline at end of file diff --git a/archived/src/parquet_builder/benchmark/vertex4_io.jl b/archived/src/parquet_builder/benchmark/vertex4_io.jl deleted file mode 100644 index c09d2d24..00000000 --- a/archived/src/parquet_builder/benchmark/vertex4_io.jl +++ /dev/null @@ -1,224 +0,0 @@ -################## implement AbstractTrees interface ####################### -# refer to https://github.com/JuliaCollections/AbstractTrees.jl for more details -function AbstractTrees.children(ver4::Ver4) - return ver4.bubble -end - -function AbstractTrees.children(bubble::Bubble) - return (bubble.Lver, bubble.Rver) -end - -function iterate(ver4::Ver4{W}) where {W} - if length(ver4.bubble) == 0 - return nothing - else - return (ver4.bubble[1], 1) - end -end - -function iterate(bub::Bubble) - return (bub.Lver, false) -end - -function iterate(ver4::Ver4{W}, state) where {W} - if state >= length(ver4.bubble) || length(ver4.bubble) == 0 - return nothing - else - return (ver4.bubble[state+1], state + 1) - end -end - -function iterate(bub::Bubble, state::Bool) - state && return nothing - return (bub.Rver, true) -end - -Base.IteratorSize(::Type{Ver4{W}}) where {W} = Base.SizeUnknown() -Base.eltype(::Type{Ver4{W}}) where {W} = Ver4{W} - -Base.IteratorSize(::Type{Bubble{Ver4{W}}}) where {W} = Base.SizeUnknown() -Base.eltype(::Type{Bubble{Ver4{W}}}) where {W} = Bubble{Ver4{W}} - -AbstractTrees.printnode(io::IO, ver4::Ver4) = print(io, tpair(ver4)) -AbstractTrees.printnode(io::IO, bub::Bubble) = print(io, - "\u001b[32m$(bub.id): $(bub.chan) $(bub.Lver.para.innerLoopNum)Ⓧ $(bub.Rver.para.innerLoopNum)\u001b[0m") - -function tpair(ver4, MaxT = 18) - s = "\u001b[31m$(ver4.id):\u001b[0m" - if ver4.para.innerLoopNum > 0 - s *= "$(ver4.para.innerLoopNum)lp, T$(length(ver4.Tpair))⨁ " - else - s *= "⨁ " - end - # if ver4.loopNum <= 1 - for (ti, T) in enumerate(ver4.Tpair) - if ti <= MaxT - s *= "($(T[1]),$(T[2]),$(T[3]),$(T[4]))" - else - s *= "..." - break - end - end - # end - return s -end - -##### pretty print of Bubble and Ver4 ########################## -Base.show(io::IO, bub::Bubble) = AbstractTrees.printnode(io::IO, bub) -Base.show(io::IO, ver4::Ver4) = AbstractTrees.printnode(io::IO, ver4) - - -""" -convert Ver4 tree struct to a string in the newick format -""" -function newick(ver4::Ver4) - return "$(newickVer4(ver4));" -end - -""" -convert Bubble tree struct to a string in the newick format -""" -function newick(bub::Bubble) - return "$(newickBuble(bub));" -end - -function newickBubble(bub::Bubble) - # Recursive version - # Practically a postorder tree traversal - left = newickVer4(bub.Lver) - right = newickVer4(bub.Rver) - return "($left,$right)$(bub.id)_$(ChanName[bub.chan])_$(bub.Lver.para.innerLoopNum)Ⓧ$(bub.Rver.para.innerLoopNum)" -end - - -function newickVer4(ver4::Ver4) - # Recursive version - # Practically a postorder tree traversal - - function tpairNewick(ver4) - if ver4.para.innerLoopNum > 0 - s = "$(ver4.id):lp$(ver4.para.innerLoopNum)_T$(length(ver4.Tpair))⨁" - else - s = "$(Ver4.id):⨁" - end - # if ver4.loopNum <= 1 - for (ti, T) in enumerate(ver4.Tpair) - if ti <= 5 - s *= "⟨$(T[1])-$(T[2])-$(T[3])-$(T[4])⟩" - else - s *= "…" - break - end - end - # end - return s - end - - if ver4.para.innerLoopNum == 0 - return tpairNewick(ver4) - else - s = "(" - for (bi, bub) in enumerate(ver4.bubble) - s *= newickBubble(bub) - if bi != length(ver4.bubble) - s *= "," - else - s *= ")" - end - end - return s * tpairNewick(ver4) - end -end - -""" - showTree(ver4, para::Para; verbose=0, depth=999) - - Visualize the diagram tree using ete3 python package - -#Arguments -- `ver4`: the 4-vertex diagram tree to visualize -- `para`: parameters -- `verbose=0`: the amount of information to show -- `depth=999`: deepest level of the diagram tree to show -""" -function showTree(ver4; verbose = 0, depth = 999) - - # pushfirst!(PyVector(pyimport("sys")."path"), @__DIR__) #comment this line if no need to load local python module - ete = pyimport("ete3") - - function tpairETE(ver4, depth) - s = "$(ver4.id):" - if ver4.para.innerLoopNum > 0 - s *= "$(ver4.para.innerLoopNum)lp, T$(length(ver4.Tpair))⨁ " - else - s *= "⨁ " - end - if ver4.para.innerLoopNum == 0 || ver4.level > depth - MaxT = Inf - else - MaxT = 1 - end - - # if ver4.loopNum <= 1 - for (ti, T) in enumerate(ver4.Tpair) - if ti <= MaxT - s *= "($(T[1]),$(T[2]),$(T[3]),$(T[4]))" - else - s *= "..." - break - end - end - # end - return s - end - - - function treeview(ver4, t = nothing) - if isnothing(t) - t = ete.Tree(name = " ") - end - - if ver4.para.innerLoopNum == 0 || ver4.level > depth - nt = t.add_child(name = tpairETE(ver4, depth)) - return t - else - # prefix = "$(ver4.id): $(ver4.loopNum) lp, $(length(ver4.Tpair)) elem" - # nt = t.add_child(name=prefix * ", ⨁") - nt = t.add_child(name = tpairETE(ver4, depth)) - name_face = ete.TextFace(nt.name, fgcolor = "black", fsize = 10) - nt.add_face(name_face, column = 0, position = "branch-top") - end - - for bub in ver4.bubble - nnt = nt.add_child(name = "$(bub.id): $(bub.chan) $(bub.Lver.para.innerLoopNum)Ⓧ$(bub.Rver.para.innerLoopNum)") - - name_face = ete.TextFace(nnt.name, fgcolor = "black", fsize = 10) - nnt.add_face(name_face, column = 0, position = "branch-top") - - treeview(bub.Lver, nnt) - treeview(bub.Rver, nnt) - end - - return t - end - - t = treeview(ver4) - # style = ete.NodeStyle() - # style["bgcolor"] = "Khaki" - # t.set_style(style) - - - ts = ete.TreeStyle() - ts.show_leaf_name = true - # ts.show_leaf_name = True - # ts.layout_fn = my_layout - ####### show tree vertically ############ - # ts.rotation = 90 #show tree vertically - - ####### show tree in an arc ############# - # ts.mode = "c" - # ts.arc_start = -180 - # ts.arc_span = 180 - # t.write(outfile="/home/kun/test.txt", format=8) - t.show(tree_style = ts) -end \ No newline at end of file diff --git a/archived/src/parquet_builder/common.jl b/archived/src/parquet_builder/common.jl deleted file mode 100644 index 51100f47..00000000 --- a/archived/src/parquet_builder/common.jl +++ /dev/null @@ -1,182 +0,0 @@ -import ..Filter -import ..Wirreducible #remove all polarization subdiagrams -import ..Girreducible #remove all self-energy inseration -import ..NoHartree -import ..NoFock -import ..NoBubble # true to remove all bubble subdiagram -import ..Proper #ver4, ver3, and polarization diagrams may require to be irreducible along the transfer momentum/frequency -import ..DirectOnly - -import ..DiagramType -import ..GreenDiag -import ..SigmaDiag -import ..PolarDiag -import ..Ver3Diag -import ..Ver4Diag - -import ..Composite -import ..ChargeCharge -import ..SpinSpin -import ..UpUp -import ..UpDown -import ..Response - -import ..Instant -import ..Dynamic -import ..D_Instant -import ..D_Dynamic -import ..AnalyticProperty - -import ..symbol -import ..short - -import ..Interaction -import ..DiagPara -import ..innerTauNum -import ..interactionTauNum -import ..derivepara - -import ..Diagram - -import ..DiagramId -import ..Ver4Id -import ..Ver3Id -import ..GreenId -import ..SigmaId -import ..PolarId -import ..BareInteractionId -import ..BareGreenId - -import ..TwoBodyChannel -import ..Alli -import ..PHr -import ..PHEr -import ..PPr -import ..AnyChan - -import ..Permutation -import ..Di -import ..Ex -import ..DiEx - -import ..uidreset -import ..toDataFrame -import ..mergeby - -function build(para::DiagPara{W}, extK=nothing, subdiagram=false) where {W} - if para.type == Ver4Diag - if isnothing(extK) - extK = [DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2), DiagTree.getK(para.totalLoopNum, 3)] - end - return vertex4(para, extK, [PHr, PHEr, PPr, Alli], subdiagram) - elseif para.type == SigmaDiag - if isnothing(extK) - extK = DiagTree.getK(para.totalLoopNum, 1) - end - return sigma(para, extK, subdiagram) - elseif para.type == PolarDiag - if isnothing(extK) - extK = DiagTree.getK(para.totalLoopNum, 1) - end - return polarization(para, extK, subdiagram) - elseif para.type == Ver3Diag - if isnothing(extK) - extK = [DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2)] - end - return vertex3(para, extK, subdiagram) - else - error("not implemented!") - end -end - -""" - struct ParquetBlocks - - The channels of the left and right sub-vertex4 of a bubble diagram in the parquet equation - -#Members -- `phi` : channels of left sub-vertex for the particle-hole and particle-hole-exchange bubbles -- `ppi` : channels of left sub-vertex for the particle-particle bubble -- `Ξ“4` : channels of right sub-vertex of all channels -""" -struct ParquetBlocks - phi::Vector{TwoBodyChannel} - ppi::Vector{TwoBodyChannel} - Ξ“4::Vector{TwoBodyChannel} - function ParquetBlocks(; phi=[Alli, PHEr, PPr], ppi=[Alli, PHr, PHEr], Ξ“4=union(phi, ppi)) - return new(phi, ppi, Ξ“4) - end -end - -function Base.isequal(a::ParquetBlocks, b::ParquetBlocks) - if issetequal(a.phi, b.phi) && issetequal(a.ppi, b.ppi) && issetequal(a.Ξ“4, b.Ξ“4) - return true - else - return false - end -end -Base.:(==)(a::ParquetBlocks, b::ParquetBlocks) = Base.isequal(a, b) - -function orderedPartition(_total, n, lowerbound=1) - @assert lowerbound >= 0 - total = _total - n * (lowerbound - 1) - @assert total >= n - unorderedPartition = collect(partitions(total, n)) - #e.g., loopNum =5, n =2 ==> unordered = [[4, 1], [3, 2]] - orderedPartition = Vector{Vector{Int}}([]) - for p in unorderedPartition - p = p .+ (lowerbound - 1) - @assert sum(p) == _total - for i in p - @assert i >= lowerbound - end - append!(orderedPartition, Set(permutations(p))) - end - #e.g., loopNum =5, n =2 ==> ordered = [[4, 1], [1, 4], [3, 2], [2, 3]] - return orderedPartition -end - -function findFirstLoopIdx(partition, firstidx::Int) - ## example: firstidx = 1 - # partition = [1, 1, 2, 1], then the loop partition = [1][2][34][5], thus firstTauIdx = [1, 2, 3, 5] - # partition = [1, 0, 2, 0], then the loop partition = [1][][23][], thus firstTauIdx = [1, 2, 2, 4] - # @assert length(partition) == length(isG) - accumulated = accumulate(+, partition; init=firstidx) # idx[i] = firstidx + p[1]+p[2]+...+p[i] - firstLoopIdx = [firstidx,] - append!(firstLoopIdx, accumulated[1:end-1]) - maxLoopIdx = accumulated[end] - 1 - return firstLoopIdx, maxLoopIdx -end - -function findFirstTauIdx(partition::Vector{Int}, type::Vector{DiagramType}, firstidx::Int, _tauNum::Int) - ## example: type =[Vertex4, GreenDiag, Vertex4, GreenDiag], firstidx = 1 - # n-loop G has n*_tauNum DOF, while n-loop ver4 has (n+1)*_tauNum DOF - # partition = [1, 1, 2, 1], then the tau partition = [12][3][456][7], thus firstTauIdx = [1, 3, 4, 7] - # partition = [1, 0, 2, 0], then the tau partition = [12][][345][], thus firstTauIdx = [1, 3, 3, 6] - @assert length(partition) == length(type) - @assert _tauNum >= 0 - taupartition = [innerTauNum(type[i], p, _tauNum) for (i, p) in enumerate(partition)] - accumulated = accumulate(+, taupartition; init=firstidx) # idx[i] = firstidx + p[1]+p[2]+...+p[i] - firstTauidx = [firstidx,] - append!(firstTauidx, accumulated[1:end-1]) - maxTauIdx = accumulated[end] - 1 - return firstTauidx, maxTauIdx -end - -function allsame(df, name::Symbol) - @assert all(x -> x == df[1, name], df[!, name]) "Not all rows of the $name field are the same.\n$df" -end -function allsame(df, names::Vector{Symbol}) - for name in names - allsame(df, name) - end -end -function allsametype(df, name::Symbol) - @assert all(x -> typeof(x) == typeof(df[1, name]), df[!, name]) "Not all rows of the $name field are the same type.\n$df" -end -function allsametype(df, names::Vector{Symbol}) - for name in names - allsametype(df, name) - end -end - diff --git a/archived/src/parquet_builder/ep_coupling.jl b/archived/src/parquet_builder/ep_coupling.jl deleted file mode 100644 index 35d0563b..00000000 --- a/archived/src/parquet_builder/ep_coupling.jl +++ /dev/null @@ -1,144 +0,0 @@ -""" - function ep_coupling(para::DiagPara{W}; - extK=[DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2), DiagTree.getK(para.totalLoopNum, 3)], - channels::AbstractVector=[PHr, PHEr, PPr, Alli], - subdiagram=false, - name=:none, resetuid=false, - blocks::ParquetBlocks=ParquetBlocks() - ) where {W} - -Generate electron-phonon 4-vertex diagrams using Parquet Algorithm. The right incoming Tau will be set to the last Tau for all diagrams -| | -Ξ“3 -------| -| | - -# Arguments -- `para` : parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `extK` : basis of external loops as a vector [left in, left out, right in, right out]. -- `channels` : vector of channels in the left Ξ“3 diagrams. -- `subdiagram` : a sub-vertex or not -- `name` : name of the vertex -- `resetuid` : restart uid count from 1 -- `blocks` : building blocks of the Parquet equation. See the struct ParquetBlocks for more details. - -# Output -- A DataFrame with fields :response, :extT, :diagram, :hash. - -# Output -- A DataFrame with fields :response, :type, :extT, :diagram, :hash -""" -function ep_coupling(para::DiagPara{W}; - extK=[DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2), DiagTree.getK(para.totalLoopNum, 3)], - channels::AbstractVector=[PHr, PHEr, PPr, Alli], - subdiagram=false, - name=:none, resetuid=false, - blocks::ParquetBlocks=ParquetBlocks() -) where {W} - - @warn("ep vertex4 breaks SU(2) spin symmetry!") - if NoBubble in para.filter - @warn("the RPA chain counterterms from the renormalization of the outgoing interaction leg in the ep vertex4 have not yet been implemented!") - end - - for k in extK - @assert length(k) >= para.totalLoopNum "expect dim of extK>=$(para.totalLoopNum), got $(length(k))" - end - - legK = [k[1:para.totalLoopNum] for k in extK[1:3]] - push!(legK, legK[1] + legK[3] - legK[2]) - - resetuid && uidreset() - - @assert para.totalTauNum >= maxVer4TauIdx(para) "Increase totalTauNum!\n$para" - @assert para.totalLoopNum >= maxVer4LoopIdx(para) "Increase totalLoopNum\n$para" - - loopNum = para.innerLoopNum - # @assert loopNum >= 0 - - ver4df = DataFrame(response=Response[], type=AnalyticProperty[], extT=Tuple{Int,Int,Int,Int}[], diagram=Diagram{W}[]) - - partition = orderedPartition(loopNum - 1, 4, 0) - - for p in partition - if p[3] == 0 #oL, oG0, oR, oGx - ep_bubble!(ver4df, para, legK, channels, p, name, blocks, 1.0) - end - end - - if NoBubble in para.filter - # add RPA bubble counter-diagram to remove the bubble - ep_RPA_chain!(ver4df, para, legK, name, -1.0) - end - # println(bub) - - diags = ver4df.diagram - @assert all(x -> x.id isa Ver4Id, diags) "not all id are Ver4Id! $diags" - @assert all(x -> x.id.extK β‰ˆ legK, diags) "not all extK are the same! $diags" - - ver4df = merge_vertex4(para, ver4df, name, legK, W) - @assert all(x -> x[1] == para.firstTauIdx, ver4df.extT) "not all extT[1] are equal to the first Tau index $(para.firstTauIdx)! $ver4df" - # @assert all(x -> x[3] == para.totalTauNum, ver4df.extT) "not all extT[3] are equal to the first Tau index $(para.totalTauNum)! $ver4df" - # @assert all(x -> x[4] == para.totalTauNum, ver4df.extT) "not all extT[4] are equal to the first Tau index $(para.totalTauNum)! $ver4df" - # println(typeof(groups)) - return ver4df -end - -function ep_bubble!(ver4df::DataFrame, para::DiagPara{W}, legK, chans::Vector{TwoBodyChannel}, partition::Vector{Int}, name::Symbol, blocks::ParquetBlocks, - extrafactor=1.0) where {W} - - @assert partition[3] == 0 - - TauNum = interactionTauNum(para) # maximum tau number for each bare interaction - oL, oG0, oR, oGx = partition[1], partition[2], partition[3], partition[4] - if isValidG(para.filter, oG0) == false || isValidG(para.filter, oGx) == false - return - end - - #the first loop idx is the inner loop of the bubble! - LoopIdx = para.firstLoopIdx - idx, maxLoop = findFirstLoopIdx(partition, LoopIdx + 1) - LfirstLoopIdx, G0firstLoopIdx, RfirstLoopIdx, GxfirstLoopIdx = idx - @assert maxLoop == maxVer4LoopIdx(para) - - type = [Ver4Diag, GreenDiag, Ver4Diag, GreenDiag] - idx, maxTau = findFirstTauIdx(partition, type, para.firstTauIdx, TauNum) - LfirstTauIdx, G0firstTauIdx, RfirstTauIdx, GxfirstTauIdx = idx - @assert maxTau == maxVer4TauIdx(para) "Partition $partition with tauNum configuration $idx. maxTau = $maxTau, yet $(maxTauIdx(para)) is expected!" - - lPara = reconstruct(para, type=Ver4Diag, innerLoopNum=oL, firstLoopIdx=LfirstLoopIdx, firstTauIdx=LfirstTauIdx) - rPara = reconstruct(para, type=Ver4Diag, innerLoopNum=oR, firstLoopIdx=RfirstLoopIdx, firstTauIdx=RfirstTauIdx) - gxPara = reconstruct(para, type=GreenDiag, innerLoopNum=oGx, firstLoopIdx=GxfirstLoopIdx, firstTauIdx=GxfirstTauIdx) - g0Para = reconstruct(para, type=GreenDiag, innerLoopNum=oG0, firstLoopIdx=G0firstLoopIdx, firstTauIdx=G0firstTauIdx) - - LLegK, K, RLegK, Kx = legBasis(PHr, legK, LoopIdx) - - Lver = vertex4(lPara, LLegK, chans, true; name=:Ξ“f, blocks=blocks) - isempty(Lver) && return - - Rver = DataFrame(response=Response[], type=AnalyticProperty[], extT=Tuple{Int,Int,Int,Int}[], diagram=Diagram{W}[]) - bareVer4(Rver, rPara, RLegK, [Di,], false) # the external tau is right aligned - Rver = merge_vertex4(rPara, Rver, :bare, RLegK, W) - - @assert isempty(Rver) == false - - for ldiag in Lver.diagram - for rdiag in Rver.diagram - LvT, RvT = ldiag.id.extT, rdiag.id.extT - extT, G0T, GxT = tauBasis(PHr, ldiag.id.extT, rdiag.id.extT) - g0 = green(g0Para, K, G0T, true, name=:G0, blocks=blocks) - gx = green(gxPara, Kx, GxT, true, name=:Gx, blocks=blocks) - @assert g0 isa Diagram && gx isa Diagram - # append!(diag, bubble2diag(para, chan, ldiag, rdiag, legK, g0, gx, extrafactor)) - bubble2diag!(ver4df, para, PHr, ldiag, rdiag, legK, g0, gx, extrafactor) - end - end - return -end - -function ep_RPA_chain!(ver4df::DataFrame, para::DiagPara, legK, name::Symbol, extrafactor) - new_filter = union(union(para.filter, Girreducible), DirectOnly) - para_rpa = reconstruct(para, filter=new_filter) - blocks = ParquetBlocks(; phi=[], ppi=[], Ξ“4=[PHr,]) - ep_bubble!(ver4df, para_rpa, legK, [PHr,], [0, 0, para.innerLoopNum - 1, 0], Symbol("$(name)_ep_RPA_CT"), blocks, extrafactor) - return -end \ No newline at end of file diff --git a/archived/src/parquet_builder/filter.jl b/archived/src/parquet_builder/filter.jl deleted file mode 100644 index 3e64ef68..00000000 --- a/archived/src/parquet_builder/filter.jl +++ /dev/null @@ -1,78 +0,0 @@ -function removeBubble(bubble, lc, rc) - Lver, Rver = bubble.lver, bubble.rver - para = bubble.parent.para - chan = bubble.channel - - if NoBubble in para.filter - if Lver.para.innerLoopNum == 0 && Rver.para.innerLoopNum == 0 - if chan == T || chan == U - if lc == DI && rc == DI - return true - end - end - end - end - - return false -end - -function notProper(para, K) - if Proper in para.filter - transferLoop = para.transferLoop - @assert isempty(transferLoop) == false "Please initialize para.transferLoop to check proper diagrams." - if transferLoop[1:length(K)] β‰ˆ K #transfer loop may have higher dimension than K, then only compare the first K elements - return true - end - end - return false -end - -# check if G exist without creating objects in the pool -function isValidG(filter, innerLoopNum::Int) - #one-loop diagram could be either Fock or Hartree. If both are filtered, then nothing left - if ((NoFock in filter) && (NoHartree in filter)) && (innerLoopNum == 1) - return false - end - - if (Girreducible in filter) && (innerLoopNum > 0) - return false - end - - return true -end - -function isValidG(para::DiagPara) - @assert para.type == GreenDiag - return isValidG(para.filter, para.innerLoopNum) -end - -function isValidSigma(filter, innerLoopNum::Int, subdiagram::Bool) - @assert innerLoopNum >= 0 - if innerLoopNum == 0 - return false - end - if subdiagram && (Girreducible in filter) - return false - end - - #one-loop diagram could be either Fock or Hartree. If both are filtered, then nothing left - if subdiagram && ((NoFock in filter) && (NoHartree in filter)) && innerLoopNum == 1 - return false - end - - return true -end - -function isValidPolarization(filter, innerLoopNum::Int, subdiagram::Bool) - @assert innerLoopNum >= 0 - if innerLoopNum == 0 - return false - end - if subdiagram && (Wirreducible in filter) - return false - end - if subdiagram && (NoBubble in filer) && innerLoopNum == 1 - return false - end - return true -end \ No newline at end of file diff --git a/archived/src/parquet_builder/green.jl b/archived/src/parquet_builder/green.jl deleted file mode 100644 index 9b8202d0..00000000 --- a/archived/src/parquet_builder/green.jl +++ /dev/null @@ -1,115 +0,0 @@ -""" - green(para::DiagPara, extK = DiagTree.getK(para.totalLoopNum, 1), extT = para.hasTau ? (1, 2) : (0, 0), subdiagram = false; - name = :G, resetuid = false, blocks::ParquetBlocks=ParquetBlocks()) - -Build composite Green's function. -By definition, para.firstTauIdx is the first Tau index of the left most self-energy subdiagram. - -# Arguments -- `para` : parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `extK` : basis of external loop. -- `extT`: [Tau index of the left leg, Tau index of the right leg] -- `subdiagram` : a sub-vertex or not -- `name` : name of the diagram -- `resetuid` : restart uid count from 1 -- `blocks` : building blocks of the Parquet equation. See the struct ParquetBlocks for more details. - - -# Output -- A Diagram object or nothing if the Green's function is illegal. -""" -function green(para::DiagPara{W}, extK=DiagTree.getK(para.totalLoopNum, 1), extT=para.hasTau ? (1, 2) : (0, 0), subdiagram=false; - name=:G, resetuid=false, blocks::ParquetBlocks=ParquetBlocks()) where {W} - - @assert isValidG(para) "$para doesn't gives a valid Green's function" - @assert para.type == GreenDiag - @assert para.innerLoopNum >= 0 - # @assert length(extK) == para.totalLoopNum - @assert length(extT) == 2 - - @assert length(extK) >= para.totalLoopNum "expect dim of extK>=$(para.totalLoopNum), got $(length(extK))" - extK = extK[1:para.totalLoopNum] - - resetuid && uidreset() - - tin, tout = extT[1], extT[2] - t0 = para.firstTauIdx - - # if isValidG(para) == false - # return nothing - # end - - if para.innerLoopNum == 0 - return Diagram{W}(BareGreenId(para, k=extK, t=extT), name=name) - end - - # ################# after this step, the Green's function must be nontrivial! ################## - - # if (para.extra isa ParquetBlocks) == false - # parquetblocks = ParquetBlocks(phi=[PPr, PHEr], ppi=[PHr, PHEr], Ξ“4=[PPr, PHr, PHEr]) - # para::DiagPara = reconstruct(para, extra=parquetblocks) - # end - - function Ξ£G(group, oG, Tidx, Kidx, Ξ£Tidx) - #type: Instant or Dynamic - paraG = reconstruct(para, type=GreenDiag, firstTauIdx=Tidx, firstLoopIdx=Kidx, innerLoopNum=oG) - G = Parquet.green(paraG, extK, group[:GT], true; blocks=blocks) - # G = Diagram(GreenId(paraG, k = extK, t = group[:GT]), name = Symbol("g#$li")) #there is only one G diagram for a extT - @assert G isa Diagram - # println(group) - pairT = (t=(Ξ£Tidx, (group[:GT][2])),) - return Diagram{W}(GenericId(para, pairT), Prod(), [group[:diagram], G], name=:Ξ£G) - end - - para0 = reconstruct(para, innerLoopNum=0) #parameter for g0 - g0 = Diagram{W}(BareGreenId(para0, k=extK, t=(tin, t0)), name=:g0) - Ξ£Gpairs = Vector{Diagram{W}}() - for p in orderedPartition(para.innerLoopNum, 2, 0) - oΞ£, oG = p - - if (isValidSigma(para.filter, oΞ£, true) == false) || (isValidG(para.filter, oG) == false) - continue - end - - idx, maxTau = findFirstTauIdx(p, [SigmaDiag, GreenDiag], t0, interactionTauNum(para)) - @assert maxTau <= para.totalTauNum "maxTau = $maxTau > $(para.totalTauNum)" - if para.hasTau - @assert tin < t0 || tin > maxTau "external T index cann't be with in [$t0, $maxTau]" - @assert tout < t0 || tout > maxTau "external T index cann't be with in [$t0, $maxTau]" - end - Ξ£firstTidx, GfirstTidx = idx - - idx, maxLoop = findFirstLoopIdx(p, para.firstLoopIdx) - @assert maxLoop <= para.totalLoopNum "maxLoop = $maxLoop > $(para.totalLoopNum)" - Ξ£firstKidx, GfirstKidx = idx - - sigmaPara = reconstruct(para, type=SigmaDiag, firstTauIdx=Ξ£firstTidx, firstLoopIdx=Ξ£firstKidx, innerLoopNum=oΞ£) - # println(Ξ£firstTidx) - sigma = Parquet.sigma(sigmaPara, extK, true, name=:Ξ£, blocks=blocks) - @assert all(x -> x[1] == Ξ£firstTidx, sigma.extT) "all sigma should share the same in Tidx\n$sigma" - - #combine sigmas with the same out Tidx - df = transform(sigma, :extT => ByRow(x -> [x[1], (x[2], extT[2]),]) => [:Tin, :GT,]) - allsame(df, :Tin) - groups = mergeby(df, :GT, operator=Sum()) - - #for each sigma group, attach a G, all pair Ξ£G share the same in and out Tidx - append!(Ξ£Gpairs, [Ξ£G(g, oG, GfirstTidx, GfirstKidx, Ξ£firstTidx) for g in eachrow(groups)]) - end - # println(Ξ£Gpairs) - # println(operator) - Ξ£Gmerged = mergeby(Ξ£Gpairs; operator=Sum(), name=:gΞ£G)[1] - - # ORIGINAL: - # compositeG = Diagram{W}(GreenId(para, k=extK, t=extT), Prod(), [g0, Ξ£Gmerged], name=:G) - - # PROPOSITION 1: Allow the user's custom name to persist after unwrapping with Parquet.green - compositeG = Diagram{W}(GreenId(para, k=extK, t=extT), Prod(), [g0, Ξ£Gmerged], name=name) - - # PROPOSITION 2: Allow the user's custom name to persist after unwrapping with Parquet.green - # if the string representation contains "G" (e.g., :G₁ and :Gdashed are allowed) - # validname = contains(string(name), "G") ? name : (:G) - # compositeG = Diagram{W}(GreenId(para, k=extK, t=extT), Prod(), [g0, Ξ£Gmerged], name=validname) - - return compositeG -end \ No newline at end of file diff --git a/archived/src/parquet_builder/parquet.jl b/archived/src/parquet_builder/parquet.jl deleted file mode 100644 index 8344b657..00000000 --- a/archived/src/parquet_builder/parquet.jl +++ /dev/null @@ -1,34 +0,0 @@ -module Parquet - -using StaticArrays, PyCall -using AbstractTrees -using Parameters, Combinatorics -using DataFrames -using ..DiagTree - -# if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@optlevel")) -# @eval Base.Experimental.@optlevel 1 -# end - - -const DI, EX, BOTH = 1, 2, 3 -const INL, OUTL, INR, OUTR = 1, 2, 3, 4 -# orginal diagrams T, U, S; particle-hole counterterm Ts, Us; and their counterterm Tc, Uc, Sc, Tsc, Usc -# symmetry factor for Alli, PHr, PHEr, PPr, PHrc, PHErc -const SymFactor = [1.0, -1.0, 1.0, -0.5, +1.0, -1.0] - -include("common.jl") -export ParquetBlocks - -include("filter.jl") -include("vertex4.jl") - -include("sigma.jl") -include("green.jl") -include("vertex3.jl") -include("polarization.jl") - -include("ep_coupling.jl") - -include("benchmark/benchmark.jl") -end \ No newline at end of file diff --git a/archived/src/parquet_builder/polarization.jl b/archived/src/parquet_builder/polarization.jl deleted file mode 100644 index a84a681d..00000000 --- a/archived/src/parquet_builder/polarization.jl +++ /dev/null @@ -1,140 +0,0 @@ - -""" - function polarization(para, extK = DiagTree.getK(para.totalLoopNum, 1), subdiagram = false; name = :Ξ , resetuid = false, blocks::ParquetBlocks=ParquetBlocks()) - -Generate polarization diagrams using Parquet Algorithm. - -# Arguments -- `para` : parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `extK` : basis of external loop. -- `subdiagram` : a sub-vertex or not -- `name` : name of the vertex -- `resetuid` : restart uid count from 1 -- `blocks` : building blocks of the Parquet equation. See the struct ParquetBlocks for more details. - -# Output -- A DataFrame with fields `:response`, `:diagram`, `:hash`. -- All polarization share the same external Tau index. With imaginary-time variables, they are extT = (para.firstTauIdx, para.firstTauIdx+1) -""" -function polarization(para::DiagPara{W}, extK=DiagTree.getK(para.totalLoopNum, 1), subdiagram=false; name=:Ξ , resetuid=false, - blocks::ParquetBlocks=ParquetBlocks() -) where {W} - resetuid && uidreset() - @assert para.type == PolarDiag - @assert para.innerLoopNum >= 1 - # @assert length(extK) == para.totalLoopNum - @assert length(extK) >= para.totalLoopNum "expect dim of extK>=$(para.totalLoopNum), got $(length(extK))" - - #polarization diagram should always proper - # if !(Proper in _para.filter) || (length(_para.transferLoop) != length(extK)) || (_para.transferLoop β‰ˆ extK) - # # @warn "Polarization diagram parameter is not proper. It will be reconstructed with proper transfer loops." - # para = derivepara(_para, filter=union(Proper, _para.filter), transferLoop=extK) - # end - para = _properPolarPara(para, extK) - - extK = extK[1:para.totalLoopNum] - - # if (para.extra isa ParquetBlocks) == false - # para::DiagPara = reconstruct(para, extra=ParquetBlocks()) - # end - - K = zero(extK) - LoopIdx = para.firstLoopIdx - K[LoopIdx] = 1.0 - @assert (K β‰ˆ extK) == false - t0 = para.firstTauIdx - extT = para.hasTau ? (t0, t0 + 1) : (t0, t0) - legK = [extK, K, K .- extK] - - polar = DataFrame(response=Response[], extT=Tuple{Int,Int}[], diagram=Diagram{W}[]) - - for (oVer3, oGin, oGout) in orderedPartition(para.innerLoopNum - 1, 3, 0) - # ! Vertex3 must be in the first place, because we want to make sure that the bosonic extT of the vertex3 start with t0+1 - - idx, maxLoop = findFirstLoopIdx([oVer3, oGin, oGout], LoopIdx + 1) # GGΞ“3 consumes one internal loop - @assert maxLoop <= para.totalLoopNum "maxLoop = $maxLoop > $(para.totalLoopNum)" - Ver3Kidx, GinKidx, GoutKidx = idx - - if isValidG(para.filter, oGin) && isValidG(para.filter, oGout) - if oVer3 == 0 - ######################## Ξ 0 = GG ######################################### - gt0 = para.hasTau ? extT[2] + 1 : extT[1] - idx, maxTau = findFirstTauIdx([oGin, oGout], [GreenDiag, GreenDiag], gt0, interactionTauNum(para)) - @assert maxTau <= para.totalTauNum "maxTau = $maxTau > $(para.totalTauNum)" - GinTidx, GoutTidx = idx - - paraGin = reconstruct(para, type=GreenDiag, innerLoopNum=oGin, - firstLoopIdx=GinKidx, firstTauIdx=GinTidx) - paraGout = reconstruct(para, type=GreenDiag, innerLoopNum=oGout, - firstLoopIdx=GoutKidx, firstTauIdx=GoutTidx) - - response = UpUp - polarid = PolarId(para, response, k=extK, t=extT) - gin = green(paraGin, K, (extT[1], extT[2]), true, name=:Gin) - gout = green(paraGout, K .- extK, (extT[2], extT[1]), true, name=:Gout) - @assert gin isa Diagram && gout isa Diagram "$gin or $gout is not a single diagram" - - sign = para.isFermi ? -1.0 : 1.0 - polardiag = Diagram{W}(polarid, Prod(), [gin, gout], name=name, factor=sign) - push!(polar, (response=response, extT=extT, diagram=polardiag)) - else - ##################### composite polarization ##################################### - idx, maxTau = findFirstTauIdx([oVer3, oGin, oGout], [Ver3Diag, GreenDiag, GreenDiag], extT[2], interactionTauNum(para)) - @assert maxTau <= para.totalTauNum "maxTau = $maxTau > $(para.totalTauNum)" - Ver3Tidx, GinTidx, GoutTidx = idx - - paraGin = reconstruct(para, type=GreenDiag, innerLoopNum=oGin, - firstLoopIdx=GinKidx, firstTauIdx=GinTidx) - paraGout = reconstruct(para, type=GreenDiag, innerLoopNum=oGout, - firstLoopIdx=GoutKidx, firstTauIdx=GoutTidx) - - paraVer3 = reconstruct(para, type=Ver3Diag, innerLoopNum=oVer3, - firstLoopIdx=Ver3Kidx, firstTauIdx=Ver3Tidx) - ver3 = vertex3(paraVer3, legK, true; blocks=blocks) - if isnothing(ver3) || isempty(ver3) - continue - end - if para.hasTau - @assert all(x -> x[1] == extT[2], ver3.extT) "The bosonic T must be firstTauIdx+1 if hasTau\n$ver3" - @assert all(x -> x[2] == ver3[1, :extT][2], ver3.extT) "The TinL must be firstTauIdx+2 if hasTau\n$ver3" - end - - #transform extT coloum into extT for Vertex4 and the extT for Gin and Gout - df = transform(ver3, :extT => ByRow(x -> [extT, (extT[1], x[2]), (x[3], extT[1])]) => [:extT, :GinT, :GoutT]) - - groups = mergeby(W, df, [:response, :GinT, :GoutT, :extT], operator=Sum()) - - for v3 in eachrow(groups) - response = v3.response - @assert response == UpUp || response == UpDown - #type: Instant or Dynamic - polarid = PolarId(para, response, k=extK, t=v3.extT) - gin = green(paraGin, K, v3.GinT, true, name=:Gin, blocks=blocks) - gout = green(paraGout, K .- extK, v3.GoutT, true, name=:Gout, blocks=blocks) - @assert gin isa Diagram && gout isa Diagram - - polardiag = Diagram{W}(polarid, Prod(), [gin, gout, v3.diagram], name=name) - push!(polar, (response=response, extT=v3.extT, diagram=polardiag)) - end - end - end - end - - if isempty(polar) == false - # legK = [extK, K, K, extK] - # Factor = 1 / (2Ο€)^para.loopDim - Factor = 1.0 - polar = mergeby(W, polar, [:response, :extT]; name=name, factor=Factor, - getid=g -> PolarId(para, g[1, :response], k=extK, t=extT) - ) - end - return polar -end - -function _properPolarPara(p::DiagPara{W}, q) where {W} - # ############ reset transferLoop to be q ################ - if !(Proper in p.filter) || (length(p.transferLoop) != length(q)) || (p.transferLoop β‰ˆ q) - return derivepara(p, transferLoop=q, filter=union(Proper, p.filter)) - end - return p -end \ No newline at end of file diff --git a/archived/src/parquet_builder/sigma.jl b/archived/src/parquet_builder/sigma.jl deleted file mode 100644 index b0700d41..00000000 --- a/archived/src/parquet_builder/sigma.jl +++ /dev/null @@ -1,138 +0,0 @@ -""" - function sigma(para, extK = DiagTree.getK(para.totalLoopNum, 1), subdiagram = false; name = :Ξ£, resetuid = false, blocks::ParquetBlocks=ParquetBlocks()) - -Build sigma diagram. -When sigma is created as a subdiagram, then no Fock diagram is generated if para.filter contains NoFock, and no sigma diagram is generated if para.filter contains Girreducible - -# Arguments -- `para` : parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `extK` : basis of external loop. -- `subdiagram` : a sub-vertex or not -- `name` : name of the diagram -- `resetuid` : restart uid count from 1 -- `blocks` : building blocks of the Parquet equation. See the struct ParquetBlocks for more details. - -# Output -- A DataFrame with fields `:type`, `:extT`, `:diagram`, `:hash` -- All sigma share the same incoming Tau index, but not the outgoing one -""" -function sigma(para::DiagPara{W}, extK=DiagTree.getK(para.totalLoopNum, 1), subdiagram=false; - name=:Ξ£, resetuid=false, blocks::ParquetBlocks=ParquetBlocks() -) where {W} - resetuid && uidreset() - (para.type == SigmaDiag) || error("$para is not for a sigma diagram") - (para.innerLoopNum >= 1) || error("sigma must has more than one inner loop") - # @assert length(extK) == para.totalLoopNum - # @assert (para.innerLoopNum <= 1) || ((NoBubble in para.filter) == false) "The many-body correction sigma only accounts for half of the bubble counterterm right now." - if (para.innerLoopNum > 1) && (NoBubble in para.filter) - @warn "Sigma with two or more loop orders still contain bubble subdiagram even if NoBubble is turned on in para.filter!" - end - - (length(extK) >= para.totalLoopNum) || error("expect dim of extK>=$(para.totalLoopNum), got $(length(extK))") - extK = extK[1:para.totalLoopNum] - - compositeSigma = DataFrame(type=AnalyticProperty[], extT=Tuple{Int,Int}[], diagram=Diagram{W}[]) - - if isValidSigma(para.filter, para.innerLoopNum, subdiagram) == false - # return DataFrame(type=[], extT=[], diagram=[]) - return compositeSigma - end - - # if (para.extra isa ParquetBlocks) == false - # parquetblocks = ParquetBlocks(phi=[PPr, PHEr], ppi=[PHr, PHEr], Ξ“4=[PPr, PHr, PHEr]) - # para::DiagPara = reconstruct(para, extra=parquetblocks) - # end - - K = zero(extK) - LoopIdx = para.firstLoopIdx - K[LoopIdx] = 1.0 - (isapprox(K, extK) == false) || error("K and extK can not be the same") - legK = [extK, K, K, extK] - - function GWwithGivenExTtoΞ£(group, oW, paraG) - # println(group) - # @assert length(group[:, :diagram]) == 1 - # allsame(group, [:response, :type, :GT]) - (group[:response] == UpUp || group[:response] == UpDown) || error("GW with given ExT to Ξ£ only works for UpUp or UpDown") - #type: Instant or Dynamic - response, type = group[:response], group[:type] - sid = SigmaId(para, type, k=extK, t=group[:extT]) - g = green(paraG, K, group[:GT], true; name=(oW == 0 ? :Gfock : :G_Ξ£), blocks=blocks) #there is only one G diagram for a extT - (g isa Diagram) || error("green function must return a Diagram") - # Sigma = G*(2 W↑↑ - W↑↓) - # ! The sign of ↑↓ is from the spin symmetry, not from the fermionic statistics! - spinfactor = (response == UpUp) ? 2 : -1 - if (oW > 0) # oW are composte Sigma, there is a symmetry factor 1/2 - spinfactor *= 0.5 - end - # plot_tree(mergeby(DataFrame(group)), maxdepth = 7) - sigmadiag = Diagram{W}(sid, Prod(), [g, group[:diagram]], factor=spinfactor, name=name) - # plot_tree(sigmadiag, maxdepth = 7) - return (type=type, extT=group[:extT], diagram=sigmadiag) - end - - for (oG, oW) in orderedPartition(para.innerLoopNum - 1, 2, 0) - - idx, maxLoop = findFirstLoopIdx([oW, oG], LoopIdx + 1) - (maxLoop <= para.totalLoopNum) || error("maxLoop = $maxLoop > $(para.totalLoopNum)") - WfirstLoopIdx, GfirstLoopIdx = idx - - # it is important to do W first, because the left in of W is also the incoming leg of sigma, they have the same Tidx - idx, maxTau = findFirstTauIdx([oW, oG], [Ver4Diag, GreenDiag], para.firstTauIdx, interactionTauNum(para)) - (maxTau <= para.totalTauNum) || error("maxTau = $maxTau > $(para.totalTauNum)") - WfirstTauIdx, GfirstTauIdx = idx - - paraG = reconstruct(para, type=GreenDiag, innerLoopNum=oG, - firstLoopIdx=GfirstLoopIdx, firstTauIdx=GfirstTauIdx) - paraW = reconstruct(para, type=Ver4Diag, innerLoopNum=oW, - firstLoopIdx=WfirstLoopIdx, firstTauIdx=WfirstTauIdx) - - #TODO: add validation for paraW - # println("oG: $oG, oW: $oW -> ", isValidG(paraG)) - if isValidG(paraG) - # println(paraW) - if oW == 0 # Fock-type Ξ£ - if NoHartree in paraW.filter - paraW0 = reconstruct(paraW, filter=union(paraW.filter, Proper), transferLoop=zero(K)) - ver4 = vertex4(paraW0, legK, [], true) - else - ver4 = vertex4(paraW, legK, [], true) - end - # println(ver4) - else # composite Ξ£ - # paraW0 = reconstruct(paraW, filter=union(paraW.filter, Proper), transferLoop=extK-K) - # plot_tree(mergeby(ver4).diagram[1]) - # if compact - # ver4 = ep_coupling(paraW; extK=legK, subdiagram=true, name=:W, blocks=blocks) - # else - ver4 = vertex4(paraW, legK, [PHr,], true; blocks=blocks, blockstoplevel=ParquetBlocks(phi=[], Ξ“4=[PHr, PHEr, PPr])) - # end - end - #transform extT coloum intwo extT for Ξ£ and extT for G - # plot_tree(ver4) - df = transform(ver4, :extT => ByRow(x -> [(x[INL], x[OUTR]), (x[OUTL], x[INR])]) => [:extT, :GT]) - - groups = mergeby(W, df, [:response, :type, :GT, :extT], operator=Sum()) - for mergedVer4 in eachrow(groups) - push!(compositeSigma, GWwithGivenExTtoΞ£(mergedVer4, oW, paraG)) - end - end - end - - - if isempty(compositeSigma) - return compositeSigma - else - # Factor = 1 / (2Ο€)^para.loopDim - Factor = 1.0 - # sigmaid(g) = SigmaId(para, g[1, :type], k=extK, t=g[1, :extT]) - # sigmadf = mergeby(compositeSigma, [:type, :extT], name=name, factor=Factor, getid=sigmaid) - sigmadf = mergeby(W, compositeSigma, [:type, :extT], name=name, factor=Factor, - getid=g -> SigmaId(para, g[1, :type], k=extK, t=g[1, :extT])) - - all(x -> x[1] == para.firstTauIdx, sigmadf.extT) || error("all sigma should share the same in Tidx\n$sigmadf") - # println(sigmadf) - # plot_tree(sigmadf) - return sigmadf - end -end \ No newline at end of file diff --git a/archived/src/parquet_builder/sigmaGV.jl b/archived/src/parquet_builder/sigmaGV.jl deleted file mode 100644 index 3253b075..00000000 --- a/archived/src/parquet_builder/sigmaGV.jl +++ /dev/null @@ -1,134 +0,0 @@ - -""" - function sigmaGV(para, extK = DiagTree.getK(para.totalLoopNum, 1), subdiagram = false; name = :Ξ£, resetuid = false, blocks::ParquetBlocks=ParquetBlocks()) - -Build sigma diagram. -When sigma is created as a subdiagram, then no Fock diagram is generated if para.filter contains NoFock, and no sigma diagram is generated if para.filter contains Girreducible - -# Arguments -- `para` : parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `extK` : basis of external loop. -- `subdiagram` : a sub-vertex or not -- `name` : name of the diagram -- `resetuid` : restart uid count from 1 -- `blocks` : building blocks of the Parquet equation. See the struct ParquetBlocks for more details. - -# Output -- A DataFrame with fields `:type`, `:extT`, `:diagram`, `:hash` -- All sigma share the same incoming Tau index, but not the outgoing one -""" -function sigmaGV(para::DiagPara{W}, extK=DiagTree.getK(para.totalLoopNum, 1), subdiagram=false; - name=:Ξ£, resetuid=false, blocks::ParquetBlocks=ParquetBlocks() -) where {W} - resetuid && uidreset() - for i in para.interaction - @assert (Dynamic in i.type) == false "Dynamic interaction is not supported for sigmaGV diagrams." - end - @assert NoHartree in para.filter "sigmaGV diagrams must have NoHartree in para.filter." - - (para.type == SigmaDiag) || error("$para is not for a sigma diagram") - (para.innerLoopNum >= 1) || error("sigma must has more than one inner loop") - # @assert length(extK) == para.totalLoopNum - # @assert (para.innerLoopNum <= 1) || ((NoBubble in para.filter) == false) "The many-body correction sigma only accounts for half of the bubble counterterm right now." - if (para.innerLoopNum > 1) && (NoBubble in para.filter) - @warn "Sigma with two or more loop orders still contain bubble subdiagram even if NoBubble is turned on in para.filter!" - end - - (length(extK) >= para.totalLoopNum) || error("expect dim of extK>=$(para.totalLoopNum), got $(length(extK))") - extK = extK[1:para.totalLoopNum] - - compositeSigma = DataFrame(type=AnalyticProperty[], extT=Tuple{Int,Int}[], diagram=Diagram{W}[]) - - if isValidSigma(para.filter, para.innerLoopNum, subdiagram) == false - # return DataFrame(type=[], extT=[], diagram=[]) - return compositeSigma - end - - # if (para.extra isa ParquetBlocks) == false - # parquetblocks = ParquetBlocks(phi=[PPr, PHEr], ppi=[PHr, PHEr], Ξ“4=[PPr, PHr, PHEr]) - # para::DiagPara = reconstruct(para, extra=parquetblocks) - # end - - K = zero(extK) - LoopIdx = para.firstLoopIdx - K[LoopIdx] = 1.0 - (isapprox(K, extK) == false) || error("K and extK can not be the same") - legK = [extK, K, K, extK] - - function GWwithGivenExTtoΞ£(group, oW, paraG) - # println(group) - # @assert length(group[:, :diagram]) == 1 - # allsame(group, [:response, :type, :GT]) - (group[:response] == UpUp || group[:response] == UpDown) || error("GW with given ExT to Ξ£ only works for UpUp or UpDown") - #type: Instant or Dynamic - response, type = group[:response], group[:type] - sid = SigmaId(para, type, k=extK, t=group[:extT]) - g = green(paraG, K, group[:GT], true; name=(oW == 0 ? :Gfock : :G_Ξ£), blocks=blocks) #there is only one G diagram for a extT - (g isa Diagram) || error("green function must return a Diagram") - # Sigma = G*(2 W↑↑ - W↑↓) - # ! The sign of ↑↓ is from the spin symmetry, not from the fermionic statistics! - spinfactor = (response == UpUp) ? 2 : -1 - if (oW > 0) # oW are composte Sigma, there is a symmetry factor 1/2 - spinfactor *= 0.5 - end - # plot_tree(mergeby(DataFrame(group)), maxdepth = 7) - sigmadiag = Diagram{W}(sid, Prod(), [g, group[:diagram]], factor=spinfactor, name=name) - # plot_tree(sigmadiag, maxdepth = 7) - return (type=type, extT=group[:extT], diagram=sigmadiag) - end - - for (oG, oW) in orderedPartition(para.innerLoopNum - 1, 2, 0) - - idx, maxLoop = findFirstLoopIdx([oW, oG], LoopIdx + 1) - (maxLoop <= para.totalLoopNum) || error("maxLoop = $maxLoop > $(para.totalLoopNum)") - WfirstLoopIdx, GfirstLoopIdx = idx - - # it is important to do W first, because the left in of W is also the incoming leg of sigma, they have the same Tidx - idx, maxTau = findFirstTauIdx([oW, oG], [Ver3Diag, GreenDiag], para.firstTauIdx, interactionTauNum(para)) - (maxTau <= para.totalTauNum) || error("maxTau = $maxTau > $(para.totalTauNum)") - WfirstTauIdx, GfirstTauIdx = idx - - paraG = reconstruct(para, type=GreenDiag, innerLoopNum=oG, - firstLoopIdx=GfirstLoopIdx, firstTauIdx=GfirstTauIdx) - paraW = reconstruct(para, type=Ver3Diag, innerLoopNum=oW, - firstLoopIdx=WfirstLoopIdx, firstTauIdx=WfirstTauIdx) - - #TODO: add validation for paraW - # println("oG: $oG, oW: $oW -> ", isValidG(paraG)) - if isValidG(paraG) - # println(paraW) - paraW0 = reconstruct(paraW, filter=union(paraW.filter, Proper), transferLoop=zero(K)) - bareV = vertex4(paraW0, legK, [], true) - if oW == 0 # Fock-type Ξ£ - ver4 = bareV - df = transform(ver4, :extT => ByRow(x -> [(x[INL], x[OUTR]), (x[OUTL], x[INR])]) => [:extT, :GT]) - - groups = mergeby(W, df, [:response, :type, :GT, :extT], operator=Sum()) - for mergedVer4 in eachrow(groups) - push!(compositeSigma, GWwithGivenExTtoΞ£(mergedVer4, oW, paraG)) - end - else # composite Ξ£ - ver3 = vertex3(paraW, [extK - K, extK, K]) - end - #transform extT coloum intwo extT for Ξ£ and extT for G - # plot_tree(ver4) - end - end - - - if isempty(compositeSigma) - return compositeSigma - else - # Factor = 1 / (2Ο€)^para.loopDim - Factor = 1.0 - # sigmaid(g) = SigmaId(para, g[1, :type], k=extK, t=g[1, :extT]) - # sigmadf = mergeby(compositeSigma, [:type, :extT], name=name, factor=Factor, getid=sigmaid) - sigmadf = mergeby(W, compositeSigma, [:type, :extT], name=name, factor=Factor, - getid=g -> SigmaId(para, g[1, :type], k=extK, t=g[1, :extT])) - - all(x -> x[1] == para.firstTauIdx, sigmadf.extT) || error("all sigma should share the same in Tidx\n$sigmadf") - # println(sigmadf) - # plot_tree(sigmadf) - return sigmadf - end -end \ No newline at end of file diff --git a/archived/src/parquet_builder/vertex3.jl b/archived/src/parquet_builder/vertex3.jl deleted file mode 100644 index affedb7f..00000000 --- a/archived/src/parquet_builder/vertex3.jl +++ /dev/null @@ -1,127 +0,0 @@ -""" - function vertex3(para, extK = [DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2)], - subdiagram = false; name = :Ξ“3, chan = [PHr, PHEr, PPr, Alli], resetuid = false, - blocks::ParquetBlocks=ParquetBlocks() - ) - -Generate 3-vertex diagrams using Parquet Algorithm. -With imaginary-time variables, all vertex3 generated has the same bosonic Tidx ``extT[1]=para.firstTauIdx`` and the incoming fermionic Tidx ``extT[2]=para.firstTauIdx+1``. - -#Arguments -- `para` : parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `extK` : basis of external loops as a vector [bosonic leg (out), fermionic in, fermionic out], extK[1] = extK[2] - extK[3]. -- `subdiagram` : a sub-vertex or not -- `name` : name of the vertex -- `chan` : vector of channels of the current 4-vertex. -- `resetuid` : restart uid count from 1 -- `blocks` : building blocks of the Parquet equation. See the struct ParquetBlocks for more details. - -# Output -- A DataFrame with fields :response, :extT, :diagram, :hash. -""" -function vertex3(para::DiagPara{WW}, - _extK=[DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2)], - subdiagram=false; - name=:Ξ“3, - chan=[PHr, PHEr, PPr, Alli], - resetuid=false, - blocks::ParquetBlocks=ParquetBlocks() -) where {WW} - - resetuid && uidreset() - @assert para.type == Ver3Diag - @assert para.innerLoopNum >= 1 "Only generates vertex corrections with more than one internal loops." - for k in _extK - @assert length(k) >= para.totalLoopNum "expect dim of extK>=$(para.totalLoopNum), got $(length(k))" - end - - q, Kin = _extK[1][1:para.totalLoopNum], _extK[2][1:para.totalLoopNum] - # Kout = length(extK) == 3 ? extK[3] : Kin .- q - Kout = Kin - q - @assert ((q β‰ˆ Kin) == false) && ((q β‰ˆ Kout) == false) "The bosonic q cann't be same as the fermionic k. Ohterwise the proper diagram check will fail!" - extK = [q, Kin, Kout] - - para = _properVer3Para(para, q) - - t0 = para.firstTauIdx - vertex3 = DataFrame(response=Response[], extT=Tuple{Int,Int,Int}[], diagram=Diagram{WW}[]) - - # if para.innerLoopNum == 0 - # push!(vertex3, (response = UpUp, extT = (t0, t0, t0), diagram = ver3diag)) - # end - - K = zero(q) - LoopIdx = para.firstLoopIdx - K[LoopIdx] = 1.0 - # extT = (t0, t0 + 1) - legK = [Kin, Kout, K, K .+ q] - - ######################## Ξ 0 = GG ######################################### - for (oVer4, oGin, oGout) in orderedPartition(para.innerLoopNum - 1, 3, 0) - # ! Vertex4 must be in the first place, because we want to make sure that the TinL of the vertex4 start with t0+1 - - idx, maxLoop = findFirstLoopIdx([oVer4, oGin, oGout], LoopIdx + 1) - @assert maxLoop <= para.totalLoopNum "maxLoop = $maxLoop > $(para.totalLoopNum)" - Ver4Kidx, GinKidx, GoutKidx = idx - - ver4t0 = para.hasTau ? para.firstTauIdx + 1 : para.firstTauIdx - idx, maxTau = findFirstTauIdx([oVer4, oGin, oGout], [Ver4Diag, GreenDiag, GreenDiag], ver4t0, interactionTauNum(para)) - @assert maxTau <= para.totalTauNum "maxTau = $maxTau > $(para.totalTauNum)" - Ver4Tidx, GinTidx, GoutTidx = idx - - if isValidG(para.filter, oGin) && isValidG(para.filter, oGout) - paraGin = reconstruct(para, type=GreenDiag, innerLoopNum=oGin, - firstLoopIdx=GinKidx, firstTauIdx=GinTidx) - paraGout = reconstruct(para, type=GreenDiag, innerLoopNum=oGout, - firstLoopIdx=GoutKidx, firstTauIdx=GoutTidx) - paraVer4 = reconstruct(para, type=Ver4Diag, innerLoopNum=oVer4, - firstLoopIdx=Ver4Kidx, firstTauIdx=Ver4Tidx) - ver4 = vertex4(paraVer4, legK, chan, true; blocks=blocks) - if isnothing(ver4) || isempty(ver4) - continue - end - - if para.hasTau - @assert all(x -> x[INL] == ver4t0, ver4.extT) "The TinL of the inner Ξ“4 must be firstTauIdx+1" - end - - #transform extT coloum into extT for Vertex4 and the extT for Gin and Gout - df = transform(ver4, :extT => ByRow(x -> [(t0, x[INL], x[OUTL]), (t0, x[INR]), (x[OUTR], t0)]) => [:extT, :GinT, :GoutT]) - - groups = mergeby(WW, df, [:response, :GinT, :GoutT, :extT], operator=Sum()) - - for v4 in eachrow(groups) - response = v4.response - @assert response == UpUp || response == UpDown - #type: Instant or Dynamic - ver3id = Ver3Id(para, response, k=extK, t=v4.extT) - gin = green(paraGin, K, v4.GinT, true, name=:Gin, blocks=blocks) - gout = green(paraGout, K .+ q, v4.GoutT, true, name=:Gout, blocks=blocks) - @assert gin isa Diagram && gout isa Diagram - - ver3diag = Diagram{WW}(ver3id, Prod(), [gin, gout, v4.diagram], name=name) - push!(vertex3, (response=response, extT=v4.extT, diagram=ver3diag)) - end - end - end - # println(vertex3) - - if isempty(vertex3) == false - # Factor = 1 / (2Ο€)^para.loopDim - Factor = 1.0 - vertex3 = mergeby(WW, vertex3, [:response, :extT]; name=name, factor=Factor, - getid=g -> Ver3Id(para, g[1, :response], k=extK, t=g[1, :extT]) - ) - end - return vertex3 -end - -function _properVer3Para(p::DiagPara{W}, q) where {W} - # ############ reset transferLoop to be q ################ - if Proper in p.filter - if (length(p.transferLoop) != length(q)) || (!(p.transferLoop β‰ˆ q)) #first check if the dimension is wrong - return derivepara(p, transferLoop=q) - end - end - return p -end diff --git a/archived/src/parquet_builder/vertex4.jl b/archived/src/parquet_builder/vertex4.jl deleted file mode 100644 index 23bc1637..00000000 --- a/archived/src/parquet_builder/vertex4.jl +++ /dev/null @@ -1,482 +0,0 @@ -""" - vertex4(para::DiagPara, - extK = [DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2), DiagTree.getK(para.totalLoopNum, 3)], - chan::AbstractVector = [PHr, PHEr, PPr, Alli], - subdiagram = false; - level = 1, name = :none, resetuid = false, - blocks::ParquetBlocks=ParquetBlocks(), - blockstoplevel::ParquetBlocks=blocks - ) - -Generate 4-vertex diagrams using Parquet Algorithm - -# Arguments -- `para` : parameters. It should provide internalLoopNum, interactionTauNum, firstTauIdx -- `extK` : basis of external loops as a vector [left in, left out, right in, right out]. -- `chan` : vector of channels of the current 4-vertex. -- `subdiagram` : a sub-vertex or not -- `name` : name of the vertex -- `level` : level in the diagram tree -- `resetuid` : restart uid count from 1 -- `blocks` : building blocks of the Parquet equation. See the struct ParquetBlocks for more details. -- `blockstoplevel` : building blocks of the Parquet equation at the toplevel. See the struct ParquetBlocks for more details. - -# Output -- A DataFrame with fields :response, :type, :extT, :diagram, :hash -""" -function vertex4(para::DiagPara{W}, - extK=[DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2), DiagTree.getK(para.totalLoopNum, 3)], - chan::AbstractVector=[PHr, PHEr, PPr, Alli], subdiagram=false; - level=1, name=:none, resetuid=false, - # phi_toplevel=ParquetBlocks().phi, ppi_toplevel=ParquetBlocks().ppi, Ξ“4_toplevel=ParquetBlocks().Ξ“4, - blocks::ParquetBlocks=ParquetBlocks(), - blockstoplevel::ParquetBlocks=blocks -) where {W} - - # if (para.innerLoopNum > 1) && (NoBubble in para.filter) - # @warn "Vertex4 with two or more loop orders still contain bubble subdiagram even if NoBubble is turned on in para.filter!" - # end - - for k in extK - @assert length(k) >= para.totalLoopNum "expect dim of extK>=$(para.totalLoopNum), got $(length(k))" - end - - legK = [k[1:para.totalLoopNum] for k in extK[1:3]] - push!(legK, legK[1] + legK[3] - legK[2]) - - resetuid && uidreset() - - @assert para.totalTauNum >= maxVer4TauIdx(para) "Increase totalTauNum!\n$para" - @assert para.totalLoopNum >= maxVer4LoopIdx(para) "Increase totalLoopNum\n$para" - - phi, ppi = blocks.phi, blocks.ppi - phi_toplevel, ppi_toplevel = blockstoplevel.phi, blockstoplevel.ppi - - @assert (PHr in phi) == false "PHi vertex is particle-hole irreducible, so that PHr channel is not allowed in $phi" - @assert (PPr in ppi) == false "PPi vertex is particle-particle irreducible, so that PPr channel is not allowed in $ppi" - @assert (PHr in phi_toplevel) == false "PHi vertex is particle-hole irreducible, so that PHr channel is not allowed in $phi_toplevel" - @assert (PPr in ppi_toplevel) == false "PPi vertex is particle-particle irreducible, so that PPr channel is not allowed in $ppi_toplevel" - - loopNum = para.innerLoopNum - # @assert loopNum >= 0 - - ver4df = DataFrame(response=Response[], type=AnalyticProperty[], extT=Tuple{Int,Int,Int,Int}[], diagram=Diagram{W}[]) - - if loopNum == 0 - if DirectOnly in para.filter - permutation = [Di,] - else - permutation = [Di, Ex] - end - bareVer4(ver4df, para, legK, permutation) - else # loopNum>0 - for c in chan - if c == Alli - continue - end - - partition = orderedPartition(loopNum - 1, 4, 0) - - for p in partition - if c == PHr || c == PHEr || c == PPr - bubble!(ver4df, para, legK, c, p, level, name, blocks, blockstoplevel, 1.0) - end - end - - if (NoBubble in para.filter) && (c == PHr || c == PHEr) - # add RPA bubble counter-diagram to remove the bubble - RPA_chain!(ver4df, para, legK, c, level, name, -1.0) - end - # println(bub) - end - # # TODO: add envolpe diagrams - end - # println(typeof(groups)) - ver4df = merge_vertex4(para, ver4df, name, legK, W) - @assert all(x -> x[1] == para.firstTauIdx, ver4df.extT) "not all extT[1] are equal to the first Tau index $(para.firstTauIdx)! $ver4df" - return ver4df -end - -function merge_vertex4(para, ver4df, name, legK, W) - diags = ver4df.diagram - @assert all(x -> x.id isa Ver4Id, diags) "not all id are Ver4Id! $diags" - @assert all(x -> x.id.extK β‰ˆ legK, diags) "not all extK are the same! $diags" - - # @assert isempty(diags) == false "got empty ver4! $chan with\n $para\n" - if isempty(ver4df) == false - ver4df = mergeby(W, ver4df, [:response, :type, :extT], name=name, - getid=g -> Ver4Id(para, g[1, :response], g[1, :type], k=legK, t=g[1, :extT]) #generate id from the dataframe - ) - end - return ver4df -end - -function bubble!(ver4df::DataFrame, para::DiagPara{W}, legK, chan::TwoBodyChannel, partition::Vector{Int}, level::Int, name::Symbol, - blocks::ParquetBlocks, blockstoplevel::ParquetBlocks, - extrafactor=1.0) where {W} - - TauNum = interactionTauNum(para) # maximum tau number for each bare interaction - oL, oG0, oR, oGx = partition[1], partition[2], partition[3], partition[4] - if isValidG(para.filter, oG0) == false || isValidG(para.filter, oGx) == false - # return diag - return - end - - #the first loop idx is the inner loop of the bubble! - LoopIdx = para.firstLoopIdx - idx, maxLoop = findFirstLoopIdx(partition, LoopIdx + 1) - LfirstLoopIdx, G0firstLoopIdx, RfirstLoopIdx, GxfirstLoopIdx = idx - @assert maxLoop == maxVer4LoopIdx(para) - - type = [Ver4Diag, GreenDiag, Ver4Diag, GreenDiag] - idx, maxTau = findFirstTauIdx(partition, type, para.firstTauIdx, TauNum) - LfirstTauIdx, G0firstTauIdx, RfirstTauIdx, GxfirstTauIdx = idx - @assert maxTau == maxVer4TauIdx(para) "Partition $partition with tauNum configuration $idx. maxTau = $maxTau, yet $(maxTauIdx(para)) is expected!" - - lPara = reconstruct(para, type=Ver4Diag, innerLoopNum=oL, firstLoopIdx=LfirstLoopIdx, firstTauIdx=LfirstTauIdx) - rPara = reconstruct(para, type=Ver4Diag, innerLoopNum=oR, firstLoopIdx=RfirstLoopIdx, firstTauIdx=RfirstTauIdx) - gxPara = reconstruct(para, type=GreenDiag, innerLoopNum=oGx, firstLoopIdx=GxfirstLoopIdx, firstTauIdx=GxfirstTauIdx) - g0Para = reconstruct(para, type=GreenDiag, innerLoopNum=oG0, firstLoopIdx=G0firstLoopIdx, firstTauIdx=G0firstTauIdx) - - phi, ppi, Ξ“4 = blocks.phi, blocks.ppi, blocks.Ξ“4 - phi_toplevel, ppi_toplevel, Ξ“4_toplevel = blockstoplevel.phi, blockstoplevel.ppi, blockstoplevel.Ξ“4 - if chan == PHr || chan == PHEr - Ξ“i = (level == 1) ? phi_toplevel : phi - Ξ“f = (level == 1) ? Ξ“4_toplevel : Ξ“4 - elseif chan == PPr - Ξ“i = (level == 1) ? ppi_toplevel : ppi - Ξ“f = (level == 1) ? Ξ“4_toplevel : Ξ“4 - else - error("chan $chan isn't implemented!") - end - - LLegK, K, RLegK, Kx = legBasis(chan, legK, LoopIdx) - # println(K, ", ", Kx) - - Lver = vertex4(lPara, LLegK, Ξ“i, true; level=level + 1, name=:Ξ“i, blocks=blocks) - isempty(Lver) && return - Rver = vertex4(rPara, RLegK, Ξ“f, true; level=level + 1, name=:Ξ“f, blocks=blocks) - isempty(Rver) && return - - ver8 = Dict{Any,Any}() - - for ldiag in Lver.diagram - for rdiag in Rver.diagram - extT, G0T, GxT = tauBasis(chan, ldiag.id.extT, rdiag.id.extT) - g0 = green(g0Para, K, G0T, true, name=:G0, blocks=blocks) - gx = green(gxPara, Kx, GxT, true, name=:Gx, blocks=blocks) - @assert g0 isa Diagram && gx isa Diagram - # append!(diag, bubble2diag(para, chan, ldiag, rdiag, legK, g0, gx, extrafactor)) - bubble2diag!(ver8, para, chan, ldiag, rdiag, legK, g0, gx, extrafactor) - end - end - - for key in keys(ver8) - G0T, GxT, extT, Vresponse, vtype = key - g0 = green(g0Para, K, G0T, true, name=:G0, blocks=blocks) - gx = green(gxPara, Kx, GxT, true, name=:Gx, blocks=blocks) - @assert g0 isa Diagram && gx isa Diagram - id = Ver4Id(para, Vresponse, vtype, k=legK, t=extT, chan=chan) - if length(ver8[key]) == 1 - diag = Diagram{W}(id, Prod(), [ver8[key][1], g0, gx], factor=1.0) - push!(ver4df, (response=Vresponse, type=vtype, extT=extT, diagram=diag)) - elseif isempty(ver8[key]) - continue - else - diag = Diagram{W}(GenericId(para), Sum(), ver8[key], factor=1.0) - ver4diag = Diagram{W}(id, Prod(), [diag, g0, gx], factor=1.0) - push!(ver4df, (response=Vresponse, type=vtype, extT=extT, diagram=ver4diag)) - end - # push!(ver4df, (response=Vresponse, type=vtype, extT=extT, diagram=diag)) - end - - return -end - -function RPA_chain!(ver4df::DataFrame, para::DiagPara, legK, chan::TwoBodyChannel, level::Int, name::Symbol, extrafactor=1.0) - if chan != PHr && chan != PHEr - return - end - new_filter = union(union(para.filter, Girreducible), DirectOnly) - para_rpa = reconstruct(para, filter=new_filter) - blocks = ParquetBlocks(; phi=[], ppi=[], Ξ“4=[PHr,]) - bubble!(ver4df, para_rpa, legK, chan, [0, 0, para.innerLoopNum - 1, 0], level, Symbol("$(name)_RPA_CT"), blocks, blocks, extrafactor) - return -end - -function bubble2diag!(ver8, para::DiagPara{W}, chan::TwoBodyChannel, ldiag, rdiag, extK, g0, gx, extrafactor) where {W} - lid, rid = ldiag.id, rdiag.id - ln, rn = lid.response, rid.response - lo, ro = lid.para.innerLoopNum, rid.para.innerLoopNum - vtype = typeMap(lid.type, rid.type) - - extT, G0T, GxT = tauBasis(chan, lid.extT, rid.extT) - Factor = factor(para, chan) * extrafactor - spin(response) = (response == UpUp ? "↑↑" : "↑↓") - - function add(Lresponse::Response, Rresponse::Response, Vresponse::Response, factor=1.0) - key = (G0T, GxT, extT, Vresponse, vtype) - if (key in keys(ver8)) == false - ver8[key] = [] - end - - if ln == Lresponse && rn == Rresponse - nodeName = Symbol("$(spin(Lresponse))x$(spin(Rresponse)) β†’ $chan,") - id = GenericId(para) - # diag = Diagram{W}(id, Prod(), [g0, gx, ldiag, rdiag], factor=factor * Factor, name=nodeName) - diag = Diagram{W}(id, Prod(), [ldiag, rdiag], factor=factor * Factor, name=nodeName) - push!(ver8[key], diag) - # push!(ver4df, (response=Vresponse, type=vtype, extT=extT, diagram=diag)) - # push!(diag, Diagram(id, Prod(), [g0, gx, ldiag, rdiag], factor=factor * Factor, name=nodeName)) - end - end - - if chan == PHr - add(UpUp, UpUp, UpUp, 1.0) - add(UpDown, UpDown, UpUp, 1.0) - add(UpUp, UpDown, UpDown, 1.0) - add(UpDown, UpUp, UpDown, 1.0) - elseif chan == PHEr - add(UpUp, UpUp, UpUp, 1.0) - add(UpDown, UpDown, UpUp, 1.0) - - # for the spin configuration (lin, lout, rin, rout) = (up, up, down, down), the spins of the internal G pair must be (up, down) - # which gives only one spin configuration for the left and the right vertex (up, down, down, up) and (up, down, down, up) - # Due to the SU(2) symmetry, v(up, down, down, up) = v(up, up, up, up) - v(up, up, down, down) = v_uu - v_ud - # the total contribution is (vl_uu-vl_ud)*(vr_uu-vr_ud) = vl_uu*vr_uu + vl_ud*vr_ud - vl_uu*vr_ud - vl_ud*vr_uu - add(UpUp, UpUp, UpDown, 1.0) - add(UpDown, UpDown, UpDown, 1.0) - #! the sign here is from the spin symmetry, not from the fermionic statistics - add(UpUp, UpDown, UpDown, -1.0) - #! the sign here is from the spin symmetry, not from the fermionic statistics - add(UpDown, UpUp, UpDown, -1.0) - elseif chan == PPr - add(UpUp, UpUp, UpUp, 1.0) - - # for the spin configuration (lin, lout, rin, rout) = (up, up, down, down), the spins of the internal G pair should be either (up, down) or (down, up) - # which gives two spin configurations for the left and the right vertex: one is (up, up, down, down) and (up, down, down, up); another is (up, down, down, up) and (up, up, down, down) - # Due to the SU(2) symmetry, v(up, down, down, up) = v(up, up, up, up) - v(up, up, down, down) = v_uu - v_ud - # the total contribution is (vl_uu-vl_ud)*vr_ud + vl_ud*(vr_uu-vr_ud) = vl_uu*vr_ud + vl_ud*vr_uu - 2*vl_ud*vr_ud - add(UpDown, UpDown, UpDown, -2.0) #! the sign here is from the spin symmetry, not from the fermionic statistics - add(UpUp, UpDown, UpDown, 1.0) - add(UpDown, UpUp, UpDown, 1.0) - else - error("chan $chan isn't implemented!") - end - - # return diag - return -end - -function _bare(para::DiagPara{W}, diex::Vector{Permutation}, response::Response, type::AnalyticProperty, - _diex::Permutation, _innerT::Tuple{Int,Int}, _q, _factor=1.0) where {W} - @assert _diex == Di || _diex == Ex - - # there is an overall sign coming from Taylor expansion of exp(-S) depsite the statistics - if _diex == Di - sign = -1.0 - elseif _diex == Ex - sign = para.isFermi ? 1.0 : -1.0 - else - error("not implemented!") - end - - if notProper(para, _q) == false && _diex in diex - #create new bare ver4 only if _diex is required in the diex table - vid = BareInteractionId(para, response, type, k=_q, t=_innerT, permu=_diex) - return Diagram{W}(vid, factor=sign * _factor) - else - return nothing - end -end - -function _pushbarever4!(para::DiagPara{W}, nodes::DataFrame, response::Response, type::AnalyticProperty, _extT, legK, - vd::Union{Nothing,Diagram{W}}, ve::Union{Nothing,Diagram{W}}) where {W} - - if isnothing(vd) == false - id_di = Ver4Id(para, response, type, k=legK, t=_extT[DI]) - push!(nodes, (response=response, type=type, extT=_extT[DI], diagram=Diagram{W}(id_di, Sum(), [vd,]))) - end - - if isnothing(ve) == false - id_ex = Ver4Id(para, response, type, k=legK, t=_extT[EX]) - push!(nodes, (response=response, type=type, extT=_extT[EX], diagram=Diagram{W}(id_ex, Sum(), [ve,]))) - end -end - -function _pushbarever4_with_response!(para::DiagPara, nodes::DataFrame, response::Response, type::AnalyticProperty, - legK, q, diex::Vector{Permutation}, _extT, _innerT) - # println(_extT, " and inner: ", _innerT) - if response == UpUp - vd = _bare(para, diex, response, type, Di, _innerT[DI], q[DI]) - ve = _bare(para, diex, response, type, Ex, _innerT[EX], q[EX]) - _pushbarever4!(para, nodes, UpUp, type, _extT, legK, vd, ve) - elseif response == UpDown - vd = _bare(para, diex, UpDown, type, Di, _innerT[DI], q[DI]) - ve = nothing - _pushbarever4!(para, nodes, UpDown, type, _extT, legK, vd, ve) - elseif response == ChargeCharge - # UpUp channel - vuud = _bare(para, diex, ChargeCharge, type, Di, _innerT[DI], q[DI]) - vuue = _bare(para, diex, ChargeCharge, type, Ex, _innerT[EX], q[EX]) - _pushbarever4!(para, nodes, UpUp, type, _extT, legK, vuud, vuue) - - # UpDown channel - vupd = _bare(para, diex, ChargeCharge, type, Di, _innerT[DI], q[DI]) - vupe = nothing - # UpDown, exchange channel doesn't exist for the charge-charge interaction - _pushbarever4!(para, nodes, UpDown, type, _extT, legK, vupd, vupe) - elseif response == SpinSpin - # see manual/interaction.md for more details - - # UpUp channel - vuud = _bare(para, diex, SpinSpin, type, Di, _innerT[DI], q[DI]) - vuue = _bare(para, diex, SpinSpin, type, Ex, _innerT[EX], q[EX]) - _pushbarever4!(para, nodes, UpUp, type, _extT, legK, vuud, vuue) - - # UpDown channel - vupd = _bare(para, diex, SpinSpin, type, Di, _innerT[DI], q[DI], -1.0) - vupe = _bare(para, diex, SpinSpin, type, Ex, _innerT[EX], q[EX], 2.0) - _pushbarever4!(para, nodes, UpDown, type, _extT, legK, vupd, vupe) - else - error("not implemented!") - end -end - -function bareVer4(nodes::DataFrame, para::DiagPara, legK, diex::Vector{Permutation}=[Di, Ex], leftalign=true) - # @assert para.type == Ver4Diag - - KinL, KoutL, KinR = legK[1], legK[2], legK[3] - t0 = para.firstTauIdx - - q = [KinL - KoutL, KinR - KoutL] - - """ - extT is a Tuple{Int, Int, Int, Int} of four tau indices of the external legs. - innerT is a Tuple{Int, Int} of two tau indices of the bare interaction. - The innerT doesn't have to be the same of extT. Because the instant interaction is - independent of the tau variables, this gives a freedom how to choose the actual tau variables. - See Line 346 for more details. - """ - if para.hasTau - extT_ins = [(t0, t0, t0, t0), (t0, t0, t0, t0)] - extT_ins_rightalign = [(t0 + 1, t0 + 1, t0 + 1, t0 + 1), (t0 + 1, t0 + 1, t0 + 1, t0 + 1)] - extT_dyn = [(t0, t0, t0 + 1, t0 + 1), (t0, t0 + 1, t0 + 1, t0)] - innerT_ins = [(1, 1), (1, 1)] - innerT_dyn = [(t0, t0 + 1), (t0, t0 + 1)] - else - extT_ins = [(t0, t0, t0, t0), (t0, t0, t0, t0)] - extT_dyn = extT_ins - innerT_ins = [(1, 1), (1, 1)] - innerT_dyn = innerT_ins - end - - for interaction in para.interaction - response = interaction.response - typeVec = interaction.type - - if Instant ∈ typeVec && Dynamic βˆ‰ typeVec - _pushbarever4_with_response!(para, nodes, response, Instant, legK, q, diex, extT_ins, innerT_ins) - elseif Instant βˆ‰ typeVec && Dynamic ∈ typeVec - _pushbarever4_with_response!(para, nodes, response, Dynamic, legK, q, diex, extT_dyn, innerT_dyn) - elseif Instant ∈ typeVec && Dynamic ∈ typeVec - #if hasTau, instant interaction has an additional fake tau variable, making it similar to the dynamic interaction - if leftalign - _pushbarever4_with_response!(para, nodes, response, Instant, legK, q, diex, extT_ins, innerT_dyn) - else - _pushbarever4_with_response!(para, nodes, response, Instant, legK, q, diex, extT_ins_rightalign, innerT_dyn) - end - _pushbarever4_with_response!(para, nodes, response, Dynamic, legK, q, diex, extT_dyn, innerT_dyn) - end - - # if D_Instant ∈ typeVec && D_Dynamic βˆ‰ typeVec - # addresponse!(response, D_Instant, extT_ins, innerT_ins) - # elseif D_Instant βˆ‰ typeVec && D_Dynamic ∈ typeVec - # addresponse!(response, D_Dynamic, extT_dyn, innerT_dyn) - # elseif D_Instant ∈ typeVec && D_Dynamic ∈ typeVec - # #if hasTau, instant interaction has an additional fake tau variable, making it similar to the dynamic interaction - # addresponse!(response, D_Instant, extT_ins, innerT_dyn) - # addresponse!(response, D_Dynamic, extT_dyn, innerT_dyn) - # end - end - - return nodes -end - -######################### utility functions ############################ -maxVer4TauIdx(para) = (para.innerLoopNum + 1) * interactionTauNum(para) + para.firstTauIdx - 1 -maxVer4LoopIdx(para) = para.firstLoopIdx + para.innerLoopNum - 1 - -function legBasis(chan::TwoBodyChannel, legK, loopIdx::Int) - KinL, KoutL, KinR, KoutR = legK[1], legK[2], legK[3], legK[4] - K = zero(KinL) - K[loopIdx] = 1 - if chan == PHr - Kx = KoutL + K - KinL - LLegK = [KinL, KoutL, Kx, K] - RLegK = [K, Kx, KinR, KoutR] - elseif chan == PHEr - Kx = KoutR + K - KinL - LLegK = [KinL, KoutR, Kx, K] - RLegK = [K, Kx, KinR, KoutL] - elseif chan == PPr - Kx = KinL + KinR - K - LLegK = [KinL, Kx, KinR, K] - RLegK = [K, KoutL, Kx, KoutR] - else - error("not implemented!") - end - - # check conservation and momentum assignment - @assert LLegK[INL] β‰ˆ KinL - @assert LLegK[INL] + LLegK[INR] β‰ˆ LLegK[OUTL] + LLegK[OUTR] - @assert RLegK[INL] + RLegK[INR] β‰ˆ RLegK[OUTL] + RLegK[OUTR] - - return LLegK, K, RLegK, Kx -end - -function tauBasis(chan::TwoBodyChannel, LvT, RvT) - G0T = (LvT[OUTR], RvT[INL]) - if chan == PHr - extT = (LvT[INL], LvT[OUTL], RvT[INR], RvT[OUTR]) - GxT = (RvT[OUTL], LvT[INR]) - elseif chan == PHEr - extT = (LvT[INL], RvT[OUTR], RvT[INR], LvT[OUTL]) - GxT = (RvT[OUTL], LvT[INR]) - elseif chan == PPr - extT = (LvT[INL], RvT[OUTL], LvT[INR], RvT[OUTR]) - GxT = (LvT[OUTL], RvT[INR]) - else - error("not implemented!") - end - - # make sure all tidx are used once and only once - t1 = sort(vcat(collect(G0T), collect(GxT), collect(extT))) - t2 = sort(vcat(collect(LvT), collect(RvT))) - @assert t1 == t2 "chan $(chan): G0=$G0T, Gx=$GxT, external=$extT don't match with Lver4 $LvT and Rver4 $RvT" - @assert extT[INL] == LvT[INL] - return extT, G0T, GxT -end - - -function factor(para::DiagPara, chan::TwoBodyChannel) - # Factor = SymFactor[Int(chan)] / (2Ο€)^para.loopDim - Factor = SymFactor[Int(chan)] - if para.isFermi == false - Factor = abs(Factor) - end - return Factor -end - -function typeMap(ltype::AnalyticProperty, rtype::AnalyticProperty) - return Dynamic - # if (ltype == Instant || ltype == Dynamic) && (rtype == Instant || rtype == Dynamic) - # return Dynamic - # elseif (ltype == D_Instant || ltype == D_Dynamic) && (rtype == Instant || rtype == Dynamic) - # return D_Dynamic - # elseif (ltype == Instant || ltype == Dynamic) && (rtype == D_Instant || rtype == D_Dynamic) - # return D_Dynamic - # else - # return nothing - # end -end \ No newline at end of file diff --git a/archived/test/common.jl b/archived/test/common.jl deleted file mode 100644 index c6a84b44..00000000 --- a/archived/test/common.jl +++ /dev/null @@ -1,22 +0,0 @@ -@testset "Parameter" begin - p = DiagParaF64(type=Ver4Diag, innerLoopNum=1) - q = DiagParaF64(type=Ver4Diag, innerLoopNum=2) - a = DiagParaF64(type=Ver4Diag, innerLoopNum=2) - - @test p != q - @test q == a - - aa = reconstruct(a, transferLoop=[0.0, 0.0, 0.0]) - @test a != aa - - # reconstruct with the same type but different interaction - aaa = reconstruct(a, interaction=[]) - @test a != aaa - - # reconstruct with different diagram type leads to different parameter - #reconstructed DiagPara uses the old parameters such as firstLoopIdx, totalLoopNum etc., which are different between types - s = reconstruct(a, type=SigmaDiag) - ss = DiagParaF64(type=SigmaDiag, innerLoopNum=2) - @test s != ss - -end \ No newline at end of file diff --git a/archived/test/diagram_tree.jl b/archived/test/diagram_tree.jl deleted file mode 100644 index f55982de..00000000 --- a/archived/test/diagram_tree.jl +++ /dev/null @@ -1,246 +0,0 @@ -@testset "Diagram" begin - # Diagram = DiagTreeNew.Diagram - # DiagramId = DiagTreeNew.DiagramId - # add_subdiagram! = DiagTreeNew.add_subdiagram! - - struct ID <: DiagramId - uid::Int - end - Base.show(io::IO, d::ID) = print(io, d.uid) - # Base.isequal(a::ID, b::ID) = (a.index == b.index) - # Base.Dict(d::ID) = Dict(:id => d.index) - - DiagTree.uidreset() - - W = Int - ll = Diagram{W}(ID(3)) - l = Diagram{W}(ID(1), Sum(), [ll,]) - r = Diagram{W}(ID(2)) - root = Diagram{W}(ID(0), Sum(), [l, r]) - print_tree(root) - """ - 4 : 0=0=⨁ (2, 3) - β”œβ”€ 2 : 1=0=⨁ (1) - β”‚ └─ 1 : 3=0 - └─ 3 : 2=0 - """ - - collect(PostOrderDFS(root)) - @test [node.id.uid for node in PostOrderDFS(root)] == [3, 1, 2, 0] - @test [node.id.uid for node in PreOrderDFS(root)] == [0, 1, 3, 2] - @test [node.id.uid for node in Leaves(root)] == [3, 2] - - # eval(d::ID, vargs...) = d.uid - @test DiagTree.eval!(root; eval=(d -> d.uid)) == sum(node.id.uid for node in Leaves(root)) - - print_tree(root) - # DiagTreeNew.plot_tree(root) - - println(toDataFrame([root,])) -end - -function getdiagram(spin=2.0, D=3, Nk=4, Nt=2) - """ - k1-k3 k2+k3 - | | - t1.L ↑ t1.L t2.L ↑ t2.L - |-------------->----------| - | | k3+k4 | | - | v | | v | - | | k4 | | - |--------------<----------| - t1.L ↑ t1.L t2.L ↑ t2.L - | | - k1 k2 - """ - - DiagTree.uidreset() - # We only consider the direct part of the above diagram - - paraG = DiagParaF64(type=GreenDiag, - innerLoopNum=0, totalLoopNum=Nk, - hasTau=true, totalTauNum=Nt) - paraV = paraG - - # #construct the propagator table - gK = [[0.0, 0.0, 1.0, 1.0], [0.0, 0.0, 0.0, 1.0]] - gT = [(1, 2), (2, 1)] - g = [Diagram{Float64}(BareGreenId(paraG, k=gK[i], t=gT[i]), name=:G) for i in 1:2] - - vdK = [[0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 1.0, 0.0]] - # vdT = [[1, 1], [2, 2]] - vd = [Diagram{Float64}(BareInteractionId(paraV, ChargeCharge, k=vdK[i], permu=Di), name=:Vd) for i in 1:2] - - veK = [[1, 0, -1, -1], [0, 1, 0, -1]] - # veT = [[1, 1], [2, 2]] - ve = [Diagram{Float64}(BareInteractionId(paraV, ChargeCharge, k=veK[i], permu=Ex), name=:Ve) for i in 1:2] - - Id = GenericId(paraV) - # contruct the tree - ggn = Diagram{Float64}(Id, Prod(), [g[1], g[2]]) - vdd = Diagram{Float64}(Id, Prod(), [vd[1], vd[2]], factor=spin) - vde = Diagram{Float64}(Id, Prod(), [vd[1], ve[2]], factor=-1.0) - ved = Diagram{Float64}(Id, Prod(), [ve[1], vd[2]], factor=-1.0) - vsum = Diagram{Float64}(Id, Sum(), [vdd, vde, ved]) - root = Diagram{Float64}(Id, Prod(), [vsum, ggn], factor=1 / (2Ο€)^D, name=:root) - - return root, gK, gT, vdK, veK -end - -@testset "Generic Diagrams" begin - - DiagTree.uidreset() - # We only consider the direct part of the above diagram - spin = 1.0 - D = 3 - kF, Ξ², mass2 = 1.919, 0.5, 1.0 - Nk, Nt = 4, 2 - - root, gK, gT, vdK, veK = getdiagram(spin, D, Nk, Nt) - - #optimize the diagram - DiagTree.optimize!([root,]) - - # autodiff - droot_dg = DiagTree.derivative([root,], BareGreenId)[1] - droot_dv = DiagTree.derivative([root,], BareInteractionId)[1] - # plot_tree(droot_dg) - - DiagTree.eval!(root; eval=(x -> 1.0)) - factor = 1 / (2Ο€)^D - @test root.weight β‰ˆ (-2 + spin) * factor - - DiagTree.eval!(droot_dg; eval=(x -> 1.0)) - @test droot_dg.weight β‰ˆ (-2 + spin) * 2 * factor - - DiagTree.eval!(droot_dv; eval=(x -> 1.0)) - @test droot_dv.weight β‰ˆ (-2 + spin) * 2 * factor - - # #more sophisticated test of the weight evaluation - varK = rand(D, Nk) - varT = [rand() * Ξ² for t in 1:Nt] - - function evalG(K, Ο„Basis, varT, order=0) - Ο΅ = dot(K, K) / 2 - kF^2 - Ο„ = varT[Ο„Basis[2]] - varT[Ο„Basis[1]] - if order == 0 - return Spectral.kernelFermiT(Ο„, Ο΅, Ξ²) - elseif order == 1 - return Spectral.kernelFermiT(Ο„, Ο΅, Ξ²) * 3.1415 - else - error("not implemented!") - end - end - - function evalV(K, order=0) - if order == 0 - return 8Ο€ / (dot(K, K) + mass2) - elseif order == 1 - return 8Ο€ / (dot(K, K) + mass2) * 3.1415 - else - error("not implemented!") - end - end - - # # getK(basis, varK) = sum([basis[i] * K for (i, K) in enumerate(varK)]) - getK(basis, varK) = varK * basis - - eval(id::BareGreenId, varK, varT) = evalG(getK(id.extK, varK), id.extT, varT, id.order[1]) - eval(id::BareInteractionId, varK, varT) = evalV(getK(id.extK, varK), id.order[2]) - - gw = [evalG(getK(gK[i], varK), gT[i], varT) for i = 1:2] - vdw = [evalV(getK(vdK[i], varK)) for i = 1:2] - vew = [evalV(getK(veK[i], varK)) for i = 1:2] - - dgw = [evalG(getK(gK[i], varK), gT[i], varT, 1) for i = 1:2] - dvdw = [evalV(getK(vdK[i], varK), 1) for i = 1:2] - dvew = [evalV(getK(veK[i], varK), 1) for i = 1:2] - - Vweight = spin * vdw[1] * vdw[2] - vdw[1] * vew[2] - vew[1] * vdw[2] - Gweight = gw[1] * gw[2] - Weight = Gweight * Vweight / (2Ο€)^D - - dVweight = spin * (dvdw[1] * vdw[2] + vdw[1] * dvdw[2]) - - (dvdw[1] * vew[2] + vdw[1] * dvew[2]) - - (dvew[1] * vdw[2] + vew[1] * dvdw[2]) - - dGweight = dgw[1] * gw[2] + gw[1] * dgw[2] - dWeight_dg = dGweight * Vweight / (2Ο€)^D - dWeight_dv = Gweight * dVweight / (2Ο€)^D - - # print_tree(root) - DiagTree.eval!(root, varK, varT; eval=eval) - @test root.weight β‰ˆ Weight - - DiagTree.eval!(droot_dg, varK, varT; eval=eval) - @test droot_dg.weight β‰ˆ dWeight_dg - - DiagTree.eval!(droot_dv, varK, varT; eval=eval) - @test droot_dv.weight β‰ˆ dWeight_dv - - ############### test diagram optimization ################# - uniqueG, uniqueInt = DiagTree.removeDuplicatedLeaves!([root,], verbose=1) - @test length(uniqueG) == 2 - @test length(uniqueInt) == 3 - DiagTree.eval!(root, varK, varT; eval=eval) - @test root.weight β‰ˆ Weight -end - -@testset "dataframe" begin - DiagTree.uidreset() - # We only consider the direct part of the above diagram - spin = 2.0 - D = 3 - kF, Ξ², mass2 = 1.919, 0.5, 1.0 - Nk, Nt = 4, 2 - - root, gK, gT, vdK, veK = getdiagram(spin, D, Nk, Nt) - diags = root.subdiagram - diags = collect(Leaves(root)) - df1 = DiagTree.toDataFrame(diags) - df2 = DiagTree.toDataFrame(diags, :extT) - s1 = size(df1) - s2 = size(df2) - @assert s1[1] == s2[1] - @assert s1[2] == s2[2] - 1 - - d = mergeby(diags) #should return a vector of a single diagram - @assert length(d) == 1 -end - -@testset "optimize" begin - DiagTree.uidreset() - - W = Int - lll = Diagram{W}(ID(5)) - ll = Diagram{W}(ID(3), Prod(), [lll,]) - l = Diagram{W}(ID(1), Sum(), [ll,]) - r = Diagram{W}(ID(2)) - root = Diagram{W}(ID(0), Sum(), [l, r]) - # print_tree(root) - """ - 5 : 0=0=⨁ (3, 4) - β”œβ”€ 3 : 1=0=⨁ (2) - β”‚ └─ 2 : 3=0=Ⓧ (1) - β”‚ └─ 1 : 5=0 - └─ 4 : 2=0 - """ - - #remove the 2, which only has one child - DiagTree.removeOneChildParent!([root,]) - """ - 4 : 0=0=⨁ (1, 3) - β”œβ”€ 1 : 3=0 - └─ 3 : 2=0 - """ - - # print_tree(root) - - @test root.subdiagram[1].hash == 1 - # print_tree(root) - - # root, gK, gT, vdK, veK = getdiagram() - # uniqueG, uniqueInt = DiagTree.removeDuplicatedLeaves!(root, verbose = 1) - # @test length(uniqueG) == 2 - # @test length(uniqueInt) == 3 -end \ No newline at end of file diff --git a/archived/test/expression_tree.jl b/archived/test/expression_tree.jl deleted file mode 100644 index 2d2b3271..00000000 --- a/archived/test/expression_tree.jl +++ /dev/null @@ -1,150 +0,0 @@ -@testset "LoopPool" begin - dim, N = 3, 4 - loopPool = ExprTree.LoopPool(:K, dim, N, Float64) - 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 = ExprTree.append(loopPool, basis1) - idx2 = ExprTree.append(loopPool, basis2) - idx3 = ExprTree.append(loopPool, basis2) - idx4 = ExprTree.append(loopPool, basis1) - idx5 = ExprTree.append(loopPool, basis3) - @test length(loopPool) == 3 - @test idx1 == idx4 - @test idx2 == idx3 - - varK = rand(dim, N) - ExprTree.update(loopPool, varK) - @test ExprTree.current(loopPool, 1) β‰ˆ varK * basis1 - @test ExprTree.current(loopPool, 2) β‰ˆ varK * basis2 - @test ExprTree.current(loopPool, 3) β‰ˆ varK * basis3 - -end - -# @testset "CachedPool" begin -# objType, weightType = Int, Float64 -# pool = ExprTree.CachedPool(:P, objType, weightType) -# idx1 = ExprTree.append(pool, 1) -# idx2 = ExprTree.append(pool, 2) -# idx3 = ExprTree.append(pool, 2) -# idx4 = ExprTree.append(pool, 1) -# @test length(pool) == 2 -# @test idx1 == idx4 -# @test idx2 == idx3 -# end - -@testset "Generic Diagrams" begin - - """ - k1-k3 k2+k3 - | | - t1.L ↑ t1.L t2.L ↑ t2.L - |-------------->----------| - | | k3+k4 | | - | v | | v | - | | k4 | | - |--------------<----------| - t1.L ↑ t1.L t2.L ↑ t2.L - | | - k1 k2 - """ - # We only consider the direct part of the above diagram - Gtype, Wtype = 1, 2 - spin = 2.0 - D = 3 - kF, Ξ², mass2 = 1.919, 0.5, 1.0 - - # varK = [rand(D) for i = 1:4] #k1, k2, k3, k4 - - varK = rand(D, 4) - varT = [rand() * Ξ², rand() * Ξ²] - - K0 = [0.0, 0.0, 0.0] - T0 = 0.0 - - calcK(para, basis) = sum([para[i] .* basis[i] for i = 1:length(para)]) - calcT(para, basis) = para[basis[2]] - para[basis[1]] - - gorder, vorder = 0, 1 - - weightType = Float64 - - # function LoopPool(name::Symbol, dim::Int, N::Int, type::DataType) - MomPool = ExprTree.LoopPool(:K, D, 4) - - diag = ExprTree.ExpressionTree(loopBasis=MomPool, nodePara=Int, weight=weightType) - - # #construct the propagator table - gK = [[0.0, 0.0, 1.0, 1.0], [0.0, 0.0, 0.0, 1.0]] - gT = [(1, 2), (2, 1)] - g = [ExprTree.addpropagator!(diag, :G; site=gT[i], loop=gK[i], para=1) for i = 1:2] - - vdK = [[0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 1.0, 0.0]] - vdT = [[1, 1], [2, 2]] - vd = [ExprTree.addpropagator!(diag, :Vd; loop=vdK[i], para=2) for i = 1:2] - - veK = [[1, 0, -1, -1], [0, 1, 0, -1]] - veT = [[1, 1], [2, 2]] - ve = [ExprTree.addpropagator!(diag, :Ve; loop=veK[i], para=2) for i = 1:2] - # ve = [ExprTree.addPropagator!(diag, Wtype, 1, veK[i], veT[i], Wsym)[1] for i = 1:2] - # # W order is 1 - - # # contruct the tree - MUL, ADD = ExprTree.MUL, ExprTree.ADD - ggn = ExprTree.addnode!(diag, MUL, :gxg, [g[1], g[2]], 1.0, para=0) - vdd = ExprTree.addnode!(diag, MUL, :dxd, [vd[1], vd[2]], spin, para=0) - vde = ExprTree.addnode!(diag, MUL, :dxe, [vd[1], ve[2]], -1.0, para=0) - ved = ExprTree.addnode!(diag, MUL, :exd, [ve[1], vd[2]], -1.0, para=0) - vsum = ExprTree.addnode!(diag, ADD, :sum, [vdd, vde, ved], 1.0, para=0) - root = ExprTree.addnode!(diag, MUL, :root, [ggn, vsum], 1.0, para=0) - push!(diag.root, root) - ExprTree.initialize!(diag.node) - - # printBasisPool(diag) - # printPropagator(diag) - # ExprTree.printNodes(diag) - # ExprTree.showTree(diag, diag.root[1]) - - # #make sure the total number of diagrams are correct - let - DiagTree.eval(para, K, Tbasis, varT) = 1.0 - ExprTree.evalKT!(diag, varK, varT) - @test diag[1] β‰ˆ -2 + 1 * spin - end - - # #more sophisticated test of the weight evaluation - let - function evalG(K, Ο„Basis, varT) - Ο΅ = dot(K, K) / 2 - kF^2 - Ο„ = varT[Ο„Basis[2]] - varT[Ο„Basis[1]] - return Spectral.kernelFermiT(Ο„, Ο΅, Ξ²) - end - - evalV(K) = 8Ο€ / (dot(K, K) + mass2) - - function DiagTree.eval(para, K, Tbasis, varT) - if para[1] == 1 - return evalG(K, Tbasis, varT) - elseif para[1] == 2 - return evalV(K) - else - error("not implemented") - end - end - - # getK(basis, varK) = sum([basis[i] * K for (i, K) in enumerate(varK)]) - getK(basis, varK) = varK * basis - - gw = [evalG(getK(gK[i], varK), gT[i], varT) for i = 1:2] - vdw = [evalV(getK(vdK[i], varK)) for i = 1:2] - vew = [evalV(getK(veK[i], varK)) for i = 1:2] - - Vweight = spin * vdw[1] * vdw[2] - vdw[1] * vew[2] - vew[1] * vdw[2] - Weight = gw[1] * gw[2] * Vweight - - # println(ExprTree.printPropagator(diag)) - ExprTree.evalKT!(diag, varK, varT) - @test diag[1] β‰ˆ Weight - end - -end \ No newline at end of file diff --git a/archived/test/parquet_builder.jl b/archived/test/parquet_builder.jl deleted file mode 100644 index c1ee383e..00000000 --- a/archived/test/parquet_builder.jl +++ /dev/null @@ -1,521 +0,0 @@ -@testset "Partition" begin - p = Parquet.orderedPartition(5, 2) - expect = [[4, 1], [1, 4], [2, 3], [3, 2]] - @test Set(p) == Set(expect) - - p = Parquet.orderedPartition(3, 2, 0) - expect = [[3, 0], [0, 3], [1, 2], [2, 1]] - @test Set(p) == Set(expect) -end - -@testset "FindFirstIdx" begin - function testLoopIdx(partition, firstidx, expected) - firstLoopIdx, total = Parquet.findFirstLoopIdx(partition, firstidx) - @test firstLoopIdx == expected - totalExp = sum(partition) + firstidx - 1 - @test total == totalExp - end - - testLoopIdx([1, 1, 2, 1], 1, [1, 2, 3, 5]) - testLoopIdx([1, 1, 2, 1], 0, [0, 1, 2, 4]) - testLoopIdx([1, 0, 2, 0], 1, [1, 2, 2, 4]) - testLoopIdx([1,], 1, [1,]) - - function testTauIdx(partition, isG, firstidx, tauNum, expected) - firstIdx, total = Parquet.findFirstTauIdx(partition, isG, firstidx, tauNum) - @test firstIdx == expected - end - tauNum = 1 - # isG = [false, true, false, true] - isG = [Ver4Diag, GreenDiag, Ver4Diag, GreenDiag] - testTauIdx([1, 1, 2, 1], isG, 1, tauNum, [1, 3, 4, 7]) - testTauIdx([1, 1, 2, 1], isG, 0, tauNum, [0, 2, 3, 6]) - testTauIdx([1, 0, 2, 0], isG, 1, tauNum, [1, 3, 3, 6]) - -end - -@testset "Filter" begin - - # for G irreducible diagrams, only 0-loop G is allowed - @test Parquet.isValidG([Girreducible,], 0) == true - @test Parquet.isValidG([Girreducible,], 1) == false - @test Parquet.isValidG([Girreducible,], 2) == false - - # for Fock irreducible diagrams, only 0-loop or 2, 3, 4...-loop G is allowed - @test Parquet.isValidG([NoFock,], 0) == true - @test Parquet.isValidG([NoFock,], 1) == true - #one-loop G diagram becomes invalid only if both Hartree and Fock are filtered - @test Parquet.isValidG([NoFock, NoHartree], 1) == false - @test Parquet.isValidG([NoFock, NoHartree], 2) == true - - # for G irreducible diagrams, no sigma subdiagram is allowed - @test Parquet.isValidSigma([Girreducible,], 0, true) == false - @test Parquet.isValidSigma([Girreducible,], 1, true) == false - @test Parquet.isValidSigma([Girreducible,], 2, true) == false - - @test Parquet.isValidSigma([Girreducible,], 0, false) == false - @test Parquet.isValidSigma([Girreducible,], 1, false) == true - @test Parquet.isValidSigma([Girreducible,], 2, false) == true - - # for Fock irreducible diagrams, no Fock sigma subdiagram is allowed - @test Parquet.isValidSigma([NoFock,], 0, true) == false - #one-loop sigma diagram can be either Hartree or Fock diagram - #one-loop sigma sub-diagram becomes invalid only if both Hartree and Fock are filtered - @test Parquet.isValidSigma([NoFock,], 1, true) == true - @test Parquet.isValidSigma([NoFock, NoHartree], 1, true) == false - @test Parquet.isValidSigma([NoFock, NoHartree], 2, true) == true - - @test Parquet.isValidSigma([NoFock,], 0, false) == false - @test Parquet.isValidSigma([NoFock,], 1, false) == true - @test Parquet.isValidSigma([NoFock, NoHartree], 1, false) == true - @test Parquet.isValidSigma([NoFock,], 2, false) == true -end - -function evalG(K, Ο„in, Ο„out) - # println(Ο„Basis, ", ", varT) - kF, Ξ² = 1.0, 1.0 - Ο΅ = dot(K, K) / 2 - kF^2 - Ο„ = Ο„out - Ο„in - if Ο„ β‰ˆ 0.0 - return Spectral.kernelFermiT(-1e-8, Ο΅, Ξ²) - else - return Spectral.kernelFermiT(Ο„, Ο΅, Ξ²) - end -end -evalV(K) = 8Ο€ / (dot(K, K) + 1) - -evalGfixK(K, Ο„in, Ο„out) = evalG(zero(K), Ο„in, Ο„out) -evalVfixK(K) = 1.0 - -evalFakeG(K, Ο„in, Ο„out) = 1.0 -evalFakeV(K) = 1.0 - -################## api for expression tree ############################## -evalPropagator(id::BareGreenId, K, extT, varT) = evalG(K, varT[extT[1]], varT[extT[2]]) -evalPropagator(id::BareInteractionId, K, extT, varT) = evalV(K) -evalPropagatorfixK(id::BareGreenId, K, extT, varT) = evalGfixK(K, varT[extT[1]], varT[extT[2]]) -evalPropagatorfixK(id::BareInteractionId, K, extT, varT) = evalVfixK(K) -evalFakePropagator(id::PropagatorId, K, extT, varT) = 1.0 - -# @testset "ep Ver4" begin -# loopnum = 2 -# para = DiagParaF64(type=Ver4Diag, hasTau=true, innerLoopNum=loopnum, interaction=[Interaction(ChargeCharge, [Instant, Dynamic])]) -# Parquet.ep_coupling(para) # make sure ep_coupling runs -# end - - -@testset "Ver4 RPA chain" begin - - loopnum = 3 - - para = DiagParaF64(type=Ver4Diag, hasTau=true, innerLoopNum=loopnum, interaction=[Interaction(ChargeCharge, [Instant, Dynamic])]) - - - legK1, legK2, legK3 = DiagTree.getK(para.totalLoopNum, 1), DiagTree.getK(para.totalLoopNum, 2), DiagTree.getK(para.totalLoopNum, 3) - extK = [legK1, legK2, legK3, legK1 + legK3 - legK2] - level = 0 - - varK = rand(3, para.totalLoopNum) - varT = [rand() for i in 1:para.totalTauNum] - - weight = (2^loopnum) * (2^(loopnum + 1)) - - ############ PHEr ############ - c = PHEr - ver4df = DataFrame(response=Response[], type=AnalyticProperty[], extT=Tuple{Int,Int,Int,Int}[], diagram=Diagram{Float64}[]) - Parquet.RPA_chain!(ver4df, para, extK, c, level, :RPA, -1.0) - diags = mergeby(ver4df, :response) - DiagTree.evalKT!(diags, varK, varT; eval=evalFakePropagator) - w = [diags.diagram[1].weight, diags.diagram[2].weight] - # plot_tree(diags, maxdepth=15) - # println(w1) - #each bubble contribute 2, each dynamic interaction contribute 2, and there is two spin configuration upup, updown - @test w[1] β‰ˆ -weight #additional minus sign from the exchange diagram - @test w[2] β‰ˆ 0.0 # updown is not allowed in exchange diagram - - - ############ PHr ############ - c = PHr - ver4df = DataFrame(response=Response[], type=AnalyticProperty[], extT=Tuple{Int,Int,Int,Int}[], diagram=Diagram{Float64}[]) - Parquet.RPA_chain!(ver4df, para, extK, c, level, :RPA, -1.0) - diags = mergeby(ver4df, :response) - DiagTree.evalKT!(diags, varK, varT; eval=evalFakePropagator) - w = [diags.diagram[1].weight, diags.diagram[2].weight] - # plot_tree(diags, maxdepth=15) - # println(w1) - weight = (2^loopnum) * (2^(loopnum + 1)) - #each bubble contribute 2, each dynamic interaction contribute 2, and there is two spin configuration upup, updown - @test w[1] β‰ˆ weight - @test w[2] β‰ˆ weight -end - - -@testset "ParquetNew Ver4" begin - Benchmark = Parquet.Benchmark - - function getfunction(type) - if type == :physical - return evalG, evalV, evalPropagator - elseif type == :fixK - return evalGfixK, evalVfixK, evalPropagatorfixK - elseif type == :fake - return evalFakeG, evalFakeV, evalFakePropagator - else - error("not implemented") - end - end - - function testVertex4(loopNum, chan, type::Symbol; filter=[NoHartree,], timing=false, toeval=true) - println("$(Int.(chan)) Channel Test") - Kdim, spin = 3, 2 - interactionTauNum = 1 - isFermi = true - - K0 = zeros(loopNum + 2) - KinL, KoutL, KinR, KoutR = deepcopy(K0), deepcopy(K0), deepcopy(K0), deepcopy(K0) - KinL[1] = KoutL[1] = 1 - KinR[2] = KoutR[2] = 1 - legK = [KinL, KoutL, KinR, KoutR] - - blocks = ParquetBlocks(phi=[PHEr, PPr], ppi=[PHr, PHEr]) - - para = DiagParaF64( - type=Ver4Diag, - # loopDim=Kdim, - isFermi=isFermi, - hasTau=true, - innerLoopNum=loopNum, - totalLoopNum=length(KinL), - totalTauNum=(loopNum + 1) * interactionTauNum, - spin=spin, - firstLoopIdx=3, - firstTauIdx=1, - filter=union(filter, [Girreducible,]), #ver4 evaluation only support one-particle-irreducible diagram - transferLoop=KinL - KoutL, - interaction=[Interaction(ChargeCharge, Instant),], - extra=blocks - ) - - varK = rand(Kdim, para.totalLoopNum) - varT = [rand() for i in 1:para.totalTauNum] - - #################### DiagTree #################################### - diags = Parquet.vertex4(para, legK, chan) - diags = mergeby(diags, :response) - # DiagTreeNew.plot_tree(diags[1]) - # DiagTreeNew.plot_tree(diags[2]) - - ################### ExprTree ################################### - tree = ExprTree.build(diags.diagram, Kdim) - # println("root", root) - - ################### original Parquet builder ################################### - ver4 = Benchmark.Ver4{Benchmark.Weight}(para, Int.(chan), Int.(blocks.phi), Int.(blocks.ppi)) - - - if toeval - - evalG, evalV, evalPropagator = getfunction(type) - - # w1 = DiagTree.evalNaive(diag, varK, varT, evalPropagator) - DiagTree.evalKT!(diags, varK, varT; eval=evalPropagator) - w1 = [diags.diagram[1].weight, diags.diagram[2].weight] - if timing - printstyled("naive DiagTree evaluator cost:", color=:green) - @time DiagTree.evalKT!(diags, varK, varT; eval=evalPropagator) - end - - ExprTree.evalNaive!(tree, varK, varT; eval=evalPropagator) - w1e = [tree[1], tree[2]] - if timing - printstyled("naive ExprTree cost:", color=:green) - @time ExprTree.evalKT!(tree, varK, varT; eval=evalPropagator) - end - - - # optdiags = DiagTree.optimize!(diags.diagram) - opttree = ExprTree.build(diags.diagram, Kdim) - ExprTree.evalKT!(opttree, varK, varT; eval=evalPropagator) - w1eopt = [opttree[1], opttree[2]] - - if timing - printstyled("naive optimized ExprTree cost:", color=:green) - @time ExprTree.evalKT!(opttree, varK, varT; eval=evalPropagator) - end - - ##################### lower level subroutines ####################################### - - KinL, KoutL, KinR, KoutR = varK[:, 1], varK[:, 1], varK[:, 2], varK[:, 2] - legK = [KinL, KoutL, KinR, KoutR] - # Benchmark.eval(para, ver4, varK, varT, [KinL, KoutL, KinR, KoutR], evalG, evalV, true) - Benchmark.eval(para, ver4, varK, varT, legK, evalG, evalV, true) - - if timing - printstyled("parquet evaluator cost:", color=:green) - # @btime sin(p, ver4, var) setup = (x = rand()) - # @time Benchmark.eval(para, ver4, varK, varT, [KinL, KoutL, KinR, KoutR], evalG, evalV, true) - @time Benchmark.eval(para, ver4, varK, varT, legK, evalG, evalV, true) - # @btime Benchmark.eval(p, v4, vK, vT, lK, eG, eV, flag) setup = (p = para, v4 = ver4, vK = varK, vT = varT, l = legK, eG = evalG, eV = evalV, flag = true) - end - - w2 = ver4.weight[1] - - # println(w1, " vs ", w1e, " vs ", w2) - - @assert w1 β‰ˆ w1e - @assert w1 β‰ˆ w1eopt - - # The upup channel of charge-charge vertex4 == Direct + exchange - @test w1[1] β‰ˆ w2[1] + w2[2] - # The updown channel of charge-charge vertex4 == Direct - @test w1[2] β‰ˆ w2[1] - - end - - return para, diags, ver4 - end - - function testEval(type) - for l = 1:3 - testVertex4(l, [PHr,], type) - testVertex4(l, [PHEr,], type) - testVertex4(l, [PPr,], type) - testVertex4(l, [PHr, PHEr, PPr], type; timing=true) - end - end - - # testEval(:fake) - # testEval(:fixK) - testEval(:physical) - - #test only proper diagrams are generated if the switch is turned on - # para, diag, ver4 = testVertex4(3, [Parquet.T, Parquet.U, Parquet.S], :physical; filter = [Builder.Proper], eval = false) - # for i in 1:length(diag.basisPool) - # @test (diag.basisPool.basis[:, i] β‰ˆ para.transferLoop) == false - # end -end - -@testset "Parquet Sigma" begin - function getSigma(loopNum; Kdim=3, spin=2, interactionTauNum=1, filter=[NoHartree,], isFermi=true, subdiagram=false) - println("LoopNum =$loopNum Sigma Test") - - para = DiagParaF64( - type=SigmaDiag, - # loopDim=Kdim, - hasTau=true, - innerLoopNum=loopNum, - totalLoopNum=loopNum + 1, - totalTauNum=loopNum * interactionTauNum, - isFermi=isFermi, - spin=spin, - firstLoopIdx=2, - firstTauIdx=1, - filter=filter, - interaction=[Interaction(ChargeCharge, Instant),], - extra=ParquetBlocks(phi=[PHEr, PPr], ppi=[PHr, PHEr]) - ) - - extK = zeros(para.totalLoopNum) - extK[1] = 1.0 - - varK = rand(Kdim, para.totalLoopNum) - varT = [rand() for i in 1:para.totalTauNum] - - #################### DiagTree #################################### - diag = Parquet.sigma(para, extK, subdiagram) - diag = mergeby(diag) - # print_tree(diag.diagram[1]) - - return para, diag.diagram[1], varK, varT - end - - - function testDiagramNumber(para, diag, varK, varT) - # w = DiagTree.evalNaive(diag, varK, varT, evalFakePropagator) - w = DiagTree.evalKT!(diag, varK, varT; eval=evalFakePropagator) - # plot_tree(diag, maxdepth = 7) - # factor = (1 / (2Ο€)^para.loopDim)^para.innerLoopNum - factor = 1.0 - num = w / factor - @test num * (-1)^(para.innerLoopNum) β‰ˆ Parquet.Benchmark.count_sigma_G2v(para.innerLoopNum, para.spin) - end - - - ################## G^2*v expansion ######################################### - for l = 1:4 - # ret = getSigma(l, spin = 1, isFermi = false, filter = [Builder.Girreducible,]) - # testDiagramNumber(ret...) - ret = getSigma(l, spin=2, isFermi=false, filter=[NoHartree, Girreducible,]) - testDiagramNumber(ret...) - end - - # para, diag, varK, varT = getSigma(1, spin = 2, isFermi = false, filter = [Builder.NoFock,], subdiagram = true) - # @test isempty(diag.root) - -end - -@testset "Green" begin - function buildG(loopNum, extT; Kdim=3, spin=2, interactionTauNum=1, filter=[NoHartree,], isFermi=true) - para = DiagParaF64( - type=GreenDiag, - # loopDim=Kdim, - hasTau=true, - innerLoopNum=loopNum, - isFermi=isFermi, - spin=spin, - filter=filter, - interaction=[Interaction(ChargeCharge, Instant),] - ) - extK = zeros(para.totalLoopNum) - extK[1] = 1.0 - if Parquet.isValidG(para) - G = Parquet.green(para, extK, extT) - return G - else - return nothing - end - end - # diag, Gidx = buildG(2, [1, 2], 3; filter = []) - # DiagTree.showTree(diag, Gidx) - - # If G is irreducible, then only loop-0 G exist for main diagram, and no G exist for subdiagram - G = buildG(0, [1, 2]; filter=[NoHartree, Girreducible,]) - @test G isa Diagram - G = buildG(1, [1, 2]; filter=[NoHartree, Girreducible,]) - @test isnothing(G) - G = buildG(2, [1, 2]; filter=[NoHartree, Girreducible,]) - @test isnothing(G) - - # If Fock diagram is not allowed, then one-loop G diagram should not be exist for subdiagram - G = buildG(0, [1, 2]; filter=[NoHartree, NoFock,]) - @test G isa Diagram - G = buildG(1, [1, 2]; filter=[NoHartree, NoFock,]) - @test isnothing(G) - G = buildG(2, [1, 2]; filter=[NoHartree, NoFock,]) #high order subdiagram is allowed - @test G isa Diagram - -end - - -@testset "Parquet Vertex3" begin - function getGamma3(loopNum; Kdim=3, spin=2, interactionTauNum=1, filter=[NoHartree, Girreducible, Proper,], isFermi=true, subdiagram=false) - println("LoopNum =$loopNum Vertex3 Test") - - para = DiagParaF64( - type=Ver3Diag, - # loopDim=Kdim, - innerLoopNum=loopNum, - isFermi=isFermi, - hasTau=true, - filter=filter, - interaction=[Interaction(ChargeCharge, Instant),] - ) - - K0 = zeros(para.totalLoopNum) - KinL, Q = deepcopy(K0), deepcopy(K0) - Q[1] = 1 - KinL[2] = 1 - legK = [Q, KinL] - - varK = rand(Kdim, para.totalLoopNum) - varT = [rand() for i in 1:para.totalTauNum] - - #################### DiagTree #################################### - vertex3 = Parquet.vertex3(para, legK) - diag = mergeby(vertex3) - # print_tree(diag.diagram[1]) - - return para, diag.diagram[1], varK, varT - end - - - function testDiagramNumber(para, diag, varK, varT) - # w = DiagTree.evalNaive(diag, varK, varT, evalFakePropagator) - w = DiagTree.evalKT!(diag, varK, varT; eval=evalFakePropagator) - # plot_tree(diag, maxdepth = 9) - # factor = (1 / (2Ο€)^para.loopDim)^para.innerLoopNum - factor = 1.0 - num = w / factor - @test num * (-1)^(para.innerLoopNum) β‰ˆ Parquet.Benchmark.count_ver3_G2v(para.innerLoopNum, para.spin) - end - - - ################## G^2*v expansion ######################################### - for l = 1:3 - # ret = getSigma(l, spin = 1, isFermi = false, filter = [Builder.Girreducible,]) - # testDiagramNumber(ret...) - ret = getGamma3(l, isFermi=false, filter=[NoHartree, Girreducible, Proper]) - testDiagramNumber(ret...) - end - - # para, diag, varK, varT = getSigma(1, spin = 2, isFermi = false, filter = [Builder.NoFock,], subdiagram = true) - # @test isempty(diag.root) - -end - - -@testset "Parquet Polarization" begin - function getPolar(loopNum; Kdim=3, spin=2, interactionTauNum=1, filter=[NoHartree, Girreducible,], isFermi=true, subdiagram=false) - println("LoopNum =$loopNum Polarization Test") - - para = DiagParaF64( - type=PolarDiag, - # loopDim=Kdim, - innerLoopNum=loopNum, - isFermi=isFermi, - hasTau=true, - filter=filter, - interaction=[Interaction(ChargeCharge, Instant),] - ) - - Q = zeros(para.totalLoopNum) - Q[1] = 1 - - varK = rand(Kdim, para.totalLoopNum) - varT = [rand() for i in 1:para.totalTauNum] - - #################### DiagTree #################################### - diag = Parquet.polarization(para, Q) - # print_tree(diag.diagram[1]) - return para, diag, varK, varT - end - - # Test polarization Parquet builder when filter 'Proper' is specified explicitly - getPolar(1, filter=[Proper, NoHartree, NoFock,]) - - ################## G^2*v expansion ######################################### - for l = 1:4 - para, diag, varK, varT = getPolar(l, isFermi=false, filter=[NoHartree, Girreducible,]) - diag = mergeby(diag).diagram[1] - w = DiagTree.evalKT!(diag, varK, varT; eval=evalFakePropagator) - # factor = (1 / (2Ο€)^para.loopDim)^para.innerLoopNum - factor = 1.0 - num = w / factor - # println(num * para.spin) - @test num * para.spin * (-1)^(para.innerLoopNum - 1) β‰ˆ Parquet.Benchmark.count_polar_G2v(para.innerLoopNum, para.spin) - end - - ################## g^2*v expansion ######################################### - for l = 1:4 - para, diag, varK, varT = getPolar(l, isFermi=false, filter=[NoHartree, NoFock,]) - diag = mergeby(diag).diagram[1] - w = DiagTree.evalKT!(diag, varK, varT, eval=evalFakePropagator) - # factor = (1 / (2Ο€)^para.loopDim)^para.innerLoopNum - factor = 1.0 - num = w / factor - # println(num * para.spin) - @test num * para.spin * (-1)^(para.innerLoopNum - 1) β‰ˆ Parquet.Benchmark.count_polar_g2v_noFock(para.innerLoopNum, para.spin) - end - - ################## g^2*v expansion for the upup polarization ######################################### - for l = 1:4 - para, diag, varK, varT = getPolar(l, isFermi=false, filter=[NoHartree, NoFock,]) - w = DiagTree.evalKT!(diag.diagram[1], varK, varT, eval=evalFakePropagator) - # factor = (1 / (2Ο€)^para.loopDim)^para.innerLoopNum - factor = 1.0 - num = w / factor - # println(num * para.spin) - # println("$diag") - @test num * para.spin * (-1)^(para.innerLoopNum - 1) β‰ˆ Parquet.Benchmark.count_polar_g2v_noFock_upup(para.innerLoopNum, para.spin) - end -end \ No newline at end of file