Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import numpy as np
3from ase.io.fortranfile import FortranFile
6def read_rho(fname):
7 "Read unformatted Siesta charge density file"
9 # TODO:
10 #
11 # Handle formatted and NetCDF files.
12 #
13 # Siesta source code (at least 2.0.2) can possibly also
14 # save RHO as a _formatted_ file (the source code seems
15 # prepared, but there seems to be no fdf-options for it though).
16 # Siesta >= 3 has support for saving RHO as a NetCDF file
17 # (according to manual)
19 fh = FortranFile(fname)
21 # Read (but ignore) unit cell vectors
22 x = fh.readReals('d')
23 if len(x) != 3 * 3:
24 raise IOError('Failed to read cell vectors')
26 # Read number of grid points and spin components
27 x = fh.readInts()
28 if len(x) != 4:
29 raise IOError('Failed to read grid size')
30 gpts = x # number of 'X', 'Y', 'Z', 'spin' gridpoints
32 rho = np.zeros(gpts)
33 for ispin in range(gpts[3]):
34 for n3 in range(gpts[2]):
35 for n2 in range(gpts[1]):
36 x = fh.readReals('f')
37 if len(x) != gpts[0]:
38 raise IOError('Failed to read RHO[:,%i,%i,%i]' %
39 (n2, n3, ispin))
40 rho[:, n2, n3, ispin] = x
42 fh.close()
44 return rho
47def get_valence_charge(filename):
48 """ Read the valence charge from '.psf'-file."""
49 with open(filename, 'r') as fd:
50 fd.readline()
51 fd.readline()
52 fd.readline()
53 valence = -float(fd.readline().split()[-1])
55 return valence
58def read_vca_synth_block(filename, species_number=None):
59 """ Read the SyntheticAtoms block from the output of the
60 'fractional' siesta utility.
62 Parameters:
63 - filename: String with '.synth' output from fractional.
64 - species_number: Optional argument to replace override the
65 species number in the text block.
67 Returns: A string that can be inserted into the main '.fdf-file'.
68 """
69 with open(filename, 'r') as fd:
70 lines = fd.readlines()
71 lines = lines[1:-1]
73 if species_number is not None:
74 lines[0] = '%d\n' % species_number
76 block = ''.join(lines).strip()
78 return block
81def readHSX(fname):
82 """
83 Read unformatted siesta HSX file
84 """
85 import collections
87 HSX_tuple = collections.namedtuple('HSX',
88 ['norbitals', 'norbitals_sc', 'nspin',
89 'nonzero', 'is_gamma', 'sc_orb2uc_orb',
90 'row2nnzero', 'sparse_ind2column',
91 'H_sparse', 'S_sparse',
92 'aB2RaB_sparse', 'total_elec_charge',
93 'temp'])
95 fh = FortranFile(fname)
96 norbitals, norbitals_sc, nspin, nonzero = fh.readInts('i')
97 is_gamma = fh.readInts('i')[0]
99 sc_orb2uc_orb = 0
100 if is_gamma == 0:
101 sc_orb2uc_orb = fh.readInts('i')
103 row2nnzero = fh.readInts('i')
105 sum_row2nnzero = np.sum(row2nnzero)
106 if (sum_row2nnzero != nonzero):
107 raise ValueError('sum_row2nnzero != nonzero: {0} != {1}'
108 .format(sum_row2nnzero, nonzero))
110 row2displ = np.zeros((norbitals), dtype=int)
112 for i in range(1, norbitals):
113 row2displ[i] = row2displ[i - 1] + row2nnzero[i - 1]
115 max_nonzero = np.max(row2nnzero)
116 int_buff = np.zeros((max_nonzero), dtype=int)
117 sparse_ind2column = np.zeros((nonzero))
119 # Fill the rows for each index in *_sparse arrays
120 for irow in range(norbitals):
121 f = row2nnzero[irow]
122 int_buff[0:f] = fh.readInts('i')
123 # read set of rows where nonzero elements reside
124 d = row2displ[irow]
125 sparse_ind2column[d:d + f] = int_buff[0:f]
126 # END of Fill the rows for each index in *_sparse arrays
128 # allocate H, S and X matrices
129 sp_buff = np.zeros((max_nonzero), dtype=float)
131 H_sparse = np.zeros((nonzero, nspin), dtype=float)
132 S_sparse = np.zeros((nonzero), dtype=float)
133 aB2RaB_sparse = np.zeros((3, nonzero), dtype=float)
135 # Read the data to H_sparse array
136 for ispin in range(nspin):
137 for irow in range(norbitals):
138 d = row2displ[irow]
139 f = row2nnzero[irow]
140 sp_buff[0:f] = fh.readReals('f')
141 H_sparse[d:d + f, ispin] = sp_buff[0:f]
143 # Read the data to S_sparse array
144 for irow in range(norbitals):
145 f = row2nnzero[irow]
146 d = row2displ[irow]
147 sp_buff[0:f] = fh.readReals('f')
148 S_sparse[d:d + f] = sp_buff[0:f]
150 total_elec_charge, temp = fh.readReals('d')
152 sp_buff = np.zeros((3 * max_nonzero), dtype=float)
153 # Read the data to S_sparse array
154 for irow in range(norbitals):
155 f = row2nnzero[irow]
156 d = row2displ[irow]
157 sp_buff[0: 3 * f] = fh.readReals('f')
158 aB2RaB_sparse[0, d:d + f] = sp_buff[0:f]
159 aB2RaB_sparse[1, d:d + f] = sp_buff[f:2 * f]
160 aB2RaB_sparse[2, d:d + f] = sp_buff[2 * f:3 * f]
162 fh.close()
164 return HSX_tuple(norbitals, norbitals_sc, nspin, nonzero, is_gamma,
165 sc_orb2uc_orb, row2nnzero, sparse_ind2column, H_sparse,
166 S_sparse, aB2RaB_sparse, total_elec_charge, temp)
169def readDIM(fname):
170 """
171 Read unformatted siesta DIM file
172 """
173 import collections
175 DIM_tuple = collections.namedtuple('DIM', ['natoms_sc', 'norbitals_sc',
176 'norbitals', 'nspin',
177 'nnonzero',
178 'natoms_interacting'])
180 fh = FortranFile(fname)
182 natoms_sc = fh.readInts('i')[0]
183 norbitals_sc = fh.readInts('i')[0]
184 norbitals = fh.readInts('i')[0]
185 nspin = fh.readInts('i')[0]
186 nnonzero = fh.readInts('i')[0]
187 natoms_interacting = fh.readInts('i')[0]
188 fh.close()
190 return DIM_tuple(natoms_sc, norbitals_sc, norbitals, nspin,
191 nnonzero, natoms_interacting)
194def readPLD(fname, norbitals, natoms):
195 """
196 Read unformatted siesta PLD file
197 """
198 import collections
199 # use struct library to read mixed data type from binary
200 import struct
202 PLD_tuple = collections.namedtuple('PLD', ['max_rcut', 'orb2ao',
203 'orb2uorb', 'orb2occ',
204 'atm2sp', 'atm2shift',
205 'coord_sc', 'cell',
206 'nunit_cells'])
208 fh = FortranFile(fname)
210 orb2ao = np.zeros((norbitals), dtype=int)
211 orb2uorb = np.zeros((norbitals), dtype=int)
212 orb2occ = np.zeros((norbitals), dtype=float)
214 max_rcut = fh.readReals('d')
215 for iorb in range(norbitals):
216 dat = fh.readRecord()
217 dat_size = struct.calcsize('iid')
218 val_list = struct.unpack('iid', dat[0:dat_size])
219 orb2ao[iorb] = val_list[0]
220 orb2uorb[iorb] = val_list[1]
221 orb2occ[iorb] = val_list[2]
223 atm2sp = np.zeros((natoms), dtype=int)
224 atm2shift = np.zeros((natoms + 1), dtype=int)
225 for iatm in range(natoms):
226 atm2sp[iatm] = fh.readInts('i')[0]
228 for iatm in range(natoms + 1):
229 atm2shift[iatm] = fh.readInts('i')[0]
231 cell = np.zeros((3, 3), dtype=float)
232 nunit_cells = np.zeros((3), dtype=int)
233 for i in range(3):
234 cell[i, :] = fh.readReals('d')
235 nunit_cells = fh.readInts('i')
237 coord_sc = np.zeros((natoms, 3), dtype=float)
238 for iatm in range(natoms):
239 coord_sc[iatm, :] = fh.readReals('d')
241 fh.close()
242 return PLD_tuple(max_rcut, orb2ao, orb2uorb, orb2occ, atm2sp, atm2shift,
243 coord_sc, cell, nunit_cells)
246def readWFSX(fname):
247 """
248 Read unformatted siesta WFSX file
249 """
250 import collections
251 # use struct library to read mixed data type from binary
252 import struct
254 WFSX_tuple = collections.namedtuple('WFSX',
255 ['nkpoints', 'nspin', 'norbitals',
256 'gamma', 'orb2atm', 'orb2strspecies',
257 'orb2ao', 'orb2n', 'orb2strsym',
258 'kpoints', 'DFT_E', 'DFT_X',
259 'mo_spin_kpoint_2_is_read'])
261 fh = FortranFile(fname)
263 nkpoints, gamma = fh.readInts('i')
264 nspin = fh.readInts('i')[0]
265 norbitals = fh.readInts('i')[0]
267 orb2atm = np.zeros((norbitals), dtype=int)
268 orb2strspecies = []
269 orb2ao = np.zeros((norbitals), dtype=int)
270 orb2n = np.zeros((norbitals), dtype=int)
271 orb2strsym = []
272 # for string list are better to select all the string length
274 dat_size = struct.calcsize('i20sii20s')
275 dat = fh.readRecord()
277 ind_st = 0
278 ind_fn = dat_size
279 for iorb in range(norbitals):
280 val_list = struct.unpack('i20sii20s', dat[ind_st:ind_fn])
281 orb2atm[iorb] = val_list[0]
282 orb2strspecies.append(val_list[1])
283 orb2ao[iorb] = val_list[2]
284 orb2n[iorb] = val_list[3]
285 orb2strsym.append(val_list[4])
286 ind_st = ind_st + dat_size
287 ind_fn = ind_fn + dat_size
288 orb2strspecies = np.array(orb2strspecies)
289 orb2strsym = np.array(orb2strsym)
291 kpoints = np.zeros((3, nkpoints), dtype=np.float64)
292 DFT_E = np.zeros((norbitals, nspin, nkpoints), dtype=np.float64)
294 if (gamma == 1):
295 DFT_X = np.zeros((1, norbitals, norbitals, nspin, nkpoints),
296 dtype=np.float64)
297 eigenvector = np.zeros((1, norbitals), dtype=float)
298 else:
299 DFT_X = np.zeros((2, norbitals, norbitals, nspin, nkpoints),
300 dtype=np.float64)
301 eigenvector = np.zeros((2, norbitals), dtype=float)
303 mo_spin_kpoint_2_is_read = np.zeros((norbitals, nspin, nkpoints),
304 dtype=bool)
305 mo_spin_kpoint_2_is_read[0:norbitals, 0:nspin, 0:nkpoints] = False
307 dat_size = struct.calcsize('iddd')
308 for ikpoint in range(nkpoints):
309 for ispin in range(nspin):
310 dat = fh.readRecord()
311 val_list = struct.unpack('iddd', dat[0:dat_size])
312 ikpoint_in = val_list[0] - 1
313 kpoints[0:3, ikpoint] = val_list[1:4]
314 if (ikpoint != ikpoint_in):
315 raise ValueError('siesta_get_wfsx: ikpoint != ikpoint_in')
316 ispin_in = fh.readInts('i')[0] - 1
317 if (ispin_in > nspin - 1):
318 msg = 'siesta_get_wfsx: err: ispin_in>nspin\n \
319 siesta_get_wfsx: ikpoint, ispin, ispin_in = \
320 {0} {1} {2}\n siesta_get_wfsx'.format(ikpoint,
321 ispin, ispin_in)
322 raise ValueError(msg)
324 norbitals_in = fh.readInts('i')[0]
325 if (norbitals_in > norbitals):
326 msg = 'siesta_get_wfsx: err: norbitals_in>norbitals\n \
327 siesta_get_wfsx: ikpoint, norbitals, norbitals_in = \
328 {0} {1} {2}\n siesta_get_wfsx'.format(ikpoint,
329 norbitals,
330 norbitals_in)
331 raise ValueError(msg)
333 for imolecular_orb in range(norbitals_in):
334 imolecular_orb_in = fh.readInts('i')[0] - 1
335 if (imolecular_orb_in > norbitals - 1):
336 msg = """
337 siesta_get_wfsx: err: imolecular_orb_in>norbitals\n
338 siesta_get_wfsx: ikpoint, norbitals,
339 imolecular_orb_in = {0} {1} {2}\n
340 siesta_get_wfsx""".format(ikpoint, norbitals,
341 imolecular_orb_in)
342 raise ValueError(msg)
344 real_E_eV = fh.readReals('d')[0]
345 eigenvector = fh.readReals('f')
346 DFT_E[imolecular_orb_in, ispin_in,
347 ikpoint] = real_E_eV / 13.60580
348 DFT_X[:, :, imolecular_orb_in, ispin_in,
349 ikpoint] = eigenvector
350 mo_spin_kpoint_2_is_read[imolecular_orb_in, ispin_in,
351 ikpoint] = True
353 if (not all(mo_spin_kpoint_2_is_read[:, ispin_in, ikpoint])):
354 msg = 'siesta_get_wfsx: warn: .not. all(mo_spin_k_2_is_read)'
355 print('mo_spin_kpoint_2_is_read = ', mo_spin_kpoint_2_is_read)
356 raise ValueError(msg)
358 fh.close()
359 return WFSX_tuple(nkpoints, nspin, norbitals, gamma, orb2atm,
360 orb2strspecies, orb2ao, orb2n, orb2strsym,
361 kpoints, DFT_E, DFT_X, mo_spin_kpoint_2_is_read)