Applications
Gradient flow
We can use Lüscher's gradient flow.
NX = 4
NY = 4
NZ = 4
NT = 4
Nwing = 1
NC = 3
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "hot")
temp1 = similar(U[1])
temp2 = similar(U[1])
temp3 = similar(U[1])
comb = 6
factor = 1/(comb*U[1].NV*U[1].NC)
g = Gradientflow(U)
for itrj=1:100
flow!(U,g)
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("$itrj plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("$itrj polyakov loop = $(real(poly)) $(imag(poly))")
end
Gradient flow with general terms
We can do the gradient flow with general terms with the use of Wilsonloop.jl, which is shown below. The coefficient of the action can be complex. The complex conjugate of the action defined here is added automatically to make the total action hermitian. The code is
using Random
using Test
using Gaugefields
using Wilsonloop
function gradientflow_test_4D(NX,NY,NZ,NT,NC)
Dim = 4
Nwing = 1
Random.seed!(123)
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "hot",randomnumber="Reproducible")
temp1 = similar(U[1])
temp2 = similar(U[1])
if Dim == 4
comb = 6 #4*3/2
elseif Dim == 3
comb = 3
elseif Dim == 2
comb = 1
else
error("dimension $Dim is not supported")
end
factor = 1/(comb*U[1].NV*U[1].NC)
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("0 plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("0 polyakov loop = $(real(poly)) $(imag(poly))")
#Plaquette term
loops_p = Wilsonline{Dim}[]
for μ=1:Dim
for ν=μ:Dim
if ν == μ
continue
end
loop1 = Wilsonline([(μ,1),(ν,1),(μ,-1),(ν,-1)],Dim = Dim)
push!(loops_p,loop1)
end
end
#Rectangular term
loops = Wilsonline{Dim}[]
for μ=1:Dim
for ν=μ:Dim
if ν == μ
continue
end
loop1 = Wilsonline([(μ,1),(ν,2),(μ,-1),(ν,-2)],Dim = Dim)
push!(loops,loop1)
loop1 = Wilsonline([(μ,2),(ν,1),(μ,-2),(ν,-1)],Dim = Dim)
push!(loops,loop1)
end
end
listloops = [loops_p,loops]
listvalues = [1+im,0.1]
g = Gradientflow_general(U,listloops,listvalues,eps = 0.01)
for itrj=1:100
flow!(U,g)
if itrj % 10 == 0
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("$itrj plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("$itrj polyakov loop = $(real(poly)) $(imag(poly))")
end
end
return plaq_t
end
function gradientflow_test_2D(NX,NT,NC)
Dim = 2
Nwing = 1
U = Initialize_Gaugefields(NC,Nwing,NX,NT,condition = "hot",randomnumber="Reproducible")
temp1 = similar(U[1])
temp2 = similar(U[1])
if Dim == 4
comb = 6 #4*3/2
elseif Dim == 3
comb = 3
elseif Dim == 2
comb = 1
else
error("dimension $Dim is not supported")
end
factor = 1/(comb*U[1].NV*U[1].NC)
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("0 plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("0 polyakov loop = $(real(poly)) $(imag(poly))")
#g = Gradientflow(U,eps = 0.01)
#listnames = ["plaquette"]
#listvalues = [1]
loops_p = Wilsonline{Dim}[]
for μ=1:Dim
for ν=μ:Dim
if ν == μ
continue
end
loop1 = Wilsonline([(μ,1),(ν,1),(μ,-1),(ν,-1)],Dim = Dim)
push!(loops_p,loop1)
end
end
loops = Wilsonline{Dim}[]
for μ=1:Dim
for ν=μ:Dim
if ν == μ
continue
end
loop1 = Wilsonline([(μ,1),(ν,2),(μ,-1),(ν,-2)],Dim = Dim)
push!(loops,loop1)
loop1 = Wilsonline([(μ,2),(ν,1),(μ,-2),(ν,-1)],Dim = Dim)
push!(loops,loop1)
end
end
listloops = [loops_p,loops]
listvalues = [1+im,0.1]
g = Gradientflow_general(U,listloops,listvalues,eps = 0.01)
for itrj=1:100
flow!(U,g)
if itrj % 10 == 0
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("$itrj plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("$itrj polyakov loop = $(real(poly)) $(imag(poly))")
end
end
return plaq_t
end
const eps = 0.1
println("2D system")
@testset "2D" begin
NX = 4
#NY = 4
#NZ = 4
NT = 4
Nwing = 1
@testset "NC=1" begin
β = 2.3
NC = 1
println("NC = $NC")
@time plaq_t = gradientflow_test_2D(NX,NT,NC)
end
#error("d")
@testset "NC=2" begin
β = 2.3
NC = 2
println("NC = $NC")
@time plaq_t = gradientflow_test_2D(NX,NT,NC)
end
@testset "NC=3" begin
β = 5.7
NC = 3
println("NC = $NC")
@time plaq_t = gradientflow_test_2D(NX,NT,NC)
end
@testset "NC=4" begin
β = 5.7
NC = 4
println("NC = $NC")
@time plaq_t = gradientflow_test_2D(NX,NT,NC)
end
end
println("4D system")
@testset "4D" begin
NX = 4
NY = 4
NZ = 4
NT = 4
Nwing = 1
@testset "NC=2" begin
β = 2.3
NC = 2
println("NC = $NC")
@time plaq_t = gradientflow_test_4D(NX,NY,NZ,NT,NC)
end
@testset "NC=3" begin
β = 5.7
NC = 3
println("NC = $NC")
@time plaq_t = gradientflow_test_4D(NX,NY,NZ,NT,NC)
end
@testset "NC=4" begin
β = 5.7
NC = 4
println("NC = $NC")
val = 0.7301232810349298
@time plaq_t =gradientflow_test_4D(NX,NY,NZ,NT,NC)
end
end
Heatbath updates (even-odd method)
using Gaugefields
function heatbath_SU3!(U,NC,temps,β)
Dim = 4
temp1 = temps[1]
temp2 = temps[2]
V = temps[3]
ITERATION_MAX = 10^5
temps2 = Array{Matrix{ComplexF64},1}(undef,5)
temps3 = Array{Matrix{ComplexF64},1}(undef,5)
for i=1:5
temps2[i] = zeros(ComplexF64,2,2)
temps3[i] = zeros(ComplexF64,NC,NC)
end
mapfunc!(A,B) = SU3update_matrix!(A,B,β,NC,temps2,temps3,ITERATION_MAX)
for μ=1:Dim
loops = loops_staple[(Dim,μ)]
iseven = true
evaluate_gaugelinks_evenodd!(V,loops,U,[temp1,temp2],iseven)
map_U!(U[μ],mapfunc!,V,iseven)
iseven = false
evaluate_gaugelinks_evenodd!(V,loops,U,[temp1,temp2],iseven)
map_U!(U[μ],mapfunc!,V,iseven)
end
end
function heatbathtest_4D(NX,NY,NZ,NT,β,NC)
Dim = 4
Nwing = 1
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "cold")
temp1 = similar(U[1])
temp2 = similar(U[1])
temp3 = similar(U[1])
comb = 6
factor = 1/(comb*U[1].NV*U[1].NC)
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("polyakov loop = $(real(poly)) $(imag(poly))")
numhb = 40
for itrj = 1:numhb
heatbath_SU3!(U,NC,[temp1,temp2,temp3],β)
if itrj % 10 == 0
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("$itrj plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("$itrj polyakov loop = $(real(poly)) $(imag(poly))")
end
end
return plaq_t
end
NX = 4
NY = 4
NZ = 4
NT = 4
Nwing = 1
β = 5.7
NC = 3
@time plaq_t = heatbathtest_4D(NX,NY,NZ,NT,β,NC)
Heatbath updates with general actions
We can do heatbath updates with a general action.
using Gaugefields
function heatbathtest_4D(NX,NY,NZ,NT,β,NC)
Dim = 4
Nwing = 1
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "cold")
println(typeof(U))
gauge_action = GaugeAction(U)
plaqloop = make_loops_fromname("plaquette",Dim=Dim)
append!(plaqloop,plaqloop')
βinp = β/2
push!(gauge_action,βinp,plaqloop)
rectloop = make_loops_fromname("rectangular",Dim=Dim)
append!(rectloop,rectloop')
βinp = β/2
push!(gauge_action,βinp,rectloop)
hnew = Heatbath_update(U,gauge_action)
show(gauge_action)
temp1 = similar(U[1])
temp2 = similar(U[1])
temp3 = similar(U[1])
comb = 6
factor = 1/(comb*U[1].NV*U[1].NC)
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("plaq_t = $plaq_t")
poly = calculate_Polyakov_loop(U,temp1,temp2)
println("polyakov loop = $(real(poly)) $(imag(poly))")
numhb = 1000
for itrj = 1:numhb
heatbath!(U,hnew)
plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
poly = calculate_Polyakov_loop(U,temp1,temp2)
if itrj % 40 == 0
println("$itrj plaq_t = $plaq_t")
println("$itrj polyakov loop = $(real(poly)) $(imag(poly))")
end
end
close(fp)
return plaq_t
end
NX = 4
NY = 4
NZ = 4
NT = 4
NC = 3
β = 5.7
heatbathtest_4D(NX,NY,NZ,NT,β,NC)
In this code, we consider the plaquette and rectangular actions.
Wilson loops
This package and Wilsonloop.jl enable you to perform several calcurations. Here we demonstrate them.
Some of them will be simplified in LatticeQCD.jl.
We develop Wilsonloop.jl, which is useful to calculate Wilson loops. If you want to use this, please install like
add Wilsonloop
For example, if you want to calculate the following quantity:
\[U_{1}(n)U_{2}(n+\hat{1}) U^{\dagger}_{1}(n+\hat{2}) U^{\dagger}_2(n)\]
You can use Wilsonloop.jl as follows
using Wilsonloop
loop = [(1,1),(2,1),(1,-1),(2,-1)]
w = Wilsonline(loop)
The output is L"$U_{1}(n)U_{2}(n+e_{1})U^{\dagger}_{1}(n+e_{2})U^{\dagger}_{2}(n)$"
. Then, you can evaluate this loop with the use of the Gaugefields.jl like:
using LinearAlgebra
NX = 4
NY = 4
NZ = 4
NT = 4
NC = 3
Nwing = 1
Dim = 4
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "cold")
temp1 = similar(U[1])
V = similar(U[1])
evaluate_gaugelinks!(V,w,U,[temp1])
println(tr(V))
For example, if you want to calculate the clover operators, you can define like:
function make_cloverloop(μ,ν,Dim)
loops = Wilsonline{Dim}[]
loop_righttop = Wilsonline([(μ,1),(ν,1),(μ,-1),(ν,-1)],Dim = Dim) # Pmunu
push!(loops,loop_righttop)
loop_rightbottom = Wilsonline([(ν,-1),(μ,1),(ν,1),(μ,-1)],Dim = Dim) # Qmunu
push!(loops,loop_rightbottom)
loop_leftbottom= Wilsonline([(μ,-1),(ν,-1),(μ,1),(ν,1)],Dim = Dim) # Rmunu
push!(loops,loop_leftbottom)
loop_lefttop = Wilsonline([(ν,1),(μ,-1),(ν,-1),(μ,1)],Dim = Dim) # Smunu
push!(loops,loop_lefttop)
return loops
end
The energy density defined in the paper (Ramos and Sint, Eur. Phys. J. C (2016) 76:15) can be calculated as follows. Note: the coefficient in the equation (3.40) in the preprint version is wrong.
function make_clover(G,U,temps,Dim)
temp1 = temps[1]
temp2 = temps[2]
temp3 = temps[3]
for μ=1:Dim
for ν=1:Dim
if μ == ν
continue
end
loops = make_cloverloop(μ,ν,Dim)
evaluate_gaugelinks!(temp3,loops,U,[temp1,temp2])
Traceless_antihermitian!(G[μ,ν],temp3)
end
end
end
function calc_energydensity(G,U,temps,Dim)
temp1 = temps[1]
s = 0
for μ=1:Dim
for ν=1:Dim
if μ == ν
continue
end
mul!(temp1,G[μ,ν],G[μ,ν])
s += -real(tr(temp1))/2
end
end
return s/(4^2*U[1].NV)
end
Then, we can calculate the energy density:
function test(NX,NY,NZ,NT,β,NC)
Dim = 4
Nwing = 1
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "cold")
filename = "./conf_00000010.txt"
L = [NX,NY,NZ,NT]
load_BridgeText!(filename,U,L,NC) # We load a configuration from a file.
temp1 = similar(U[1])
temp2 = similar(U[1])
temp3 = similar(U[1])
println("Make clover operator")
G = Array{typeof(u1),2}(undef,Dim,Dim)
for μ=1:Dim
for ν=1:Dim
G[μ,ν] = similar(U[1])
end
end
comb = 6
factor = 1/(comb*U[1].NV*U[1].NC)
@time plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("plaq_t = $plaq_t")
g = Gradientflow(U,eps = 0.01)
for itrj=1:100
flow!(U,g)
make_clover(G,U,[temp1,temp2,temp3],Dim)
E = calc_energydensity(G,U,[temp1,temp2,temp3],Dim)
plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("$itrj $(itrj*0.01) plaq_t = $plaq_t , E = $E")
end
end
NX = 8
NY = 8
NZ = 8
NT = 8
β = 5.7
NC = 3
test(NX,NY,NZ,NT,β,NC)
Calculating actions
We can calculate actions from this packages with fixed gauge fields U. We introduce the concenpt "Scalar-valued neural network", which is S(U) -> V, where U and V are gauge fields.
using Gaugefields
using LinearAlgebra
function test1()
NX = 4
NY = 4
NZ = 4
NT = 4
Nwing = 1
Dim = 4
NC = 3
U =Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "cold")
gauge_action = GaugeAction(U) #empty network
plaqloop = make_loops_fromname("plaquette") #This is a plaquette loops.
append!(plaqloop,plaqloop') #We need hermitian conjugate loops for making the action real.
β = 1 #This is a coefficient.
push!(gauge_action,β,plaqloop)
show(gauge_action)
Uout = evaluate_Gaugeaction_untraced(gauge_action,U)
println(tr(Uout))
end
test1()
The output is
----------------------------------------------
Structure of the actions for Gaugefields
num. of terms: 1
-------------------------------
1-st term:
coefficient: 1.0
-------------------------
1-st loop
L"$U_{1}(n)U_{2}(n+e_{1})U^{\dagger}_{1}(n+e_{2})U^{\dagger}_{2}(n)$"
2-nd loop
L"$U_{1}(n)U_{3}(n+e_{1})U^{\dagger}_{1}(n+e_{3})U^{\dagger}_{3}(n)$"
3-rd loop
L"$U_{1}(n)U_{4}(n+e_{1})U^{\dagger}_{1}(n+e_{4})U^{\dagger}_{4}(n)$"
4-th loop
L"$U_{2}(n)U_{3}(n+e_{2})U^{\dagger}_{2}(n+e_{3})U^{\dagger}_{3}(n)$"
5-th loop
L"$U_{2}(n)U_{4}(n+e_{2})U^{\dagger}_{2}(n+e_{4})U^{\dagger}_{4}(n)$"
6-th loop
L"$U_{3}(n)U_{4}(n+e_{3})U^{\dagger}_{3}(n+e_{4})U^{\dagger}_{4}(n)$"
7-th loop
L"$U_{2}(n)U_{1}(n+e_{2})U^{\dagger}_{2}(n+e_{1})U^{\dagger}_{1}(n)$"
8-th loop
L"$U_{3}(n)U_{1}(n+e_{3})U^{\dagger}_{3}(n+e_{1})U^{\dagger}_{1}(n)$"
9-th loop
L"$U_{4}(n)U_{1}(n+e_{4})U^{\dagger}_{4}(n+e_{1})U^{\dagger}_{1}(n)$"
10-th loop
L"$U_{3}(n)U_{2}(n+e_{3})U^{\dagger}_{3}(n+e_{2})U^{\dagger}_{2}(n)$"
11-th loop
L"$U_{4}(n)U_{2}(n+e_{4})U^{\dagger}_{4}(n+e_{2})U^{\dagger}_{2}(n)$"
12-th loop
L"$U_{4}(n)U_{3}(n+e_{4})U^{\dagger}_{4}(n+e_{3})U^{\dagger}_{3}(n)$"
-------------------------
----------------------------------------------
9216.0 + 0.0im
How to calculate derivatives
We can easily calculate the matrix derivative of the actions. The matrix derivative is defined as
\[\left[ \frac{\partial S}{\partial U_{\mu}(n)} \right]_{ij} = \frac{\partial S}{\partial [U_{\mu}(n)]_{ji}}\]
We can calculate this like
dSdUμ = calc_dSdUμ(gauge_action,μ,U)
or
calc_dSdUμ!(dSdUμ,gauge_action,μ,U)
Hybrid Monte Carlo
With the use of the matrix derivative, we can do the Hybrid Monte Carlo method. The simple code is as follows.
using Gaugefields
using LinearAlgebra
function MDtest!(gauge_action,U,Dim)
p = initialize_TA_Gaugefields(U) #This is a traceless-antihermitian gauge fields. This has NC^2-1 real coefficients.
Uold = similar(U)
substitute_U!(Uold,U)
MDsteps = 100
temp1 = similar(U[1])
temp2 = similar(U[1])
comb = 6
factor = 1/(comb*U[1].NV*U[1].NC)
numaccepted = 0
numtrj = 100
for itrj = 1:numtrj
accepted = MDstep!(gauge_action,U,p,MDsteps,Dim,Uold)
numaccepted += ifelse(accepted,1,0)
plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("$itrj plaq_t = $plaq_t")
println("acceptance ratio ",numaccepted/itrj)
end
end
We define the functions as
function calc_action(gauge_action,U,p)
NC = U[1].NC
Sg = -evaluate_GaugeAction(gauge_action,U)/NC #evaluate_GaugeAction(gauge_action,U) = tr(evaluate_Gaugeaction_untraced(gauge_action,U))
Sp = p*p/2
S = Sp + Sg
return real(S)
end
function MDstep!(gauge_action,U,p,MDsteps,Dim,Uold)
Δτ = 1/MDsteps
gauss_distribution!(p)
Sold = calc_action(gauge_action,U,p)
substitute_U!(Uold,U)
for itrj=1:MDsteps
U_update!(U,p,0.5,Δτ,Dim,gauge_action)
P_update!(U,p,1.0,Δτ,Dim,gauge_action)
U_update!(U,p,0.5,Δτ,Dim,gauge_action)
end
Snew = calc_action(gauge_action,U,p)
println("Sold = $Sold, Snew = $Snew")
println("Snew - Sold = $(Snew-Sold)")
ratio = min(1,exp(Snew-Sold))
if rand() > ratio
substitute_U!(U,Uold)
return false
else
return true
end
end
function U_update!(U,p,ϵ,Δτ,Dim,gauge_action)
temps = get_temporary_gaugefields(gauge_action)
temp1 = temps[1]
temp2 = temps[2]
expU = temps[3]
W = temps[4]
for μ=1:Dim
exptU!(expU,ϵ*Δτ,p[μ],[temp1,temp2])
mul!(W,expU,U[μ])
substitute_U!(U[μ],W)
end
end
function P_update!(U,p,ϵ,Δτ,Dim,gauge_action) # p -> p +factor*U*dSdUμ
NC = U[1].NC
temps = get_temporary_gaugefields(gauge_action)
dSdUμ = temps[end]
factor = -ϵ*Δτ/(NC)
for μ=1:Dim
calc_dSdUμ!(dSdUμ,gauge_action,μ,U)
mul!(temps[1],U[μ],dSdUμ) # U*dSdUμ
Traceless_antihermitian_add!(p[μ],factor,temps[1])
end
end
Then, we can do the HMC:
function test1()
NX = 4
NY = 4
NZ = 4
NT = 4
Nwing = 1
Dim = 4
NC = 3
U =Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "cold")
gauge_action = GaugeAction(U)
plaqloop = make_loops_fromname("plaquette")
append!(plaqloop,plaqloop')
β = 5.7/2
push!(gauge_action,β,plaqloop)
show(gauge_action)
MDtest!(gauge_action,U,Dim)
end
test1()
Smearing
Smearing techniques make gaugefileds more smooth.
\[U_{\rm fat} = {\cal F}(U)\]
Stout smearing
We can use stout smearing.
The smearing is regarded as gauge covariant neural networks Tomiya and Nagai, arXiv:2103.11965. The network is constructed as follows.
nn = CovNeuralnet()
ρ = [0.1]
layername = ["plaquette"]
st = STOUT_Layer(layername,ρ,L)
push!(nn,st)
show(nn)
The output is
num. of layers: 1
- 1-st layer: STOUT
num. of terms: 1
-------------------------------
1-st term:
coefficient: 0.1
-------------------------
1-st loop
L"$U_{1}(n)U_{2}(n+e_{1})U^{\dagger}_{1}(n+e_{2})U^{\dagger}_{2}(n)$"
2-nd loop
L"$U_{1}(n)U_{3}(n+e_{1})U^{\dagger}_{1}(n+e_{3})U^{\dagger}_{3}(n)$"
3-rd loop
L"$U_{1}(n)U_{4}(n+e_{1})U^{\dagger}_{1}(n+e_{4})U^{\dagger}_{4}(n)$"
4-th loop
L"$U_{2}(n)U_{3}(n+e_{2})U^{\dagger}_{2}(n+e_{3})U^{\dagger}_{3}(n)$"
5-th loop
L"$U_{2}(n)U_{4}(n+e_{2})U^{\dagger}_{2}(n+e_{4})U^{\dagger}_{4}(n)$"
6-th loop
L"$U_{3}(n)U_{4}(n+e_{3})U^{\dagger}_{3}(n+e_{4})U^{\dagger}_{4}(n)$"
-------------------------
Since we ragard the smearing as the neural networks, we can calculate the derivative with the use of the back propergation techques.
\[\frac{\partial S}{\partial U} = G \left( \frac{dS}{dU_{\rm fat}},U \right)\]
For example,
using Gaugefields
using Wilsonloop
function stoutsmearing(NX,NY,NZ,NT,NC)
Nwing = 1
Dim = 4
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "hot")
L = [NX,NY,NZ,NT]
comb = 6
factor = 1/(comb*U[1].NV*U[1].NC)
temp1 = similar(U[1])
temp2 = similar(U[1])
plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println(" plaq_t = $plaq_t")
nn = CovNeuralnet()
ρ = [0.1]
layername = ["plaquette"]
st = STOUT_Layer(layername,ρ,L)
push!(nn,st)
show(nn)
@time Uout,Uout_multi,_ = calc_smearedU(U,nn)
plaq_t = calculate_Plaquette(Uout,temp1,temp2)*factor
println("plaq_t = $plaq_t")
gauge_action = GaugeAction(U)
plaqloop = make_loops_fromname("plaquette")
append!(plaqloop,plaqloop')
β = 5.7/2
push!(gauge_action,β,plaqloop)
μ = 1
dSdUμ = similar(U)
for μ=1:Dim
dSdUμ[μ] = calc_dSdUμ(gauge_action,μ,U)
end
@time dSdUbareμ = back_prop(dSdUμ,nn,Uout_multi,U)
end
NX = 4
NY = 4
NZ = 4
NT = 4
NC = 3
stoutsmearing(NX,NY,NZ,NT,NC)
HMC with stout smearing
With the use of the derivatives, we can do the HMC with the stout smearing. The code is shown as follows
using Gaugefields
using LinearAlgebra
function MDtest!(gauge_action,U,Dim,nn)
p = initialize_TA_Gaugefields(U) #This is a traceless-antihermitian gauge fields. This has NC^2-1 real coefficients.
Uold = similar(U)
dSdU = similar(U)
substitute_U!(Uold,U)
MDsteps = 100
temp1 = similar(U[1])
temp2 = similar(U[1])
comb = 6
factor = 1/(comb*U[1].NV*U[1].NC)
numaccepted = 0
numtrj = 100
for itrj = 1:numtrj
accepted = MDstep!(gauge_action,U,p,MDsteps,Dim,Uold,nn,dSdU)
numaccepted += ifelse(accepted,1,0)
plaq_t = calculate_Plaquette(U,temp1,temp2)*factor
println("$itrj plaq_t = $plaq_t")
println("acceptance ratio ",numaccepted/itrj)
end
end
function calc_action(gauge_action,U,p)
NC = U[1].NC
Sg = -evaluate_GaugeAction(gauge_action,U)/NC #evaluate_GaugeAction(gauge_action,U) = tr(evaluate_GaugeAction_untraced(gauge_action,U))
Sp = p*p/2
S = Sp + Sg
return real(S)
end
function MDstep!(gauge_action,U,p,MDsteps,Dim,Uold,nn,dSdU)
Δτ = 1/MDsteps
gauss_distribution!(p)
Uout,Uout_multi,_ = calc_smearedU(U,nn)
Sold = calc_action(gauge_action,Uout,p)
substitute_U!(Uold,U)
for itrj=1:MDsteps
U_update!(U,p,0.5,Δτ,Dim,gauge_action)
P_update!(U,p,1.0,Δτ,Dim,gauge_action,dSdU,nn)
U_update!(U,p,0.5,Δτ,Dim,gauge_action)
end
Uout,Uout_multi,_ = calc_smearedU(U,nn)
Snew = calc_action(gauge_action,Uout,p)
println("Sold = $Sold, Snew = $Snew")
println("Snew - Sold = $(Snew-Sold)")
accept = exp(Sold - Snew) >= rand()
if accept != true #rand() > ratio
substitute_U!(U,Uold)
return false
else
return true
end
end
function U_update!(U,p,ϵ,Δτ,Dim,gauge_action)
temps = get_temporary_gaugefields(gauge_action)
temp1 = temps[1]
temp2 = temps[2]
expU = temps[3]
W = temps[4]
for μ=1:Dim
exptU!(expU,ϵ*Δτ,p[μ],[temp1,temp2])
mul!(W,expU,U[μ])
substitute_U!(U[μ],W)
end
end
function P_update!(U,p,ϵ,Δτ,Dim,gauge_action,dSdU,nn) # p -> p +factor*U*dSdUμ
NC = U[1].NC
factor = -ϵ*Δτ/(NC)
temps = get_temporary_gaugefields(gauge_action)
Uout,Uout_multi,_ = calc_smearedU(U,nn)
for μ=1:Dim
calc_dSdUμ!(dSdU[μ],gauge_action,μ,Uout)
end
dSdUbare = back_prop(dSdU,nn,Uout_multi,U)
for μ=1:Dim
mul!(temps[1],U[μ],dSdUbare[μ]) # U*dSdUμ
Traceless_antihermitian_add!(p[μ],factor,temps[1])
end
end
function test1()
NX = 4
NY = 4
NZ = 4
NT = 4
Nwing = 1
Dim = 4
NC = 3
U =Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "hot")
gauge_action = GaugeAction(U)
plaqloop = make_loops_fromname("plaquette")
append!(plaqloop,plaqloop')
β = 5.7/2
push!(gauge_action,β,plaqloop)
show(gauge_action)
L = [NX,NY,NZ,NT]
nn = CovNeuralnet()
ρ = [0.1]
layername = ["plaquette"]
st = STOUT_Layer(layername,ρ,L)
push!(nn,st)
MDtest!(gauge_action,U,Dim,nn)
end
test1()
Mapping example
We have a mapping function map_U_sequential!(U,func!,V)
. This function is used in the heatbath updates. func!(U,V,ix,iy,iz,it)
updates the matrix U[ix,iy,iz,it]
on each site. V
is an input array or field. For example, in the heatbath update, the updated new matrix depends on the Gauge field U
, so we set map_U_sequential!(U[mu],func!,U)
. Then U
is updated sequentially.
We show the example to apply "staggered phase" to the Gauge field. Since this phase does not depend on the Gaugefield and does depend only on the site index, V
is a dummy variable.
This is 4D case
using Gaugefields
function test()
NX = 4
NY = 4
NZ = 4
NT = 4
NC = 3
Nwing = 0
U = Initialize_Gaugefields(NC,Nwing,NX,NY,NZ,NT,condition = "cold")
μ = 4
function staggered_phase!(A,V,ix,iy,iz,it )
t = it-1
t += ifelse(t<0,NT,0)
t += ifelse(t ≥ NT,-NT,0)
#boundary_factor_t = ifelse(t == NT -1,BoundaryCondition[4],1)
z = iz-1
z += ifelse(z<0,NZ,0)
z += ifelse(z ≥ NZ,-NZ,0)
#boundary_factor_z = ifelse(z == NZ -1,BoundaryCondition[3],1)
y = iy-1
y += ifelse(y<0,NY,0)
y += ifelse(y ≥ NY,-NY,0)
#boundary_factor_y = ifelse(y == NY -1,BoundaryCondition[2],1)
x = ix-1
x += ifelse(x<0,NX,0)
x += ifelse(x ≥ NX,-NX,0)
#boundary_factor_x = ifelse(x == NX -1,BoundaryCondition[1],1)
if μ ==1
η = 1
elseif μ ==2
#η = (-1.0)^(x)
η = ifelse(x%2 == 0,1,-1)
elseif μ ==3
#η = (-1.0)^(x+y)
η = ifelse((x+y)%2 == 0,1,-1)
elseif μ ==4
#η = (-1.0)^(x+y+z)
η = ifelse((x+y+z)%2 == 0,1,-1)
else
error("η should be positive but η = $η")
end
for ic=1:NC
for jc=1:NC
A[jc,ic] *= η
end
end
end
V = similar(U)
println(U[μ][:,:,1,1,1,1])
println(U[μ][:,:,2,1,1,1])
map_U_sequential!(U[μ],staggered_phase!,V)
println(U[μ][:,:,1,1,1,1])
println(U[μ][:,:,2,1,1,1])
end
test()
This is 2D case:
using Gaugefields
function staggered_phase!(A,V,ix,it,NX,NT,NC,μ)
t = it-1
t += ifelse(t<0,NT,0)
t += ifelse(t ≥ NT,-NT,0)
x = ix-1
x += ifelse(x<0,NX,0)
x += ifelse(x ≥ NX,-NX,0)
if μ ==1
η = 1
elseif μ ==2
#η = (-1.0)^(x)
η = ifelse(x%2 == 0,1,-1)
else
error("η should be positive but η = $η")
end
for ic=1:NC
for jc=1:NC
A[jc,ic] *= η
end
end
end
function test()
NX = 4
#NY = 4
#NZ = 4
NT = 4
NC = 3
Nwing = 0
U = Initialize_Gaugefields(NC,Nwing,NX,NT,condition = "cold")
μ = 2
V = similar(U)
for μ=1:2
println(U[μ][:,:,1,1])
println(U[μ][:,:,2,1])
mapfunc!(A,V,ix,it) = staggered_phase!(A,V,ix,it,NX,NT,NC,μ)
map_U_sequential!(U[μ],mapfunc!,V)
println(U[μ][:,:,1,1])
println(U[μ][:,:,2,1])
end
end
test()