11
22# TODO : might need to write a more specialized function which doesn't do conversions for
33# each operator separately assuming the metadata is the same
4- function RealBSparseOperator (in_operator:: FHIaimsCSCOperator )
5- # # Metadata
6- # Convert sparsity
7- out_sparsity = RealBlockSparsity (in_operator. metadata. sparsity, in_operator. metadata. basisset)
4+ # TODO : Allow to compute sparsity from radii
5+ function RealBSparseOperator (in_operator:: FHIaimsCSCOperator , radii)
6+
7+ # Obtain sparsity
8+ if isnothing (radii)
9+ out_sparsity = RealBlockSparsity (in_operator. metadata. sparsity, in_operator. metadata. basisset)
10+ else
11+ @info " Computing sparsity manually from radii"
12+ out_sparsity = RealBlockSparsity (in_operator. metadata. atoms, radii, hermitian = true )
13+ end
814
915 # Compute z1z2_ij2interval
1016 z1z2_ij2interval = compute_z1z2_ij2interval (in_operator. metadata. atoms, out_sparsity)
1117
18+ # Construct metadata
1219 out_metadata = RealBSparseMetadata (
1320 in_operator. metadata. atoms, out_sparsity, in_operator. metadata. basisset, in_operator. metadata. spins, z1z2_ij2interval
1421 )
1522
16- # # Data
1723 # Initialize out_operator with zeros
1824 out_operator = RealBSparseOperator (in_operator. kind, out_metadata)
1925
@@ -41,9 +47,11 @@ function populate!(out_keydata, out_sparsity, out_basisset, in_data, in_sparsity
4147
4248 atom2basis_offset = get_offsets (out_basisset)
4349 iglobal2ilocal = get_iglobal2ilocal (out_sparsity)
50+ shconv = SHConversion (out_type) ∘ inv (SHConversion (in_type))
4451
45- # shconv = SHConversion(out_type) ∘ inv(SHConversion(in_type))
46- # shifts, phases = precompute_shiftphases(out_basisset, shconv)
52+ # Use inv(shconv) for shifts and phases because matrix is being reordered
53+ # using `type2` reordering, for more information see tests/unit/shconversion.jl
54+ shifts, phases = precompute_shiftphases (out_basisset, inv (shconv))
4755
4856 for i_cell in axes (in_sparsity. colcellptr, 2 )
4957 image = in_sparsity. images[i_cell]
@@ -65,24 +73,31 @@ function populate!(out_keydata, out_sparsity, out_basisset, in_data, in_sparsity
6573 i_basis_row_local = i_basis_row - atom2basis_offset[i_atom_row]
6674 i_basis_col_local = i_basis_col - atom2basis_offset[i_atom_col]
6775
68- out_keydata[(i_atom_row, i_atom_col)][i_basis_row_local, i_basis_col_local, i_cell_local] = in_data[i_index]
76+ out_keydata[(i_atom_row, i_atom_col)][
77+ i_basis_row_local + shifts[out_basisset. atom2species[i_atom_row]][i_basis_row_local],
78+ i_basis_col_local + shifts[out_basisset. atom2species[i_atom_col]][i_basis_col_local],
79+ i_cell_local
80+ ] = (
81+ in_data[i_index]
82+ * phases[out_basisset. atom2species[i_atom_row]][i_basis_row_local]
83+ * phases[out_basisset. atom2species[i_atom_col]][i_basis_col_local]
84+ )
6985 end
7086 end
7187 end
72- end
7388
74- # struct FHIaimsCSCMetadata{A<:AbstractSystem, E} <: AbstractFHIaimsMetadata
75- # atoms::A
76- # sparsity::RealCSCSparsity
77- # basisset::BasisSetMetadata{E}
78- # spinset::Union{SpinsMetadata, Nothing}
79- # # TODO : Is Union{SpinsMetadata, Nothing} best approach here?
80- # # Making FHIaimsCSCMetadata a parametric type wrt typeof(spins )
81- # # or making SpinsMetadata a parametric type might be an overkill
82- # end
83-
84- # struct FHIaimsCSCOperator{O<:AbstractOperatorKind, T<:AbstractFloat, A<:AbstractSystem, E} <: AbstractFHIaimsOperator
85- # kind::O
86- # data::Vector{T}
87- # metadata::FHIaimsCSCMetadata{A, E}
88- # end
89+ # Fill in the 'L' part of on-site blocks that, due of Hermitian CSC sparsity,
90+ # were not filled in the loop above
91+ n_atoms = length (atom2basis_offset)
92+ for i_atom in 1 : n_atoms
93+ for k in axes (out_keydata[(i_atom, i_atom)], 3 )
94+ for j in axes (out_keydata[(i_atom, i_atom)], 2 )
95+ @inbounds for i in axes (out_keydata[(i_atom, i_atom)], 1 )
96+ j > i || continue
97+ out_keydata[(i_atom, i_atom)][j, i, k] = out_keydata[(i_atom, i_atom)][i, j, k]
98+ end
99+ end
100+ end
101+ end
102+
103+ end
0 commit comments