Hide keyboard shortcuts

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

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

191

192

193

194

195

196

197

198

""" 

This module provides functions for reading and writing data files 

in phonopy and phono3py formats. 

""" 

 

import warnings 

import os 

import numpy as np 

from itertools import product 

from .. import ForceConstants 

from ..io.logging import logger 

 

with warnings.catch_warnings(): 

warnings.filterwarnings('ignore', category=FutureWarning) 

import h5py 

 

 

logger = logger.getChild('io_phonopy') 

 

 

def _filename_to_format(filename): 

""" Try to guess the format from the filename """ 

basename = os.path.basename(filename) 

 

if basename == 'FORCE_CONSTANTS': 

return 'text' 

 

if '.' in basename: 

extension = basename.split('.')[-1] 

if extension == 'hdf5': 

return 'hdf5' 

raise ValueError('Could not guess file format') 

 

 

def read_phonopy_fc2(filename, format=None): 

"""Parse a second order force constant file in phonopy format. 

 

Parameters 

---------- 

filename : str 

input file name 

format : str 

specify the file-format, if None tries to guess the format from filename 

 

Returns 

------- 

NumPy (N,N,3,3) array 

second order force constant matrix where `N` is the number of atoms 

""" 

fc2_readers = { 

'text': _read_phonopy_fc2_text, 

'hdf5': _read_phonopy_fc2_hdf5 

} 

 

if format is None: 

format = _filename_to_format(filename) 

if format not in fc2_readers.keys(): 

raise ValueError('Did not recognize format {}'.format(format)) 

return fc2_readers[format](filename) 

 

 

def write_phonopy_fc2(filename, fc2, format=None): 

"""Write second order force constant matrix in phonopy format. 

 

Parameters 

---------- 

filename : str 

output file name 

fc2 : ForceConstants or NumPy array 

second order force constant matrix 

format : str 

specify the file-format, if None tries to guess the format from filename 

""" 

fc2_writers = { 

'text': _write_phonopy_fc2_text, 

'hdf5': _write_phonopy_fc2_hdf5 

} 

 

# get fc2_array 

if isinstance(fc2, ForceConstants): 

fc2_array = fc2.get_fc_array(order=2) 

elif isinstance(fc2, np.ndarray): 

fc2_array = fc2 

else: 

raise TypeError('fc2 should be ForceConstants or NumPy array') 

 

# check that fc2 has correct shape 

Natoms = fc2_array.shape[0] 

if fc2_array.shape != (Natoms, Natoms, 3, 3): 

raise ValueError('fc2 has wrong shape') 

 

# write 

if format is None: 

format = _filename_to_format(filename) 

if format not in fc2_writers.keys(): 

raise ValueError('Did not recognize format {}'.format(format)) 

fc2_writers[format](filename, fc2_array) 

 

 

def read_phonopy_fc3(filename): 

"""Parse a third order force constant file in phonopy hdf5 format. 

 

Parameters 

---------- 

filename : str 

input file name 

 

Returns 

------- 

NumPy array 

third order force constant matrix 

""" 

with h5py.File(filename, 'r') as hf: 

114 ↛ 117line 114 didn't jump to line 117, because the condition on line 114 was never false if 'fc3' in hf.keys(): 

fc3 = hf['fc3'][:] 

else: 

raise IOError('Could not find fc3 in file {}'.format(filename)) 

return fc3 

 

 

def write_phonopy_fc3(filename, fc3): 

"""Write third order force constant matrix in phonopy hdf5 format. 

 

Parameters 

---------- 

filename : str 

output file name 

fc3 : ForceConstants or NumPy array 

third order force constant matrix 

""" 

 

if isinstance(fc3, ForceConstants): 

fc3_array = fc3.get_fc_array(order=3) 

elif isinstance(fc3, np.ndarray): 

fc3_array = fc3 

else: 

raise TypeError('fc3 should be ForceConstants or NumPy array') 

 

# check that fc3 has correct shape 

Natoms = fc3_array.shape[0] 

if fc3_array.shape != (Natoms, Natoms, Natoms, 3, 3, 3): 

raise ValueError('fc3 has wrong shape') 

 

with h5py.File(filename, 'w') as hf: 

hf.create_dataset('fc3', data=fc3_array) 

hf.flush() 

 

 

def _read_phonopy_fc2_text(filename): 

""" Reads phonopy-fc2 file in text format """ 

with open(filename, 'r') as f: 

lines = f.readlines() 

for n, line in enumerate(lines): 

flds = line.split() 

if len(flds) == 1: # first line in fc2 file 

Natoms = int(flds[0]) 

fc2 = np.empty((Natoms, Natoms, 3, 3)) * np.nan 

elif len(flds) == 2: 

i = int(flds[0]) - 1 # phonopy index starts with 1 

j = int(flds[1]) - 1 

for x in range(3): 

fc_row = lines[n + x + 1].split() 

for y in range(3): 

fc2[i][j][x][y] = float(fc_row[y]) 

return fc2 

 

 

def _read_phonopy_fc2_hdf5(filename): 

"""Reads phonopy-fc2 file in hdf5 format """ 

with h5py.File(filename, 'r') as hf: 

171 ↛ 172line 171 didn't jump to line 172, because the condition on line 171 was never true if 'force_constants' in hf.keys(): 

fc2 = hf['force_constants'][:] 

173 ↛ 176line 173 didn't jump to line 176, because the condition on line 173 was never false elif 'fc2' in hf.keys(): 

fc2 = hf['fc2'][:] 

else: 

raise IOError('Could not find fc2 in file {}'.format(filename)) 

return fc2 

 

 

def _write_phonopy_fc2_text(filename, fc2): 

""" Writes fc2 NumPy array to filename in text format """ 

Natoms = fc2.shape[0] 

with open(filename, 'w') as f: 

f.write('{:}\n'.format(Natoms)) 

for i, j in product(range(Natoms), range(Natoms)): 

fc2_ij = fc2[(i, j)] 

187 ↛ 188line 187 didn't jump to line 188, because the condition on line 187 was never true if fc2_ij.shape != (3, 3): 

raise ValueError('Invalid shape for fc2[({},{})]'.format(i, j)) 

f.write('{:-5d}{:5d}\n'.format(i + 1, j + 1)) 

for row in fc2_ij: 

f.write((3*' {:22.15f}'+'\n').format(*tuple(row))) 

 

 

def _write_phonopy_fc2_hdf5(filename, fc2): 

""" Writes fc2 NumPy array to filename in hdf5 format """ 

with h5py.File(filename, 'w') as hf: 

hf.create_dataset('fc2', data=fc2) 

hf.flush()