Improved support for flow integrators

This commit is contained in:
Alberto Ramos 2021-11-03 11:49:35 +01:00
parent 410a6d7b25
commit d19b3a1132
8 changed files with 154 additions and 66 deletions

View file

@ -21,6 +21,7 @@ dag(a::SU2{T}) where T <: AbstractFloat = inverse(a)
norm(a::SU2{T}) where T <: AbstractFloat = sqrt(abs2(a.t1) + abs2(a.t2)) norm(a::SU2{T}) where T <: AbstractFloat = sqrt(abs2(a.t1) + abs2(a.t2))
norm2(a::SU2{T}) where T <: AbstractFloat = abs2(a.t1) + abs2(a.t2) norm2(a::SU2{T}) where T <: AbstractFloat = abs2(a.t1) + abs2(a.t2)
tr(g::SU2{T}) where T <: AbstractFloat = complex(2.0*real(g.t1), 0.0) tr(g::SU2{T}) where T <: AbstractFloat = complex(2.0*real(g.t1), 0.0)
dev_one(g::SU2{T}) where T <: AbstractFloat = sqrt(( abs2(g.t1 - one(T)) + abs2(g.t2))/2)
""" """
function normalize(a::T) where {T <: Group} function normalize(a::T) where {T <: Group}

View file

@ -12,6 +12,9 @@
inverse(a::SU3{T}) where T <: AbstractFloat = SU3{T}(conj(a.u11),conj(a.u21),(a.u12*a.u23 - a.u13*a.u22), conj(a.u12),conj(a.u22),(a.u13*a.u21 - a.u11*a.u23)) inverse(a::SU3{T}) where T <: AbstractFloat = SU3{T}(conj(a.u11),conj(a.u21),(a.u12*a.u23 - a.u13*a.u22), conj(a.u12),conj(a.u22),(a.u13*a.u21 - a.u11*a.u23))
dag(a::SU3{T}) where T <: AbstractFloat = inverse(a) dag(a::SU3{T}) where T <: AbstractFloat = inverse(a)
tr(a::SU3{T}) where T <: AbstractFloat = a.u11+a.u22+conj(a.u11*a.u22 - a.u12*a.u21) tr(a::SU3{T}) where T <: AbstractFloat = a.u11+a.u22+conj(a.u11*a.u22 - a.u12*a.u21)
dev_one(g::SU3{T}) where T <: AbstractFloat = sqrt(( abs2(g.u11 - one(T)) + abs2(g.u12) + abs2(g.u13) + abs2(g.u21) + abs2(g.u22 - one(T)) + abs2(g.u23) )/6)
function Base.:*(a::SU3{T},b::SU3{T}) where T <: AbstractFloat function Base.:*(a::SU3{T},b::SU3{T}) where T <: AbstractFloat

View file

@ -47,7 +47,7 @@ include("GroupU1.jl")
export U1, U1alg export U1, U1alg
export dot, expm, exp, dag, normalize, inverse, tr, projalg, norm, norm2, isgroup, alg2mat export dot, expm, exp, dag, normalize, inverse, tr, projalg, norm, norm2, isgroup, alg2mat, dev_one
end # module end # module

View file

@ -17,7 +17,7 @@ include("Groups/Groups.jl")
using .Groups using .Groups
export Group, Algebra export Group, Algebra
export SU2, SU2alg, SU3, SU3alg, M3x3, M2x2, U1, U1alg export SU2, SU2alg, SU3, SU3alg, M3x3, M2x2, U1, U1alg
export dot, expm, exp, dag, normalize, inverse, tr, projalg, norm, norm2, isgroup, alg2mat export dot, expm, exp, dag, normalize, inverse, tr, projalg, norm, norm2, isgroup, alg2mat, dev_one
include("Space/Space.jl") include("Space/Space.jl")
@ -41,7 +41,9 @@ using .YM
export ztwist export ztwist
export YMworkspace, GaugeParm, force0_wilson!, field, field_pln, randomize!, zero!, norm2 export YMworkspace, GaugeParm, force0_wilson!, field, field_pln, randomize!, zero!, norm2
export gauge_action, hamiltonian, plaquette, HMC!, OMF4! export gauge_action, hamiltonian, plaquette, HMC!, OMF4!
export wfl_euler, wfl_rk3, zfl_euler, zfl_rk3, Eoft_clover, Eoft_plaq, Qtop export Eoft_clover, Eoft_plaq, Qtop
export FlowIntr, wfl_euler, zfl_euler, wfl_rk2, zfl_rk2, wfl_rk3, zfl_rk3
export flw, flw_adapt
export sfcoupling export sfcoupling
end # module end # module

View file

@ -137,7 +137,9 @@ include("YMhmc.jl")
export gauge_action, hamiltonian, plaquette, HMC!, OMF4! export gauge_action, hamiltonian, plaquette, HMC!, OMF4!
include("YMflow.jl") include("YMflow.jl")
export wfl_euler, wfl_rk3, zfl_euler, zfl_rk3, Eoft_clover, Eoft_plaq, Qtop export FlowIntr, flw, flw_adapt
export Eoft_clover, Eoft_plaq, Qtop
export FlowIntr, wfl_euler, zfl_euler, wfl_rk2, zfl_rk2, wfl_rk3, zfl_rk3
include("YMsf.jl") include("YMsf.jl")
export sfcoupling export sfcoupling

View file

@ -9,6 +9,68 @@
### created: Sat Sep 25 08:37:14 2021 ### created: Sat Sep 25 08:37:14 2021
### ###
struct FlowIntr{N,T}
r::T
e0::NTuple{N,T}
e1::NTuple{N,T}
add_zth::Bool
c0::T
eps::T
tol::T
eps_ini::T
max_eps::T
sft_fac::T
end
# pre-defined integrators
wfl_euler(::Type{T}, eps::T, tol::T) where T = FlowIntr{0,T}(one(T),(),(),false,one(T),eps,tol,one(T)/200,one(T)/10,9/10)
zfl_euler(::Type{T}, eps::T, tol::T) where T = FlowIntr{0,T}(one(T),(),(),true, (one(T)*5)/3,eps,tol,one(T)/200,one(T)/10,9/10)
wfl_rk2(::Type{T}, eps::T, tol::T) where T = FlowIntr{1,T}(one(T)/2,(-one(T)/2,),(one(T),),false,one(T),eps,tol,one(T)/200,one(T)/10,9/10)
zfl_rk2(::Type{T}, eps::T, tol::T) where T = FlowIntr{1,T}(one(T)/2,(-one(T)/2,),(one(T),),true, (one(T)*5)/3,eps,tol,one(T)/200,one(T)/10,9/10)
wfl_rk3(::Type{T}, eps::T, tol::T) where T = FlowIntr{2,T}(one(T)/4,(-17/36,-one(T)),(8/9,3/4),false,one(T),eps,tol,one(T)/200,one(T)/10,9/10)
zfl_rk3(::Type{T}, eps::T, tol::T) where T = FlowIntr{2,T}(one(T)/4,(-17/36,-one(T)),(8/9,3/4),true, (one(T)*5)/3,eps,tol,one(T)/200,one(T)/10,9/10)
function Base.show(io::IO, int::FlowIntr{N,T}) where {N,T}
if (abs(int.c0-1) < 1.0E-10)
println(io, "WILSON flow integrator")
elseif (abs(int.c0-5/3) < 1.0E-10) && int.add_zth
println(io, "ZEUTHEN flow integrator")
elseif (abs(int.c0-5/3) < 1.0E-10) && !int.add_zth
println(io, "SYMANZIK flow integrator")
else
println(io, "CUSTOM flow integrator")
if int.add_zth
println(io, " - ", int.c0, " (with zeuthen term)")
else
println(io, " - ", int.c0)
end
end
if N == 0
println(io, " * Euler schem3")
elseif N == 1
println(io, " * One stage scheme. Coefficients3")
println(io, " stg 1: ", int.e0[1], " ", int.e1[1])
elseif N == 2
println(io, " * Two stage scheme. Coefficients:")
println(io, " stg 1: ", int.e0[1], " ", int.e1[1])
println(io, " stg 2: ", int.e0[2], " ", int.e1[2])
end
println(io, " * Fixed step size parameters: eps = ", int.eps)
println(io, " * Adaptive step size parameters: tol = ", int.tol)
println(io, " - max eps: ", int.max_eps)
println(io, " - initial eps: ", int.eps_ini)
println(io, " - safety scale: ", int.sft_fac)
return nothing
end
""" """
function add_zth_term(ymws::YMworkspace, U, lp) function add_zth_term(ymws::YMworkspace, U, lp)
@ -73,69 +135,82 @@ function krnl_add_zth!(frc, frc2::AbstractArray{TA}, U::AbstractArray{TG}, lp::S
return nothing return nothing
end end
function flw(U, int::FlowIntr{NI,T}, ns::Int64, eps, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) where {NI,T}
function flw_euler(U, ns, eps, c0, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace; add_zth=false) @timeit "Integrating flow equations" begin
@timeit "Integrating flow equations (Euler)" begin
for i in 1:ns for i in 1:ns
force_gauge(ymws, U, c0, 1, gp, lp) force_gauge(ymws, U, int.c0, 1, gp, lp)
if add_zth if int.add_zth
add_zth_term(ymws::YMworkspace, U, lp)
end
U .= expm.(U, ymws.frc1, 2*eps)
end
end
return nothing
end
function flw_rk3(U, ns, eps, c0, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace; add_zth=false)
@timeit "Integrating flow equations (RK3)" begin
for i in 1:ns
e0 = eps/2
force_gauge(ymws, U, c0, 1, gp, lp)
if add_zth
add_zth_term(ymws::YMworkspace, U, lp) add_zth_term(ymws::YMworkspace, U, lp)
end end
ymws.mom .= ymws.frc1 ymws.mom .= ymws.frc1
U .= expm.(U, ymws.mom, e0) U .= expm.(U, ymws.mom, 2*eps*int.r)
e0 = -34*eps/36 for k in 1:NI
e1 = 16*eps/9 force_gauge(ymws, U, int.c0, 1, gp, lp)
force_gauge(ymws, U, c0, 1, gp, lp) if int.add_zth
if add_zth add_zth_term(ymws::YMworkspace, U, lp)
add_zth_term(ymws::YMworkspace, U, lp) end
ymws.mom .= int.e0[k].*ymws.mom .+ int.e1[k].*ymws.frc1
U .= expm.(U, ymws.mom, 2*eps)
end end
ymws.mom .= e0.*ymws.mom .+ e1.*ymws.frc1
U .= expm.(U, ymws.mom)
e1 = 6*eps/4
force_gauge(ymws, U, c0, 1, gp, lp)
if add_zth
add_zth_term(ymws::YMworkspace, U, lp)
end
ymws.mom .= e1.*ymws.frc1 .- ymws.mom
U .= expm.(U, ymws.mom)
end end
end end
return nothing return nothing
end end
flw(U, int::FlowIntr{NI,T}, ns::Int64, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) where {NI,T} = flw(U, int, ns, int.eps, gp, lp, ymws)
##
# Adaptive step size integrators
##
function flw_adapt(U, int::FlowIntr{NI,T}, tend::T, epsini::T, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) where {NI,T}
wfl_euler(U, ns, eps, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) = flw_euler(U, ns, eps, 1, gp, lp, ymws)
zfl_euler(U, ns, eps, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) = flw_euler(U, ns, eps, 5.0/3.0, gp, lp, ymws, add_zth=true) eps = int.eps_ini
wfl_rk3(U, ns, eps, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) = flw_rk3(U, ns, eps, 1, gp, lp, ymws) dt = tend
zfl_rk3(U, ns, eps, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) = flw_rk3(U, ns, eps, 5.0/3.0, gp, lp, ymws, add_zth=true) nstp = 0
while true
ns = convert(Int64, floor(dt/eps))
if ns > 10
flw(U, int, 9, eps, gp, lp, ymws)
ymws.U1 .= U
flw(U, int, 2, eps/2, gp, lp, ymws)
flw(ymws.U1, int, 1, eps, gp, lp, ymws)
dt = dt - 10*eps
nstp = nstp + 10
# adjust step size
ymws.U1 .= ymws.U1 ./ U
maxd = CUDA.mapreduce(dev_one, max, ymws.U1, init=zero(tend))
eps = min(int.max_eps, 2*eps, int.sft_fac*eps*(int.tol/maxd)^(one(tend)/3))
else
flw(U, int, ns, eps, gp, lp, ymws)
dt = dt - ns*eps
flw(U, int, 1, dt, gp, lp, ymws)
dt = zero(tend)
nstp = nstp + ns + 1
end
if dt == zero(tend)
break
end
end
return nstp, eps
end
flw_adapt(U, int::FlowIntr{NI,T}, tend::T, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) where {NI,T} = flw_adapt(U, int, tend, int.eps_ini, gp, lp, ymws)
## ##
# Observables # Observables
## ##
""" """
function Eoft_plaq([Eslc,] U, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace) function Eoft_plaq([Eslc,] U, gp::GaugeParm, lp::SpaceParm, ymws::YMworkspace)
@ -151,7 +226,7 @@ function Eoft_plaq(Eslc, U, gp::GaugeParm{T}, lp::SpaceParm{N,M,B,D}, ymws::YMwo
tp = ntuple(i->i, N-1) tp = ntuple(i->i, N-1)
V3 = prod(lp.iL[1:end-1]) V3 = prod(lp.iL[1:end-1])
fill!(Eslc,zero(T)) fill!(Eslc,zero(T))
Etmp = zeros(T,lp.iL[end]) Etmp = zeros(T,lp.iL[end])
for ipl in 1:M for ipl in 1:M
@ -159,8 +234,8 @@ function Eoft_plaq(Eslc, U, gp::GaugeParm{T}, lp::SpaceParm{N,M,B,D}, ymws::YMwo
CUDA.@sync begin CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_plaq_pln!(ymws.cm, U, gp.Ubnd, ztw[ipl], ipl, lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_plaq_pln!(ymws.cm, U, gp.Ubnd, ztw[ipl], ipl, lp)
end end
Etmp .= (gp.ng .- reshape(Array(CUDA.mapreduce(real, +, ymws.cm;dims=tp)),lp.iL[end])/V3 ) Etmp .= (gp.ng .- reshape(Array(CUDA.mapreduce(real, +, ymws.cm;dims=tp)),lp.iL[end]) ./ V3 )
if ipl < N if ipl < N
for it in 2:lp.iL[end] for it in 2:lp.iL[end]
Eslc[it,ipl] = Etmp[it] + Etmp[it-1] Eslc[it,ipl] = Etmp[it] + Etmp[it-1]
@ -201,7 +276,7 @@ function krnl_plaq_pln!(plx, U::AbstractArray{T}, Ubnd::T, ztw, ipl, lp::SpacePa
end end
I = point_coord((b,r), lp) I = point_coord((b,r), lp)
plx[I] = ztw*tr(U[b,1,r]*gt / (U[b,2,r]*U[bu2,id1,ru2])) plx[I] = ztw*tr(U[b,id1,r]*gt / (U[b,id2,r]*U[bu2,id1,ru2]))
return nothing return nothing
end end
@ -219,22 +294,23 @@ function Qtop(Qslc, U, gp::GaugeParm, lp::SpaceParm{4,M,B,D}, ymws::YMworkspace)
ztw = ztwist(gp, lp) ztw = ztwist(gp, lp)
tp = (1,2,3) tp = (1,2,3)
fill!(ymws.rm, zero(eltype(ymws.rm)))
CUDA.@sync begin CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_field_tensor!(ymws.frc1, ymws.frc2, U, gp.Ubnd, 1,6, ztw[1], ztw[5], lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_field_tensor!(ymws.frc1, ymws.frc2, U, gp.Ubnd, 1,6, ztw[1], ztw[6], lp)
end end
CUDA.@sync begin CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_add_qd!(ymws.rm, -, ymws.frc1, ymws.frc2, U, lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_add_qd!(ymws.rm, -, ymws.frc1, ymws.frc2, U, lp)
end end
CUDA.@sync begin CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_field_tensor!(ymws.frc1, ymws.frc2, U, gp.Ubnd, 2,5, ztw[2], ztw[4], lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_field_tensor!(ymws.frc1, ymws.frc2, U, gp.Ubnd, 2,5, ztw[2], ztw[5], lp)
end end
CUDA.@sync begin CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_add_qd!(ymws.rm, +, ymws.frc1, ymws.frc2, U, lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_add_qd!(ymws.rm, +, ymws.frc1, ymws.frc2, U, lp)
end end
CUDA.@sync begin CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_field_tensor!(ymws.frc1, ymws.frc2, U, gp.Ubnd, 3,4, ztw[3], ztw[6], lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_field_tensor!(ymws.frc1, ymws.frc2, U, gp.Ubnd, 3,4, ztw[3], ztw[4], lp)
end end
CUDA.@sync begin CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_add_qd!(ymws.rm, -, ymws.frc1, ymws.frc2, U, lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_add_qd!(ymws.rm, -, ymws.frc1, ymws.frc2, U, lp)

View file

@ -37,7 +37,7 @@ function gauge_action(U, lp::SpaceParm, gp::GaugeParm{T}, ymws::YMworkspace{T})
return S return S
end end
function plaquette(U, lp::SpaceParm, gp::GaugeParm, ymws::YMworkspace) function plaquette(U, lp::SpaceParm{N,M,B,D}, gp::GaugeParm, ymws::YMworkspace) where {N,M,B,D}
ztw = ztwist(gp, lp) ztw = ztwist(gp, lp)
@timeit "Plaquette measurement" begin @timeit "Plaquette measurement" begin
@ -45,7 +45,7 @@ function plaquette(U, lp::SpaceParm, gp::GaugeParm, ymws::YMworkspace)
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_plaq!(ymws.cm, U, gp.Ubnd, one(gp.cG[1]), ztw, lp) CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_plaq!(ymws.cm, U, gp.Ubnd, one(gp.cG[1]), ztw, lp)
end end
end end
return CUDA.mapreduce(real, +, ymws.cm)/(prod(lp.iL)*lp.npls) return CUDA.mapreduce(real, +, ymws.cm)/(prod(lp.iL)*lp.npls)
end end

View file

@ -7,7 +7,7 @@ Pkg.activate("/lhome/ific/a/alramos/s.images/julia/workspace/LatticeGPU")
using LatticeGPU using LatticeGPU
# Set lattice/block size # Set lattice/block size
ntwist = (0,0,0,1,0,0) ntwist = (0,0,0,0,0,0)
lp = SpaceParm{4}((32,32,32,32), (4,4,4,4), BC_PERIODIC, ntwist) lp = SpaceParm{4}((32,32,32,32), (4,4,4,4), BC_PERIODIC, ntwist)
println("Space Parameters: ", lp) println("Space Parameters: ", lp)
@ -44,6 +44,8 @@ println("\n## WILSON ACTION/FLOW TIMES")
gp = GaugeParm{PREC}(GRP{PREC}, 6.0, 1.0, (0.5,0.5)) gp = GaugeParm{PREC}(GRP{PREC}, 6.0, 1.0, (0.5,0.5))
println("Gauge Parameters: ", gp) println("Gauge Parameters: ", gp)
flwint = wfl_rk3(PREC, 0.005, 1.0E-6)
println(flwint)
println("Initial Action: ") println("Initial Action: ")
@time S = gauge_action(U, lp, gp, ymws) @time S = gauge_action(U, lp, gp, ymws)
@ -62,11 +64,12 @@ for i in 1:4
# println("SF coupling: ", x, " ", y) # println("SF coupling: ", x, " ", y)
end end
wfl_rk3(U, 1, 0.01, gp, lp, ymws) Ucp = Array(U)
println("Action: ", gauge_action(U, lp, gp, ymws)) println("Action: ", gauge_action(U, lp, gp, ymws))
flw(U, flwint, 1, gp, lp, ymws)
println("Time for 100 steps of RK3 flow integrator: ") println("Time for 100 steps of RK3 flow integrator: ")
@time wfl_rk3(U, 100, 0.01, gp, lp, ymws) @time flw(U, flwint, 400, gp, lp, ymws)
eoft = Eoft_plaq(U, gp, lp, ymws) eoft = Eoft_plaq(U, gp, lp, ymws)
eoft = Eoft_clover(U, gp, lp, ymws) eoft = Eoft_clover(U, gp, lp, ymws)
qtop = Qtop(U, gp, lp, ymws) qtop = Qtop(U, gp, lp, ymws)
@ -77,8 +80,6 @@ println("Plaq: ", eoft)
println("Clov: ", eoft) println("Clov: ", eoft)
@time qtop = Qtop(U, gp, lp, ymws) @time qtop = Qtop(U, gp, lp, ymws)
println("Qtop: ", qtop) println("Qtop: ", qtop)
println("Action: ", gauge_action(U, lp, gp, ymws))
println("## END Wilson action/flow measurements") println("## END Wilson action/flow measurements")
# Set gauge parameters # Set gauge parameters
@ -87,6 +88,9 @@ println("\n## IMPROVED ACTION/FLOW TIMES")
gp = GaugeParm{PREC}(GRP{PREC}, 6.0, 5/6, (0.5,0.5)) gp = GaugeParm{PREC}(GRP{PREC}, 6.0, 5/6, (0.5,0.5))
println("Gauge Parameters: ", gp) println("Gauge Parameters: ", gp)
flwint = zfl_rk3(PREC, 0.01, 1.0E-6)
println(flwint)
println("Initial Action: ") println("Initial Action: ")
@time S = gauge_action(U, lp, gp, ymws) @time S = gauge_action(U, lp, gp, ymws)
@ -100,11 +104,11 @@ for i in 1:4
println("# Plaquette: ", pl[end], "\n") println("# Plaquette: ", pl[end], "\n")
end end
zfl_rk3(U, 1, 0.01, gp, lp, ymws) flw(U, flwint, 1, gp, lp, ymws)
println("Action: ", gauge_action(U, lp, gp, ymws)) println("Action: ", gauge_action(U, lp, gp, ymws))
println("Time for 100 steps of RK3 flow integrator: ") println("Time for 100 steps of RK3 flow integrator: ")
@time zfl_rk3(U, 100, 0.01, gp, lp, ymws) @time flw(U, flwint, 100, gp, lp, ymws)
println("Action: ", gauge_action(U, lp, gp, ymws)) println("Action: ", gauge_action(U, lp, gp, ymws))
println("## END improved action/flow measurements") println("## END improved action/flow measurements")