Working multi-precision simulations

The pure gauge theory with groups SU(2) and SU(3) is working
properly.
This commit is contained in:
Alberto Ramos 2021-09-20 18:21:16 +02:00
parent 1416efdbee
commit 09a09153b9
8 changed files with 188 additions and 283 deletions

View file

@ -16,46 +16,53 @@ using CUDA, Random, StructArrays
using ..Space
using ..Groups
struct GaugeParm
beta::Float64
cG::Tuple{Float64,Float64}
ng::Int32
struct GaugeParm{T}
beta::T
cG::NTuple{2,T}
ng::Int64
end
export GaugeParm
include("YMfields.jl")
export field, field_pln, randomn!, zero!, norm2
struct YMworkspace
struct YMworkspace{T}
GRP
ALG
PRC
frc1
frc2
mom
U1
cm # complex of volume
rm # float of volume
function YMworkspace(::Type{T}, lp::SpaceParm) where {T <: Union{Group,Algebra}}
function YMworkspace(::Type{G}, ::Type{T}, lp::SpaceParm) where {G <: Group, T <: AbstractFloat}
if (T == SU2)
f1 = field(SU2alg, lp)
f2 = field(SU2alg, lp)
mm = field(SU2alg, lp)
u1 = field(SU2, lp)
if (G == SU2)
GRP = SU2
ALG = SU2alg
f1 = field(SU2alg, T, lp)
f2 = field(SU2alg, T, lp)
mm = field(SU2alg, T, lp)
u1 = field(SU2, T, lp)
end
if (T == SU3)
f1 = field(SU3alg, lp)
f2 = field(SU3alg, lp)
mm = field(SU3alg, lp)
u1 = field(SU3, lp)
if (G == SU3)
GRP = SU3
ALG = SU3alg
f1 = field(SU3alg, T, lp)
f2 = field(SU3alg, T, lp)
mm = field(SU3alg, T, lp)
u1 = field(SU3, T, lp)
end
cs = CuArray{ComplexF64, 2}(undef, lp.bsz,lp.rsz)
rs = CuArray{Float64, 2}(undef, lp.bsz,lp.rsz)
cs = CuArray{Complex{T}, 2}(undef, lp.bsz,lp.rsz)
rs = CuArray{T, 2}(undef, lp.bsz,lp.rsz)
return new(f1, f2, mm, u1, cs, rs)
return new{T}(GRP,ALG,T,f1, f2, mm, u1, cs, rs)
end
end
export YMworkspace
include("YMfields.jl")
export field, field_pln, randomize!, zero!, norm2
include("YMact.jl")
export krnl_plaq!, force0_wilson!

View file

@ -16,7 +16,7 @@ function krnl_plaq!(plx, U, ipl, lp::SpaceParm)
bu1, ru1 = up((b, r), id1, lp)
bu2, ru2 = up((b, r), id2, lp)
@inbounds plx[b, r] = tr(U[b,r,id1]*U[bu1,ru1,id2] / (U[b,r,id2]*U[bu2,ru2,id1]))
@inbounds plx[b, r] = tr(U[b,id1,r]*U[bu1,id2,ru1] / (U[b,id2,r]*U[bu2,id1,ru2]))
return nothing
end
@ -24,33 +24,14 @@ end
function krnl_plaq!(plx, U, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
if (b < 1) || (b > lp.bsz)
@cuprintln("Error b: %b, %r")
end
if (r < 1) || (r > lp.rsz)
@cuprintln("Error r: %b, %r")
end
plx[b,r] = complex(0.0)
for ipl in 1:lp.npls
id1, id2 = lp.plidx[ipl]
bu1, ru1 = up((b, r), id1, lp)
bu2, ru2 = up((b, r), id2, lp)
if (bu1 < 1) || (bu1 > lp.bsz)
@cuprintln("Error bu1: %b, %r, %id1")
end
if (ru1 < 1) || (ru1 > lp.rsz)
@cuprintln("Error ru1: %b, %r, %id1")
end
if (bu2 < 1) || (bu2 > lp.bsz)
@cuprintln("Error bu2: %b, %r, %id2")
end
if (ru2 < 1) || (ru2 > lp.rsz)
@cuprintln("Error ru2: %b, %r, %id2")
end
plx[b,r] += tr(U[r,id1,b]*U[bu1,id2,ru1] / (U[b,id2,r]*U[bu2,id1,ru2]))
plx[b,r] = zero(plx[b,r])
@inbounds for ipl in 1:lp.npls
id1, id2 = lp.plidx[ipl]
bu1, ru1 = up((b, r), id1, lp)
bu2, ru2 = up((b, r), id2, lp)
plx[b,r] += tr(U[b,id1,r]*U[bu1,id2,ru1] / (U[b,id2,r]*U[bu2,id1,ru2]))
end
return nothing
@ -72,10 +53,10 @@ function krnl_force_wilson_pln!(frc1, frc2, U, ipl, lp::SpaceParm)
F2 = projalg(g1*g2)
F3 = projalg(g2*g1)
frc1[b ,r,id1 ] -= F1
frc1[b ,r,id2 ] += F1
frc2[bu1,ru1,id2] -= F2
frc2[bu2,ru2,id1] += F3
frc1[b ,id1, r ] -= F1
frc1[b ,id2, r ] += F1
frc2[bu1,id2,ru1] -= F2
frc2[bu2,id1,ru2] += F3
end
return nothing
@ -125,8 +106,8 @@ function krnl_force_wilson!(frc, U, lp::SpaceParm)
F2 = projalg((U[b,id2,r]/(U[bd1,id2,rd1]*U[bdu,id1,rdu]))*U[bd1,id1,rd1])
F3 = projalg((U[bd2,id2,rd2]\U[bd2,id1,rd2])*(U[bud,id2,rud]/U[b,id1,r]))
frc[b,r,id1] -= F1 - F3
frc[b,r,id2] += F1 - F2
frc[b,id1,r] -= F1 - F3
frc[b,id2,r] += F1 - F2
end
end
@ -138,29 +119,30 @@ function krnl_add_force_plns!(frc, fpl, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
@inbounds for ipl in 1:lp.npls
id1, id2 = lp.plidx[ipl]
frc[b,r,id1] += fpl[b,ipl,r,1,1] + fpl[b,ipl,r,1,2]
frc[b,r,id2] += fpl[b,ipl,r,2,1] + fpl[b,ipl,r,2,2]
frc[b,id1,r] += fpl[b,ipl,r,1,1] + fpl[b,ipl,r,1,2]
frc[b,id2,r] += fpl[b,ipl,r,2,1] + fpl[b,ipl,r,2,2]
end
return nothing
end
function force0_wilson_pln!(frc1, frc2, U, lp::SpaceParm)
function force0_wilson_pln!(frc1, ftmp, U, lp::SpaceParm)
zero!(frc1, lp)
zero!(frc2, lp)
fill!(frc1, zero(eltype(frc1)))
fill!(ftmp, zero(eltype(ftmp)))
for i in 1:lp.npls
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_force_wilson_pln!(frc1,frc2,U,i,lp)
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_force_wilson_pln!(frc1,ftmp,U,i,lp)
end
end
frc1 .= frc1 .+ ftmp
return nothing
end
function force0_wilson!(frc1, U, lp::SpaceParm)
zero!(frc1, lp)
fill!(frc1, zero(eltype(frc1)))
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_force_wilson!(frc1,U,lp)
end
@ -173,7 +155,7 @@ function force0_wilson_nw!(frc1, fpln, U, lp::SpaceParm)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz*lp.npls krnl_force_wilson_nw!(fpln,U,lp)
end
zero!(frc1, lp)
fill!(frc1, zero(eltype(frc1)))
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_add_force_plns!(frc1, fpln,lp)
end

View file

@ -11,196 +11,66 @@
un(t) = t <: Union{Group, Complex}
function field(::Type{T}, lp::SpaceParm) where {T <: Union{Group, Algebra}}
function field(::Type{G}, ::Type{T}, lp::SpaceParm) where {G <: Union{Group, Algebra}, T <: AbstractFloat}
sz = lp.bsz, lp.ndim, lp.rsz
if (T == SU2)
if (G == SU2)
# As = StructArray{SU2}(undef, sz, unwrap=un)
return CuArray{SU2, 3}(undef, sz)
elseif (T == SU2alg)
return CuArray{SU2{T}, 3}(undef, sz)
elseif (G == SU2alg)
# As = StructArray{SU2alg}(undef, sz, unwrap=un)
return CuArray{SU2alg, 3}(undef, sz)
elseif (T == SU3)
return CuArray{SU2alg{T}, 3}(undef, sz)
elseif (G == SU3)
# As = StructArray{SU3}(undef, sz, unwrap=un)
return CuArray{SU3, 3}(undef, sz)
return CuArray{SU3{T}, 3}(undef, sz)
# As = Array{SU3, lp.ndim+1}(undef, sz)
elseif (T == SU3alg)
elseif (G == SU3alg)
# As = StructArray{SU3alg}(undef, sz, unwrap=un)
return CuArray{SU3alg, 3}(undef, sz)
return CuArray{SU3alg{T}, 3}(undef, sz)
# As = Array{SU3alg, lp.ndim+1}(undef, sz)
end
return replace_storage(CuArray, As)
end
function krnl_SU3_one!(G, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
G[b,id,r] = SU3(1.0,0.0,0.0,0.0,1.0,0.0)
end
return nothing
end
function krnl_SU2_one!(G, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
G[b,id,r] = SU2(1.0,0.0)
end
return nothing
end
function krnl_SU3alg_zero!(G, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
G[b,id,r] = SU3alg(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0)
end
return nothing
end
function krnl_SU2alg_zero!(G, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
G[b,id,r] = SU2alg(0.0,0.0,0.0)
end
return nothing
end
function krnl_SU3alg_assign!(G, M, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
G[b,id,r] = SU3alg(M[b,id,r,1], M[b,id,r,2], M[b,id,r,3], M[b,id,r,4],
M[b,id,r,5], M[b,id,r,6], M[b,id,r,7], M[b,id,r,8])
end
return nothing
end
function krnl_SU2alg_assign!(G, M, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
G[b,id,r] = SU2alg(M[b,id,r,1], M[b,id,r,2], M[b,id,r,3])
end
return nothing
end
function randomn!(X, lp)
if (eltype(X) == SU2alg)
# randn!(CURAND.default_rng(), LazyRows(X).t1)
# randn!(CURAND.default_rng(), LazyRows(X).t2)
# randn!(CURAND.default_rng(), LazyRows(X).t3)
M = CuArray{Float64}(undef, lp.bsz, lp.ndim, lp.rsz, 3)
randn!(CURAND.default_rng(), M)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_SU2alg_assign!(X, M, lp)
end
elseif (eltype(X) == SU3alg)
# randn!(CURAND.default_rng(), LazyRows(X).t1)
# randn!(CURAND.default_rng(), LazyRows(X).t2)
# randn!(CURAND.default_rng(), LazyRows(X).t3)
# randn!(CURAND.default_rng(), LazyRows(X).t4)
# randn!(CURAND.default_rng(), LazyRows(X).t5)
# randn!(CURAND.default_rng(), LazyRows(X).t6)
# randn!(CURAND.default_rng(), LazyRows(X).t7)
# randn!(CURAND.default_rng(), LazyRows(X).t8)
M = CuArray{Float64}(undef, lp.bsz, lp.ndim, lp.rsz, 8)
randn!(CURAND.default_rng(), M)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_SU3alg_assign!(X, M, lp)
end
end
return nothing
end
function zero!(X, lp)
if (eltype(X) == SU2alg)
# fill!(LazyRows(X).t1, 0.0)
# fill!(LazyRows(X).t2, 0.0)
# fill!(LazyRows(X).t3, 0.0)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_SU2alg_zero!(X, lp)
end
end
if (eltype(X) == SU3alg)
# fill!(LazyRows(X).t1, 0.0)
# fill!(LazyRows(X).t2, 0.0)
# fill!(LazyRows(X).t3, 0.0)
# fill!(LazyRows(X).t4, 0.0)
# fill!(LazyRows(X).t5, 0.0)
# fill!(LazyRows(X).t6, 0.0)
# fill!(LazyRows(X).t7, 0.0)
# fill!(LazyRows(X).t8, 0.0)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_SU3alg_zero!(X, lp)
end
end
if (eltype(X) == SU2)
# fill!(LazyRows(X).t1.re, 1.0)
# fill!(LazyRows(X).t1.im, 0.0)
# fill!(LazyRows(X).t2.re, 0.0)
# fill!(LazyRows(X).t2.im, 0.0)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_SU2_one!(X, lp)
end
end
if (eltype(X) == SU3)
# fill!(LazyRows(X).u11.re, 1.0)
# fill!(LazyRows(X).u11.im, 0.0)
# fill!(LazyRows(X).u12.re, 0.0)
# fill!(LazyRows(X).u12.im, 0.0)
# fill!(LazyRows(X).u13.re, 0.0)
# fill!(LazyRows(X).u13.im, 0.0)
# fill!(LazyRows(X).u21.re, 0.0)
# fill!(LazyRows(X).u21.im, 0.0)
# fill!(LazyRows(X).u22.re, 1.0)
# fill!(LazyRows(X).u22.im, 0.0)
# fill!(LazyRows(X).u23.re, 0.0)
# fill!(LazyRows(X).u23.im, 0.0)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_SU3_one!(X, lp)
end
end
return nothing
end
function randomize!(f, lp::SpaceParm, ymws::YMworkspace)
function norm_field(X)
return CUDA.mapreduce(norm2, +, X)
# d = 0.0
if (eltype(X) == SU2alg)
# d = CUDA.mapreduce(x->x^2, +, LazyRows(X).t1) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t2) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t3)
elseif (eltype(X) == SU3alg)
# d = CUDA.mapreduce(x->x^2, +, LazyRows(X).t1) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t2) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t3) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t4) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t5) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t6) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t7) +
# CUDA.mapreduce(x->x^2, +, LazyRows(X).t8)
d = CUDA.mapreduce(norm2, +, X)
if ymws.ALG == SU2alg
m = CUDA.randn(ymws.PRC, lp.bsz,lp.ndim,3,lp.rsz)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_assign_SU2!(f,m,lp)
end
return nothing
end
return d
if ymws.ALG == SU3alg
m = CUDA.randn(ymws.PRC, lp.bsz,lp.ndim,8,lp.rsz)
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_assign_SU3!(f,m,lp)
end
return nothing
end
return nothing
end
function krnl_assign_SU3!(frc, m, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
frc[b,id,r] = SU3alg(m[b,id,1,r], m[b,id,2,r], m[b,id,3,r],
m[b,id,4,r], m[b,id,5,r], m[b,id,6,r],
m[b,id,7,r], m[b,id,8,r])
end
return nothing
end
function krnl_assign_SU2!(frc, m, lp::SpaceParm)
b, r = CUDA.threadIdx().x, CUDA.blockIdx().x
for id in 1:lp.ndim
frc[b,id,r] = SU2alg(m[b,id,1,r], m[b,id,2,r], m[b,id,3,r])
end
return nothing
end

View file

@ -9,7 +9,7 @@
### created: Thu Jul 15 11:27:28 2021
###
function gauge_action(U, lp::SpaceParm, gp::GaugeParm, ymws::YMworkspace)
function gauge_action(U, lp::SpaceParm, gp::GaugeParm{T}, ymws::YMworkspace{T}) where T <: AbstractFloat
CUDA.@sync begin
CUDA.@cuda threads=lp.bsz blocks=lp.rsz krnl_plaq!(ymws.cm, U, lp)
@ -32,7 +32,7 @@ function plaquette(U, lp::SpaceParm, gp::GaugeParm, ymws::YMworkspace)
end
function hamiltonian(mom, U, lp, gp, ymws)
K = norm_field(mom)/2.0
K = CUDA.mapreduce(norm2, +, mom)/2
V = gauge_action(U, lp, gp, ymws)
println("K: ", K, " V: ", V)
return K+V
@ -42,7 +42,7 @@ function HMC!(U, eps, ns, lp::SpaceParm, gp::GaugeParm, ymws::YMworkspace; noacc
ymws.U1 .= U
randomn!(ymws.mom, lp)
randomize!(ymws.mom, lp, ymws)
hini = hamiltonian(ymws.mom, U, lp, gp, ymws)
OMF4!(ymws.mom, U, eps, ns, lp, gp, ymws)
@ -78,14 +78,14 @@ function krnl_updt!(mom, frc1, frc2, eps1, U, eps2, lp::SpaceParm)
return nothing
end
function OMF4!(mom, U, eps, ns, lp::SpaceParm, gp::GaugeParm, ymws::YMworkspace)
function OMF4!(mom, U, eps, ns, lp::SpaceParm, gp::GaugeParm{T}, ymws::YMworkspace{T}) where T <: AbstractFloat
r1::Float64 = 0.08398315262876693
r2::Float64 = 0.2539785108410595
r3::Float64 = 0.6822365335719091
r4::Float64 = -0.03230286765269967
r5::Float64 = 0.5-r1-r3
r6::Float64 = 1.0-2.0*(r2+r4)
r1::T = 0.08398315262876693
r2::T = 0.2539785108410595
r3::T = 0.6822365335719091
r4::T = -0.03230286765269967
r5::T = 0.5-r1-r3
r6::T = 1.0-2.0*(r2+r4)
# ee = eps*gp.beta/gp.ng
# @device_code_warntype force0_wilson!(ymws.frc1,ymws.frc2, U, lp, gp)
@ -129,36 +129,35 @@ function OMF4!(mom, U, eps, ns, lp::SpaceParm, gp::GaugeParm, ymws::YMworkspace)
# end
ee = eps*gp.beta/gp.ng
force0_wilson!(ymws.frc1, U, lp)
zero!(ymws.frc2, lp)
force0_wilson_pln!(ymws.frc1, ymws.frc2, U, lp)
for i in 1:ns
# STEP 1
mom .= mom .+ (r1*ee) .* (ymws.frc1 .+ ymws.frc2)
mom .= mom .+ (r1*ee) .* ymws.frc1
U .= expm.(U, mom, eps*r2)
# STEP 2
force0_wilson!(ymws.frc1, U, lp)
mom .= mom .+ (r3*ee) .* (ymws.frc1 .+ ymws.frc2)
force0_wilson_pln!(ymws.frc1, ymws.frc2, U, lp)
mom .= mom .+ (r3*ee) .* ymws.frc1
U .= expm.(U, mom, eps*r4)
# STEP 3
force0_wilson!(ymws.frc1, U, lp)
mom .= mom .+ (r5*ee) .* (ymws.frc1 .+ ymws.frc2)
force0_wilson_pln!(ymws.frc1, ymws.frc2, U, lp)
mom .= mom .+ (r5*ee) .* ymws.frc1
U .= expm.(U, mom, eps*r6)
# STEP 4
force0_wilson!(ymws.frc1, U, lp)
mom .= mom .+ (r5*ee) .* (ymws.frc1 .+ ymws.frc2)
force0_wilson_pln!(ymws.frc1, ymws.frc2, U, lp)
mom .= mom .+ (r5*ee) .* ymws.frc1
U .= expm.(U, mom, eps*r4)
# STEP 5
force0_wilson!(ymws.frc1, U, lp)
mom .= mom .+ (r3*ee) .* (ymws.frc1 .+ ymws.frc2)
force0_wilson_pln!(ymws.frc1, ymws.frc2, U, lp)
mom .= mom .+ (r3*ee) .* ymws.frc1
U .= expm.(U, mom, eps*r2)
# STEP 6
force0_wilson!(ymws.frc1, U, lp)
mom .= mom .+ (r1*ee) .* (ymws.frc1 .+ ymws.frc2)
force0_wilson_pln!(ymws.frc1, ymws.frc2, U, lp)
mom .= mom .+ (r1*ee) .* ymws.frc1
end
return nothing