diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2df67bf..9fab565 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,7 +30,8 @@ repos: test/.*_wsvec.dat| test/.*\.xsf| test/.*\.cube| - test/.*\.bxsf + test/.*\.bxsf| + test/.*\.txt )$ - id: mixed-line-ending exclude: *exclude_txtfiles diff --git a/src/w90/wout.jl b/src/w90/wout.jl index 58e9522..28701d4 100644 --- a/src/w90/wout.jl +++ b/src/w90/wout.jl @@ -5,6 +5,10 @@ export read_wout Parse wannire90 `wout` file. +# Keyword Arguments +- `iterations`: if `true`, parse all the iterations of disentanglement and + maximal localization. Default is `false`. + # Return - `lattice`: each column is a lattice vector in Å - `recip_lattice`: each column is a reciprocal lattice vector in Å⁻¹ @@ -14,160 +18,400 @@ Parse wannire90 `wout` file. - `spreads`: final each WF spreads in Ų - `ΩI`, `ΩD`, `ΩOD`, `Ωtotal`: final spread (components) in Ų """ -function read_wout(filename::AbstractString) +function read_wout(filename::AbstractString; iterations::Bool=false) return open(filename) do io - start_lattice = "Lattice Vectors (" - start_recip = "Reciprocal-Space Vectors (" - start_atom = "| Site Fractional Coordinate Cartesian Coordinate" - end_atom = "*----------------------------------------------------------------------------*" - start_finalstate = "Final State" - end_finalstate = "Sum of centres and spreads" - marker_wfc = "WF centre and spread" - marker_ΩI = "Omega I =" - marker_ΩD = "Omega D =" - marker_ΩOD = "Omega OD =" - marker_Ωtotal = "Omega Total =" - - ang_unit = false - lattice = nothing - recip_lattice = nothing - atom_labels = nothing - atom_positions = nothing - centers = nothing - spreads = nothing - ΩI = nothing - ΩD = nothing - ΩOD = nothing - Ωtotal = nothing + mark_lattice = "Lattice Vectors (" + mark_recip = "Reciprocal-Space Vectors (" + mark_atom_start = "| Site Fractional Coordinate Cartesian Coordinate" + mark_atom_end = "*----------------------------------------------------------------------------*" + mark_kgrid = "Grid size =" + mark_finalstate_start = "Final State" + mark_finalstate_end = "Sum of centres and spreads" + mark_ΩI = "Omega I =" + mark_ΩD = "Omega D =" + mark_ΩOD = "Omega OD =" + mark_Ωtotal = "Omega Total =" + # convergence history + mark_dis_start = "Extraction of optimally-connected subspace" + mark_dis_end = "Time to disentangle bands" + mark_maxloc_start = "| Iter Delta Spread RMS Gradient Spread (Ang^2) Time |<-- CONV" + mark_maxloc_end = mark_finalstate_start + # parsed results + results = Dict{Symbol,Any}() + iters = Dict{Symbol,Any}() + + srline() = strip(readline(io)) while !eof(io) - line = strip(readline(io)) + line = srline() + if occursin(mark_lattice, line) + lines = String[line] + append!(lines, srline() for _ in 1:3) + push!(results, :lattice => Mat3(_parse_wout_lattice(lines))) + continue + end + if occursin(mark_recip, line) + lines = String[line] + append!(lines, srline() for _ in 1:3) + push!(results, :recip_lattice => Mat3(_parse_wout_recip_lattice(lines))) + continue + end + if occursin(mark_atom_start, line) + lines = String[line] + while line != mark_atom_end + line = srline() + push!(lines, line) + end + atom_labels, atom_positions = _parse_wout_atoms(lines) + push!( + results, :atom_labels => atom_labels, :atom_positions => atom_positions + ) + continue + end + if occursin(mark_kgrid, line) + # parse line `Grid size = 9 x 9 x 9 Total points = 729` + line = split(line)[[4, 6, 8]] + push!(results, :kgrid => parse.(Int, line)) + continue + end + if iterations + if occursin(mark_dis_start, line) + lines = String[line] + while !occursin(mark_dis_end, line) + line = srline() + push!(lines, line) + end + push!(iters, :disentangle => _parse_wout_disentangle(lines)) + continue + end + if occursin(mark_maxloc_start, line) + lines = String[line] + while !occursin(mark_maxloc_end, line) + line = srline() + push!(lines, line) + end + push!(iters, :wannierize => _parse_wout_wannierize(lines)) + # Do not continue: we use the same "Final State" mark for + # checking both the end of max localization and the start of + # final spread. Therefore, we need to proceed with the next + # if block on parsing final state. + end + end + if occursin(mark_finalstate_start, line) + line = srline() + lines = String[line] + while !occursin(mark_finalstate_end, line) + line = srline() + push!(lines, line) + end + c, s, sc, ss = _parse_wout_wf_center_spread(lines) + push!( + results, + :centers => c, + :spreads => s, + :sum_centers => sc, + :sum_spreads => ss, + ) + continue + end + if occursin(mark_ΩI, line) + push!(results, :ΩI => parse_float(split(line, mark_ΩI)[2])) + line = srline() + push!(results, :ΩD => parse_float(split(line, mark_ΩD)[2])) + line = srline() + push!(results, :ΩOD => parse_float(split(line, mark_ΩOD)[2])) + line = srline() + push!(results, :Ωtotal => parse_float(split(line, mark_Ωtotal)[2])) + continue + end + end + iterations && push!(results, :iterations => NamedTuple(iters)) + return NamedTuple(results) + end +end - if occursin(start_lattice, line) - @assert occursin("Ang", line) - ang_unit = true - lattice = zeros(Float64, 3, 3) +""" +Parse block +``` +Lattice Vectors (Ang) +a_1 0.000000 2.715265 2.715265 +a_2 2.715265 0.000000 2.715265 +a_3 2.715265 2.715265 0.000000 +``` +""" +function _parse_wout_lattice(lines) + @assert length(lines) == 4 "wrong number of lines for lattice" + ang_unit = occursin("Lattice Vectors (Ang)", lines[1]) + @assert ang_unit "wout unit is not Angstrom, not supported yet" + lattice = zeros(Float64, 3, 3) - line = split(strip(readline(io))) - @assert line[1] == "a_1" - lattice[:, 1] = parse_float.(line[2:end]) + for (i, line) in enumerate(lines[2:end]) + line = split(line) + @assert line[1] == "a_$i" + lattice[:, i] = parse_float.(line[2:end]) + end + return lattice +end - line = split(strip(readline(io))) - @assert line[1] == "a_2" - lattice[:, 2] = parse_float.(line[2:end]) +""" +Parse block +``` +Reciprocal-Space Vectors (Ang^-1) +b_1 -1.157011 1.157011 1.157011 +b_2 1.157011 -1.157011 1.157011 +b_3 1.157011 1.157011 -1.157011 +``` +""" +function _parse_wout_recip_lattice(lines) + @assert length(lines) == 4 "wrong number of lines for reciprocal lattice" + @assert occursin("Reciprocal-Space Vectors", lines[1]) + recip_lattice = zeros(Float64, 3, 3) - line = split(strip(readline(io))) - @assert line[1] == "a_3" - lattice[:, 3] = parse_float.(line[2:end]) + for (i, line) in enumerate(lines[2:end]) + line = split(line) + @assert line[1] == "b_$i" + recip_lattice[:, i] = parse_float.(line[2:end]) + end + return recip_lattice +end - continue - end +""" +Parse block +``` +| Site Fractional Coordinate Cartesian Coordinate (Ang) | ++----------------------------------------------------------------------------+ +| Si 1 0.00000 0.00000 0.00000 | 0.00000 0.00000 0.00000 | +| Si 2 0.25000 0.25000 0.25000 | 1.35763 1.35763 1.35763 | +*----------------------------------------------------------------------------* +``` +""" +function _parse_wout_atoms(lines) + lines = lines[3:(end - 1)] + n_atom = length(lines) + atom_labels = Vector{String}() + atom_positions = zeros(Vec3{Float64}, n_atom) + for (i, line) in enumerate(lines) + line = split(line) + @assert line[1] == "|" line + push!(atom_labels, line[2]) + # cartesian + # atom_positions[i] = Vec3(parse_float.(line[8:10])) + # fractional + atom_positions[i] = Vec3(parse_float.(line[4:6])) + end + return atom_labels, atom_positions +end - if occursin(start_recip, line) - @assert occursin("Ang^-1", line) - recip_lattice = zeros(Float64, 3, 3) +""" +Parse block +``` + Extraction of optimally-connected subspace + ------------------------------------------ ++---------------------------------------------------------------------+<-- DIS +| Iter Omega_I(i-1) Omega_I(i) Delta (frac.) Time |<-- DIS ++---------------------------------------------------------------------+<-- DIS + 1 25.38943399 21.32896063 1.904E-01 0.00 <-- DIS + 2 21.53095611 20.16097533 6.795E-02 0.01 <-- DIS + 3 20.40788223 19.35260423 5.453E-02 0.01 <-- DIS + 4 19.53883989 18.75563591 4.176E-02 0.02 <-- DIS +... + 341 16.22884440 16.22884440 -1.883E-10 2.43 <-- DIS + 342 16.22884440 16.22884440 -1.799E-10 2.44 <-- DIS - line = split(strip(readline(io))) - @assert line[1] == "b_1" - recip_lattice[:, 1] = parse_float.(line[2:end]) + <<< Delta < 2.000E-10 over 3 iterations >>> + <<< Disentanglement convergence criteria satisfied >>> - line = split(strip(readline(io))) - @assert line[1] == "b_2" - recip_lattice[:, 2] = parse_float.(line[2:end]) + Final Omega_I 16.22884440 (Ang^2) - line = split(strip(readline(io))) - @assert line[1] == "b_3" - recip_lattice[:, 3] = parse_float.(line[2:end]) ++----------------------------------------------------------------------------+ - continue - end +Time to disentangle bands 2.546 (sec) +``` +""" +function _parse_wout_disentangle(lines) + mark_iter = "<-- DIS" + iter = Int[] + ΩI_previous = Float64[] + ΩI_current = Float64[] + ΔΩI = Float64[] - if occursin(start_atom, line) - @assert occursin("Ang", line) - readline(io) + i_start = 6 + for line in lines[i_start:end] + occursin(mark_iter, line) || continue - lines = Vector{String}() - line = strip(readline(io)) - while line != end_atom - push!(lines, line) - line = strip(readline(io)) - end + line = split(line) + push!(iter, parse(Int, line[1])) + push!(ΩI_previous, parse(Float64, line[2])) + push!(ΩI_current, parse(Float64, line[3])) + push!(ΔΩI, parse(Float64, line[4])) + end + return (; iter, ΩI_previous, ΩI_current, ΔΩI) +end - n_atom = length(lines) - atom_labels = Vector{String}() - atom_positions = zeros(Vec3{Float64}, n_atom) - for (i, line) in enumerate(lines) - line = split(line) - @assert line[1] == "|" line - push!(atom_labels, line[2]) - # cartesian - # atom_positions[i] = Vec3(parse_float.(line[8:10])) - # fractional - atom_positions[i] = Vec3(parse_float.(line[4:6])) - end +""" +Parse block +``` +WF centre and spread 1 ( -0.000005, 0.000021, 0.000023 ) 2.56218734 +WF centre and spread 2 ( 0.000013, -0.000054, 0.000016 ) 3.19493515 +WF centre and spread 3 ( -0.000005, -0.000054, -0.000055 ) 3.19482997 +WF centre and spread 4 ( 0.000012, 0.000015, -0.000058 ) 3.19526437 +WF centre and spread 5 ( 1.357637, 1.357611, 1.357610 ) 2.56218214 +WF centre and spread 6 ( 1.357619, 1.357684, 1.357617 ) 3.19532825 +WF centre and spread 7 ( 1.357638, 1.357687, 1.357686 ) 3.19513205 +WF centre and spread 8 ( 1.357620, 1.357617, 1.357694 ) 3.19460833 +Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 24.29446759 +``` +""" +function _parse_wout_wf_center_spread(lines) + mark_wf = "WF centre and spread" + mark_sum = "Sum of centres and spreads" + centers = Vec3{Float64}[] + spreads = Float64[] + sum_centers = nothing + sum_spreads = nothing + for line in lines + if occursin(mark_wf, line) + sline = split(line, r"[ ,()]"; keepempty=false) + idx = parse(Int, sline[5]) + push!(centers, Vec3(parse_float.(sline[6:8]))) + push!(spreads, parse_float(sline[9])) + (idx != length(centers)) && error("WF index mismatch at $line") + end + if occursin(mark_sum, line) + sline = split(line, r"[ ,()]"; keepempty=false) + sum_centers = Vec3(parse_float.(sline[6:8])) + sum_spreads = parse_float(sline[9]) + end + end + return centers, spreads, sum_centers, sum_spreads +end - continue - end +""" +Parse block +``` +*------------------------------- WANNIERISE ---------------------------------* ++--------------------------------------------------------------------+<-- CONV +| Iter Delta Spread RMS Gradient Spread (Ang^2) Time |<-- CONV ++--------------------------------------------------------------------+<-- CONV - if occursin(start_finalstate, line) - lines = Vector{String}() - line = strip(readline(io)) - while !occursin(end_finalstate, line) - push!(lines, line) - line = strip(readline(io)) - end +------------------------------------------------------------------------------ +Initial State + WF centre and spread 1 ( -0.000005, 0.000021, 0.000023 ) 2.56218734 + WF centre and spread 2 ( 0.000013, -0.000054, 0.000016 ) 3.19493515 + WF centre and spread 3 ( -0.000005, -0.000054, -0.000055 ) 3.19482997 + WF centre and spread 4 ( 0.000012, 0.000015, -0.000058 ) 3.19526437 + WF centre and spread 5 ( 1.357637, 1.357611, 1.357610 ) 2.56218214 + WF centre and spread 6 ( 1.357619, 1.357684, 1.357617 ) 3.19532825 + WF centre and spread 7 ( 1.357638, 1.357687, 1.357686 ) 3.19513205 + WF centre and spread 8 ( 1.357620, 1.357617, 1.357694 ) 3.19460833 + Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 24.29446759 - n_wann = length(lines) - centers = zeros(Vec3{Float64}, n_wann) - spreads = zeros(Float64, n_wann) - for (i, line) in enumerate(lines) - @assert startswith(line, marker_wfc) line - line = split(line, r"[,()]") + 0 0.243E+02 0.0000000000 24.2944680346 2.48 <-- CONV + O_D= 0.2135529 O_OD= 7.8520707 O_TOT= 24.2944680 <-- SPRD +------------------------------------------------------------------------------ +Cycle: 1 + WF centre and spread 1 ( -0.000005, 0.000020, 0.000022 ) 2.46316318 + WF centre and spread 2 ( 0.000014, -0.000057, 0.000015 ) 3.19187236 + WF centre and spread 3 ( -0.000005, -0.000057, -0.000058 ) 3.19179103 + WF centre and spread 4 ( 0.000012, 0.000014, -0.000061 ) 3.19222621 + WF centre and spread 5 ( 1.357637, 1.357612, 1.357611 ) 2.46315800 + WF centre and spread 6 ( 1.357618, 1.357687, 1.357618 ) 3.19226713 + WF centre and spread 7 ( 1.357637, 1.357690, 1.357689 ) 3.19209166 + WF centre and spread 8 ( 1.357619, 1.357619, 1.357697 ) 3.19156919 + Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 24.07813875 - idx = strip(chopprefix(line[1], marker_wfc)) - idx = parse(Int, idx) - @assert i == idx "Wrong WF index at $(line[1])" + 1 -0.216E+00 0.2558717278 24.0781391952 2.49 <-- CONV + O_D= 0.2218113 O_OD= 7.6274835 O_TOT= 24.0781392 <-- SPRD +Delta: O_D= 0.8258326E-02 O_OD= -0.2245872E+00 O_TOT= -0.2163288E+00 <-- DLTA +------------------------------------------------------------------------------ +Cycle: 2 +... +------------------------------------------------------------------------------ +Cycle: 45 +WF centre and spread 1 ( 0.000001, 0.000006, 0.000006 ) 1.95373328 +WF centre and spread 2 ( 0.000016, -0.000065, 0.000019 ) 3.27910139 +WF centre and spread 3 ( -0.000008, -0.000065, -0.000066 ) 3.27921479 +WF centre and spread 4 ( 0.000014, 0.000016, -0.000070 ) 3.27965818 +WF centre and spread 5 ( 1.357631, 1.357627, 1.357627 ) 1.95372427 +WF centre and spread 6 ( 1.357616, 1.357695, 1.357615 ) 3.27949625 +WF centre and spread 7 ( 1.357641, 1.357699, 1.357697 ) 3.27951005 +WF centre and spread 8 ( 1.357617, 1.357616, 1.357707 ) 3.27899768 +Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 23.58343588 - vals = map(parse_float, line[2:end]) - centers[i] = Vec3(vals[1:3]) - spreads[i] = vals[4] - end + 45 -0.186E-09 0.0000077396 23.5834363262 2.88 <-- CONV + O_D= 0.2612087 O_OD= 7.0933833 O_TOT= 23.5834363 <-- SPRD +Delta: O_D= 0.2557594E-06 O_OD= -0.2559458E-06 O_TOT= -0.1863789E-09 <-- DLTA +------------------------------------------------------------------------------ - continue - end + <<< Delta < 2.000E-10 over 3 iterations >>> + <<< Wannierisation convergence criteria satisfied >>> +``` +""" +function _parse_wout_wannierize(lines) + mark_init = "Initial State" + mark_cycle = "Cycle:" + mark_sprd = "<-- SPRD" - if occursin(marker_ΩI, line) - ΩI = parse_float(split(line, marker_ΩI)[2]) - continue - end - if occursin(marker_ΩD, line) - ΩD = parse_float(split(line, marker_ΩD)[2]) - continue - end - if occursin(marker_ΩOD, line) - ΩOD = parse_float(split(line, marker_ΩOD)[2]) - continue - end - if occursin(marker_Ωtotal, line) - Ωtotal = parse_float(split(line, marker_Ωtotal)[2]) - continue - end + iter = Int[] + centers = Vector{Vector{Vec3{Float64}}}() + spreads = Vector{Vector{Float64}}() + sum_centers = Vector{Vec3{Float64}}() + sum_spreads = Float64[] + ΩD = Float64[] + ΩOD = Float64[] + Ωtotal = Float64[] + + """ + i_start: line number of "WF centre and spread 1" + i_end: line number of "<-- SPRD" + """ + function append_iter!(i_start, i_end) + (i_end > i_start) || error("Invalid range $i_start:$i_end") + c, s, sc, ss = _parse_wout_wf_center_spread(lines[i_start:(i_end - 3)]) + push!(centers, c) + push!(spreads, s) + push!(sum_centers, sc) + push!(sum_spreads, ss) + sline = split(lines[i_end]) + push!(ΩD, parse_float(sline[2])) + push!(ΩOD, parse_float(sline[4])) + push!(Ωtotal, parse_float(sline[6])) + return nothing + end + + # Initial State + i_start = i_end = -1 + for (i, line) in enumerate(lines) + if occursin(mark_init, line) + i_start = i + 1 + continue + end + if occursin(mark_sprd, line) + i_end = i + break end + end + (i_start > 0) || error("No `$mark_init` found") + (i_end > i_start) || error("No `$mark_sprd` found") + push!(iter, 0) + append_iter!(i_start, i_end) - @assert ang_unit "wout unit is not Angstrom, not supported yet" - lattice = Mat3(lattice) - recip_lattice = Mat3(recip_lattice) - return (; - lattice, - recip_lattice, - atom_labels, - atom_positions, - centers, - spreads, - ΩI, - ΩD, - ΩOD, - Ωtotal, - ) + # Remaining cycles + # for each iteration: from `Cycle` to horizontal line, inclusive + n_lines_block = i_end - i_start + 4 + i = i_end + 1 + while i <= length(lines) + line = lines[i] + if occursin(mark_cycle, line) + idx = parse(Int, split(line)[2]) + push!(iter, idx) + i_start = i + 1 + i_end = i + n_lines_block - 3 + append_iter!(i_start, i_end) + i += n_lines_block + continue + end + i += 1 end + return (; iter, centers, spreads, sum_centers, sum_spreads, ΩD, ΩOD, Ωtotal) end diff --git a/test/w90/wout.jl b/test/w90/wout.jl index 05c5b5a..fdd7abb 100644 --- a/test/w90/wout.jl +++ b/test/w90/wout.jl @@ -1,3 +1,85 @@ +@testitem "_parse_wout_lattice" begin + file = joinpath(@__DIR__, "wout_testfiles", "lattice.txt") + lines = readlines(file) + lattice = WannierIO._parse_wout_lattice(lines) + ref_lattice = [ + 0.1 1.1 2.1 + 0.2 0.2 0.2 + 0.3 0.3 0.3 + ] + @test lattice ≈ ref_lattice +end + +@testitem "_parse_wout_recip_lattice" begin + file = joinpath(@__DIR__, "wout_testfiles", "recip_lattice.txt") + lines = readlines(file) + recip_lattice = WannierIO._parse_wout_recip_lattice(lines) + ref_recip_lattice = [ + 0.1 1.1 2.1 + 0.2 0.2 0.2 + 0.3 0.3 0.3 + ] + @test recip_lattice ≈ ref_recip_lattice +end + +@testitem "_parse_wout_atoms" begin + file = joinpath(@__DIR__, "wout_testfiles", "atoms.txt") + lines = readlines(file) + atom_labels, atom_positions = WannierIO._parse_wout_atoms(lines) + ref_atom_labels = ["Si", "Si"] + ref_atom_positions = [[0.00000, 0.00000, 0.00000], [0.25000, 0.25000, 0.25000]] + @test atom_labels == ref_atom_labels + @test atom_positions ≈ ref_atom_positions +end + +@testitem "_parse_wout_disentangle" begin + file = joinpath(@__DIR__, "wout_testfiles", "disentangle.txt") + lines = readlines(file) + results = WannierIO._parse_wout_disentangle(lines) + @test results.iter == [1, 341, 342] + @test results.ΩI_previous ≈ [25.38943399, 16.22884440, 16.22884440] + @test results.ΩI_current ≈ [21.32896063, 16.22884440, 16.22884440] + @test results.ΔΩI ≈ [1.904e-01, -1.883e-10, -1.799e-10] +end + +@testitem "_parse_wout_wf_center_spread" begin + file = joinpath(@__DIR__, "wout_testfiles", "wf_center_spread.txt") + lines = readlines(file) + centers, spreads, sum_centers, sum_spreads = WannierIO._parse_wout_wf_center_spread( + lines + ) + ref_centers = [[-0.000005, 0.000021, 0.000023], [0.000013, -0.000054, 0.000016]] + ref_spreads = [2.56218734, 3.19493515] + ref_sum_centers = [5.430528, 5.430529, 5.430534] + ref_sum_spreads = 24.29446759 + @test centers ≈ ref_centers + @test spreads ≈ ref_spreads + @test sum_centers ≈ ref_sum_centers + @test sum_spreads ≈ ref_sum_spreads +end + +@testitem "_parse_wout_wannierize" begin + file = joinpath(@__DIR__, "wout_testfiles", "wannierize.txt") + lines = readlines(file) + results = WannierIO._parse_wout_wannierize(lines) + @test results.iter == [0, 1, 45] + @test results.centers ≈ [ + [[-0.000005, 0.000021, 0.000023]], + [[-0.000005, 0.000020, 0.000022]], + [[0.000001, 0.000006, 0.000006]], + ] + @test results.spreads ≈ [[2.56218734], [2.46316318], [1.95373328]] + @test results.sum_centers ≈ [ + [5.430528, 5.430529, 5.430534], + [5.430528, 5.430529, 5.430534], + [5.430528, 5.430529, 5.430534], + ] + @test results.sum_spreads ≈ [24.29446759, 24.07813875, 23.58343588] + @test results.ΩD ≈ [0.2135529, 0.2218113, 0.2612087] + @test results.ΩOD ≈ [7.8520707, 7.6274835, 7.0933833] + @test results.Ωtotal ≈ [24.2944680, 24.0781392, 23.5834363] +end + @testitem "read wout" begin using WannierIO: Vec3 using LazyArtifacts @@ -23,6 +105,9 @@ @test wout.atom_positions ≈ ref_atom_positions @test wout.centers ≈ ref_centers @test wout.spreads ≈ ref_spreads + @test wout.kgrid == [6, 6, 6] + @test wout.sum_centers ≈ [-0.000001, -0.000000, 0.000000] + @test wout.sum_spreads ≈ 7.71671562 ref_ΩI = 7.153329184 ref_ΩD = 0.000000000 @@ -105,6 +190,150 @@ end @test wout.Ωtotal ≈ ref_Ωtotal end +@testitem "read wout iterations" begin + using LazyArtifacts + wout = read_wout(artifact"Fe_soc/reference/Fe.wout"; iterations=true) + + @test wout.iterations.disentangle.iter == 1:7000 + @test wout.iterations.disentangle.ΩI_previous[[1, 7000]] ≈ [16.06412287, 10.21963555] + @test wout.iterations.disentangle.ΩI_current[[1, 7000]] ≈ [15.60506153, 10.21963555] + @test wout.iterations.disentangle.ΔΩI[[1, 7000]] ≈ [2.942e-02, 3.224e-10] + + @test wout.iterations.wannierize.iter == 0:2083 + @test wout.iterations.wannierize.centers[[1, 2084]] ≈ [ + [ + [0.032917, -0.046451, -0.535906], + [0.024248, 0.103848, 0.410673], + [0.712774, -0.046012, -0.005995], + [-0.833291, -0.010927, 0.004327], + [0.008355, 0.067909, -0.010136], + [0.019012, -0.111345, 0.041994], + [-0.000064, 0.000132, -0.000702], + [0.000076, -0.000232, 0.000050], + [-0.003011, -0.000129, 0.000164], + [0.002979, 0.000022, 0.000530], + [0.000151, -0.000186, 0.000358], + [-0.000021, 0.000357, 0.000260], + [0.000171, -0.000092, 0.000177], + [0.000002, 0.000041, -0.000426], + [-0.002417, 0.000028, -0.000420], + [0.002224, 0.000170, 0.000076], + ], + [ + [-0.001227, 0.761822, -1.210363], + [-0.001132, 0.761153, 1.211403], + [1.434030, 0.674118, -0.223106], + [-1.436981, -0.000412, 0.958820], + [-0.002088, -1.435412, 0.479468], + [-0.001066, -0.761483, -1.210896], + [0.000330, -0.000261, 0.000357], + [0.000085, -0.019916, -0.010210], + [-0.000258, -0.000766, 0.000475], + [0.000067, -0.000720, -0.001011], + [0.000082, 0.020905, 0.010305], + [0.000045, 0.019902, -0.010005], + [-0.000815, 0.000310, -0.000449], + [0.000117, -0.020922, 0.010472], + [-0.000259, 0.000986, 0.001254], + [0.000055, 0.000493, -0.000470], + ], + ] + @test wout.iterations.wannierize.spreads[[1, 2084]] ≈ [ + [ + 6.91546411, + 7.13787642, + 9.87200446, + 9.48728884, + 5.67519982, + 5.93428114, + 0.60839403, + 0.58059954, + 0.64462091, + 0.61126568, + 0.63125454, + 0.62139130, + 0.61309583, + 0.59680091, + 0.64713955, + 0.61960630, + ], + [ + 1.11313978, + 1.11389149, + 1.11392684, + 1.14257541, + 1.14112348, + 1.11318311, + 0.40981481, + 0.44675647, + 0.48652472, + 0.44072505, + 0.45362382, + 0.44649383, + 0.44007660, + 0.45389206, + 0.48648695, + 0.44062982, + ], + ] + @test wout.iterations.wannierize.sum_centers[[1, 2084]] ≈ + [[-0.035896, -0.042867, -0.094975], [-0.009014, -0.000203, 0.006043]] + @test wout.iterations.wannierize.sum_spreads[[1, 2084]] ≈ [51.19628337, 11.24286425] + @test wout.iterations.wannierize.ΩD[[1, 2084]] ≈ [22.8931526, 0.0552124] + @test wout.iterations.wannierize.ΩOD[[1, 2084]] ≈ [18.0834952, 0.9680163] + @test wout.iterations.wannierize.Ωtotal[[1, 2084]] ≈ [51.1962834, 11.2428643] + + # test that parsing the "Final State" is correct + ref_centers = [ + [-0.001227, 0.761822, -1.210363], + [-0.001132, 0.761153, 1.211403], + [1.43403, 0.674118, -0.223106], + [-1.436981, -0.000412, 0.95882], + [-0.002088, -1.435412, 0.479468], + [-0.001066, -0.761483, -1.210896], + [0.00033, -0.000261, 0.000357], + [8.5e-5, -0.019916, -0.01021], + [-0.000258, -0.000766, 0.000475], + [6.7e-5, -0.00072, -0.001011], + [8.2e-5, 0.020905, 0.010305], + [4.5e-5, 0.019902, -0.010005], + [-0.000815, 0.00031, -0.000449], + [0.000117, -0.020922, 0.010472], + [-0.000259, 0.000986, 0.001254], + [5.5e-5, 0.000493, -0.00047], + ] + ref_spreads = [ + 1.11313978, + 1.11389149, + 1.11392684, + 1.14257541, + 1.14112348, + 1.11318311, + 0.40981481, + 0.44675647, + 0.48652472, + 0.44072505, + 0.45362382, + 0.44649383, + 0.4400766, + 0.45389206, + 0.48648695, + 0.44062982, + ] + + @test wout.centers ≈ ref_centers + @test wout.spreads ≈ ref_spreads + + ref_ΩI = 10.219635550 + ref_ΩD = 0.055212384 + ref_ΩOD = 0.968016319 + ref_Ωtotal = 11.242864254 + @test wout.ΩI ≈ ref_ΩI + @test wout.ΩD ≈ ref_ΩD + @test wout.ΩOD ≈ ref_ΩOD + @test wout.Ωtotal ≈ ref_Ωtotal +end + @testitem "read wout fortran stars" begin woutdir = joinpath(@__DIR__, "wout_testfiles") wout = read_wout(joinpath(woutdir, "stars.wout")) diff --git a/test/w90/wout_testfiles/atoms.txt b/test/w90/wout_testfiles/atoms.txt new file mode 100644 index 0000000..751b9e4 --- /dev/null +++ b/test/w90/wout_testfiles/atoms.txt @@ -0,0 +1,5 @@ +| Site Fractional Coordinate Cartesian Coordinate (Ang) | ++----------------------------------------------------------------------------+ +| Si 1 0.00000 0.00000 0.00000 | 0.00000 0.00000 0.00000 | +| Si 2 0.25000 0.25000 0.25000 | 1.35763 1.35763 1.35763 | +*----------------------------------------------------------------------------* diff --git a/test/w90/wout_testfiles/disentangle.txt b/test/w90/wout_testfiles/disentangle.txt new file mode 100644 index 0000000..4346d53 --- /dev/null +++ b/test/w90/wout_testfiles/disentangle.txt @@ -0,0 +1,18 @@ + Extraction of optimally-connected subspace + ------------------------------------------ ++---------------------------------------------------------------------+<-- DIS +| Iter Omega_I(i-1) Omega_I(i) Delta (frac.) Time |<-- DIS ++---------------------------------------------------------------------+<-- DIS + 1 25.38943399 21.32896063 1.904E-01 0.00 <-- DIS +... + 341 16.22884440 16.22884440 -1.883E-10 2.43 <-- DIS + 342 16.22884440 16.22884440 -1.799E-10 2.44 <-- DIS + + <<< Delta < 2.000E-10 over 3 iterations >>> + <<< Disentanglement convergence criteria satisfied >>> + + Final Omega_I 16.22884440 (Ang^2) + ++----------------------------------------------------------------------------+ + +Time to disentangle bands 2.546 (sec) diff --git a/test/w90/wout_testfiles/lattice.txt b/test/w90/wout_testfiles/lattice.txt new file mode 100644 index 0000000..09b2865 --- /dev/null +++ b/test/w90/wout_testfiles/lattice.txt @@ -0,0 +1,4 @@ +Lattice Vectors (Ang) +a_1 0.1 0.2 0.3 +a_2 1.1 0.2 0.3 +a_3 2.1 0.2 0.3 diff --git a/test/w90/wout_testfiles/recip_lattice.txt b/test/w90/wout_testfiles/recip_lattice.txt new file mode 100644 index 0000000..ae950a7 --- /dev/null +++ b/test/w90/wout_testfiles/recip_lattice.txt @@ -0,0 +1,4 @@ +Reciprocal-Space Vectors (Ang^-1) +b_1 0.1 0.2 0.3 +b_2 1.1 0.2 0.3 +b_3 2.1 0.2 0.3 diff --git a/test/w90/wout_testfiles/wannierize.txt b/test/w90/wout_testfiles/wannierize.txt new file mode 100644 index 0000000..6938f03 --- /dev/null +++ b/test/w90/wout_testfiles/wannierize.txt @@ -0,0 +1,32 @@ +*------------------------------- WANNIERISE ---------------------------------* ++--------------------------------------------------------------------+<-- CONV +| Iter Delta Spread RMS Gradient Spread (Ang^2) Time |<-- CONV ++--------------------------------------------------------------------+<-- CONV + +------------------------------------------------------------------------------ +Initial State + WF centre and spread 1 ( -0.000005, 0.000021, 0.000023 ) 2.56218734 + Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 24.29446759 + + 0 0.243E+02 0.0000000000 24.2944680346 2.48 <-- CONV + O_D= 0.2135529 O_OD= 7.8520707 O_TOT= 24.2944680 <-- SPRD +------------------------------------------------------------------------------ +Cycle: 1 + WF centre and spread 1 ( -0.000005, 0.000020, 0.000022 ) 2.46316318 + Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 24.07813875 + + 1 -0.216E+00 0.2558717278 24.0781391952 2.49 <-- CONV + O_D= 0.2218113 O_OD= 7.6274835 O_TOT= 24.0781392 <-- SPRD +Delta: O_D= 0.8258326E-02 O_OD= -0.2245872E+00 O_TOT= -0.2163288E+00 <-- DLTA +------------------------------------------------------------------------------ +Cycle: 45 +WF centre and spread 1 ( 0.000001, 0.000006, 0.000006 ) 1.95373328 +Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 23.58343588 + + 45 -0.186E-09 0.0000077396 23.5834363262 2.88 <-- CONV + O_D= 0.2612087 O_OD= 7.0933833 O_TOT= 23.5834363 <-- SPRD +Delta: O_D= 0.2557594E-06 O_OD= -0.2559458E-06 O_TOT= -0.1863789E-09 <-- DLTA +------------------------------------------------------------------------------ + + <<< Delta < 2.000E-10 over 3 iterations >>> + <<< Wannierisation convergence criteria satisfied >>> diff --git a/test/w90/wout_testfiles/wf_center_spread.txt b/test/w90/wout_testfiles/wf_center_spread.txt new file mode 100644 index 0000000..63b45b6 --- /dev/null +++ b/test/w90/wout_testfiles/wf_center_spread.txt @@ -0,0 +1,3 @@ +WF centre and spread 1 ( -0.000005, 0.000021, 0.000023 ) 2.56218734 +WF centre and spread 2 ( 0.000013, -0.000054, 0.000016 ) 3.19493515 +Sum of centres and spreads ( 5.430528, 5.430529, 5.430534 ) 24.29446759