forked from ACEsuit/ACEfriction.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatautils.jl
More file actions
190 lines (165 loc) · 6.85 KB
/
datautils.jl
File metadata and controls
190 lines (165 loc) · 6.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
module DataUtils
using ProgressMeter
using JuLIP
using ACEfriction.mUtils: reinterpret
using StaticArrays, SparseArrays
export FrictionData, BlockDenseArray
export save_h5fdata, load_h5fdata
using HDF5
struct FrictionData
atoms
friction_tensor
friction_indices
end
function FrictionData(d::NamedTuple{(:at, :friction_tensor, :friction_indices)})
return FrictionData(d.at, d.friction_tensor, d.friction_indices)
end
# function FrictionData(d::NamedTuple{(:at, :friction_tensor, :friction_indices,:friction_indices_ref)})
# return FrictionData(d.at, d.friction_tensor, d.friction_indices, d.friction_tensor_ref)
# end
function _array2svector(x::Array{T,2}) where {T}
return [ SVector{3}(x[i,:]) for i in 1:size(x)[1] ]
end
function _svector2array(c_vec::Vector{SVector{N_rep, T}}) where {N_rep,T<:Number}
"""
input: c_vec each
N_basis = length(c_vec)
N_rep = numbero of channels
"""
c_matrix = Array{T}(undef,length(c_vec),N_rep)
for j in eachindex(c_vec)
c_matrix[j,:] = c_vec[j]
end
return c_matrix
end
"""
save_h5fdata(rdata::Vector{FrictionData}, filename::String )
Saves a friction tensor data in a costum formatted hdf5 file.
### Arguments
- `rdata` : Vector{FrictionData} :
A vector of friction data entries. Each entry is a structure of type `Frictiondata` with the following fields:
- `at` : JuLIP.Atoms : Atoms object containing the atomic positions, cell, and periodic boundary conditions.
- `friction_tensor` : SparseMatrix{SMatrix{3,3,Float64,9}} : Sparse matrix representation of the friction tensor.
- `friction_indices` : Vector{Int} : Indices of the atoms for which the friction tensor is defined.
- `filename` : String : Name of the file to save to (including h5 extension).
"""
function save_h5fdata(rdata::Vector{FrictionData}, filename::String )
fid = h5open(filename, "w")
try
# iterate over each data entry
write_attribute(fid, "N_data", length(rdata))
@showprogress for (i,d) in enumerate(rdata)
g = create_group(fid, "$i")
# write atoms data
ag = create_group(g, "atoms")
dset_pos = create_dataset(ag, "positions", Float64, (length(d.atoms.X), 3))
for (k,x) in enumerate(d.atoms.X)
dset_pos[k,:] = x
end
write_attribute(dset_pos, "column_major", true)
write(ag, "atypes", Int.(d.atoms.Z))
write(ag, "cell", Matrix(d.atoms.cell))
write_attribute(ag["cell"], "column_major", true)
write(ag, "pbc", Array(d.atoms.pbc))
# write friction data
fg = create_group(g, "friction_tensor")
(I,J,V) = findnz(d.friction_tensor)
write(fg, "ft_I", I)
write(fg, "ft_J", J)
dset_ft = create_dataset(fg, "ft_val", Float64, (length(V), 3, 3))
for (k,v) in enumerate(V)
dset_ft[k,:,:] = v
end
write_attribute(dset_ft, "column_major", true)
write(fg, "ft_mask", d.friction_indices)
end
catch
close(fid)
rethrow(e)
end
HDF5.close(fid)
end
function _hdf52Atoms( ag::HDF5.Group )
local positions, cell
try
if Bool(read_attribute(ag["positions"],"column_major")) == true
positions = read(ag["positions"])
else
positions = permutedims(read(ag["positions"]), [2, 1])
end
catch
@warn "The attribute 'column_major' is missing for the data 'positions'. Proceed assuming array was stored in column-major format. If you are saving your array from Python, make sure to set the column_major attribute to 0 (False)."
positions = read(ag["positions"])
end
try
if Bool(read_attribute(ag["cell"],"column_major")) == true
cell = read(ag["cell"])
else
cell = permutedims(read(ag["cell"]), [2, 1])
end
catch
@warn "The attribute 'column_major' is missing for the data 'cell'. Proceed assuming array was stored in column-major format. If you are saving your array from Python, make sure to set the column_major attribute to 0 (False)."
cell = read(ag["cell"])
end
return JuLIP.Atoms(;
X=[SVector{3}(d) for d in eachslice(positions; dims=1)],
Z=read(ag["atypes"]),
cell= cell,
pbc=Bool.(read(ag["pbc"]))
)
end
function _hdf52ft( ftg::HDF5.Group )
local ft_val
try
if Bool(read_attribute(ftg["ft_val"],"column_major")) == true
ft_val = read(ftg["ft_val"])
else
ft_val = permutedims(read(ftg["ft_val"]), [3, 2, 1])
end
catch
@warn "The attribute 'column_major' is missing for the data 'ft_val'. Proceed assuming array was stored in column-major format. If you are saving your array from Python, make sure to set the column_major attribute to 0 (False)."
ft_val = read(ftg["ft_val"])
end
spft = sparse( read(ftg["ft_I"]),read(ftg["ft_J"]), [SMatrix{3,3}(d) for d in eachslice(ft_val; dims=1)] )
ft_mask = read(ftg["ft_mask"])
return (friction_tensor = spft, mask = ft_mask)
end
"""
load_h5fdata(filename::String)
Loads a friction tensor data from a costum formatted hdf5 file.
### Arguments
- `filename` : String : Name of the file to load from (including h5 extension).
### Returns
- `rdata` : Vector{FrictionData} :
A vector of friction data entries. Each entry is a structure of type `Frictiondata` with the following fields:
- `at` : JuLIP.Atoms : Atoms object containing the atomic positions, cell, and periodic boundary conditions.
- `friction_tensor` : SparseMatrix{SMatrix{3,3,Float64,9}} : Sparse matrix representation of the friction tensor.
- `friction_indices` : Vector{Int} : Indices of the atoms for which the friction tensor is defined.
"""
function load_h5fdata(filename::String)
fid = h5open(filename, "r")
N_data = read_attribute(fid, "N_data")
rdata = @showprogress [begin
at = _hdf52Atoms( fid["$i/atoms/"])
spft, ft_mask = _hdf52ft( fid["$i/friction_tensor/"])
(at=at, friction_tensor=spft, friction_indices=ft_mask)
end
for i=1:N_data]
HDF5.close(fid)
return FrictionData.(rdata)
end
"""
Semi-sparse matrix representation of a square matrix M of unspecified dimension. Entries of M are
specified by the fields `values::Matrix{T}` and `indexmap` assuming
1. `M[k,l] = 0` if either of the indices `k`, `l` is not contained in `indexmap`.
2. values[i,j] = M[indexmap[i],indexmap[j]]
"""
struct BlockDenseMatrix{T} <: AbstractArray{Float64,2}
tensor::Matrix{T}
indices
end
function BlockDenseArray(full_tensor::Matrix; indices=1:size(full_tensor,1))
@assert size(full_tensor,1) == size(full_tensor,2)
return BlockDenseMatrix(full_tensor[indices,indices], indices)
end
end