Coverage for /builds/kinetik161/ase/ase/calculators/siesta/import_ion_xml.py: 92.63%

95 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-12-10 11:04 +0000

1import re 

2from xml.dom import minidom 

3 

4import numpy as np 

5 

6 

7def get_ion(fname): 

8 """ 

9 Read the ion.xml file of a specie 

10 Input parameters: 

11 ----------------- 

12 fname (str): name of the ion file 

13 Output Parameters: 

14 ------------------ 

15 ion (dict): The ion dictionary contains all the data 

16 from the ion file. Each field of the xml file give 

17 one key. 

18 The different keys are: 

19 'lmax_basis': int 

20 'self_energy': float 

21 'z': int 

22 'symbol': str 

23 'label': str 

24 'mass': flaot 

25 'lmax_projs': int 

26 'basis_specs': str 

27 'norbs_nl': int 

28 'valence': float 

29 'nprojs_nl: int 

30 

31 The following keys give the pao field, 

32 'npts': list of int 

33 'delta':list of float 

34 'cutoff': list of float 

35 'data':list of np.arrayof shape (npts[i], 2) 

36 'orbital': list of dictionary 

37 'projector': list of dictionary 

38 

39 """ 

40 doc = minidom.parse(fname) 

41 

42 # the elements from the header 

43 elements_headers = [['symbol', str], ['label', str], ['z', int], 

44 ['valence', float], ['mass', float], 

45 ['self_energy', float], ['lmax_basis', int], 

46 ['norbs_nl', int], ['lmax_projs', int], 

47 ['nprojs_nl', int]] 

48 

49 ion = {} 

50 for i, elname in enumerate(elements_headers): 

51 name = doc.getElementsByTagName(elname[0]) 

52 ion[elname[0]] = get_data_elements(name[0], elname[1]) 

53 

54 # extract the basis_specs 

55 name = doc.getElementsByTagName("basis_specs") 

56 ion["basis_specs"] = getNodeText(name[0]) 

57 

58 extract_pao_elements(ion, doc) 

59 return ion 

60 

61 

62def getNodeText(node): 

63 nodelist = node.childNodes 

64 result = [] 

65 for node in nodelist: 

66 if node.nodeType == node.TEXT_NODE: 

67 result.append(node.data) 

68 return ''.join(result) 

69 

70 

71def get_data_elements(name, dtype): 

72 """ 

73 return the right type of the element value 

74 """ 

75 if dtype is int: 

76 data = str2int(getNodeText(name)) 

77 if len(data) > 1: 

78 return np.array(data) 

79 elif len(data) == 1: 

80 return data[0] 

81 else: 

82 raise ValueError("len(data)<1 ??") 

83 elif dtype is float: 

84 data = str2float(getNodeText(name)) 

85 if len(data) > 1: 

86 return np.array(data) 

87 elif len(data) == 1: 

88 return data[0] 

89 else: 

90 raise ValueError("len(data)<1 ??") 

91 elif dtype is str: 

92 return getNodeText(name) 

93 else: 

94 raise ValueError('not implemented') 

95 

96 

97def extract_pao_elements(ion, doc): 

98 """ 

99 extract the different pao element of the xml file 

100 Input Parameters: 

101 ----------------- 

102 ion (dict) 

103 doc (minidom.parse) 

104 Output Parameters: 

105 ------------------ 

106 ion (dict): the following keys are added to the ion dict: 

107 npts 

108 delta 

109 cutoff 

110 data 

111 orbital 

112 projector 

113 """ 

114 

115 name_npts = doc.getElementsByTagName("npts") 

116 name_delta = doc.getElementsByTagName("delta") 

117 name_cutoff = doc.getElementsByTagName("cutoff") 

118 name_data = doc.getElementsByTagName("data") 

119 

120 name_orbital = doc.getElementsByTagName("orbital") 

121 name_projector = doc.getElementsByTagName("projector") 

122 

123 ion["orbital"] = [] 

124 ion["projector"] = [] 

125 for i in range(len(name_orbital)): 

126 ion["orbital"].append(extract_orbital(name_orbital[i])) 

127 for i in range(len(name_projector)): 

128 ion["projector"].append(extract_projector(name_projector[i])) 

129 

130 if len(name_data) != len(name_npts): 

131 raise ValueError("len(name_data) != len(name_npts): {0} != {1}". 

132 format(len(name_data), len(name_npts))) 

133 if len(name_data) != len(name_cutoff): 

134 raise ValueError("len(name_data) != len(name_cutoff): {0} != {1}". 

135 format(len(name_data), len(name_cutoff))) 

136 if len(name_data) != len(name_delta): 

137 raise ValueError("len(name_data) != len(name_delta): {0} != {1}". 

138 format(len(name_data), len(name_delta))) 

139 

140 ion["npts"] = np.zeros((len(name_npts)), dtype=int) 

141 ion["delta"] = np.zeros((len(name_delta)), dtype=float) 

142 ion["cutoff"] = np.zeros((len(name_cutoff)), dtype=float) 

143 ion["data"] = [] 

144 

145 for i in range(len(name_data)): 

146 ion["npts"][i] = get_data_elements(name_npts[i], int) 

147 ion["cutoff"][i] = get_data_elements(name_cutoff[i], float) 

148 ion["delta"][i] = get_data_elements(name_delta[i], float) 

149 ion["data"].append(get_data_elements(name_data[i], float). 

150 reshape(ion["npts"][i], 2)) 

151 

152 

153def extract_orbital(orb_xml): 

154 """ 

155 extract the orbital 

156 """ 

157 orb = {} 

158 orb['l'] = str2int(orb_xml.attributes['l'].value)[0] 

159 orb['n'] = str2int(orb_xml.attributes['n'].value)[0] 

160 orb['z'] = str2int(orb_xml.attributes['z'].value)[0] 

161 orb['ispol'] = str2int(orb_xml.attributes['ispol'].value)[0] 

162 orb['population'] = str2float(orb_xml.attributes['population'].value)[0] 

163 

164 return orb 

165 

166 

167def extract_projector(pro_xml): 

168 """ 

169 extract the projector 

170 """ 

171 pro = {} 

172 pro['l'] = str2int(pro_xml.attributes['l'].value)[0] 

173 pro['n'] = str2int(pro_xml.attributes['n'].value)[0] 

174 pro['ref_energy'] = str2float(pro_xml.attributes['ref_energy'].value)[0] 

175 

176 return pro 

177 

178 

179def str2float(string): 

180 numeric_const_pattern = r""" 

181 [-+]? # optional sign 

182 (?: 

183 (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc 

184 | 

185 (?: \d+ \.? ) # 1. 12. 123. etc 1 12 123 etc 

186 ) 

187 # followed by optional exponent part if desired 

188 (?: [Ee] [+-]? \d+ ) ? 

189 """ 

190 rx = re.compile(numeric_const_pattern, re.VERBOSE) 

191 

192 nb = rx.findall(string) 

193 for i in enumerate(nb): 

194 nb[i[0]] = float(i[1]) 

195 

196 return np.array(nb) 

197 

198 

199def str2int(string): 

200 numeric_const_pattern = r""" 

201 [-+]? # optional sign 

202 (?: 

203 (?: \d* \. \d+ ) # .1 .12 .123 etc 9.1 etc 98.1 etc 

204 | 

205 (?: \d+ \.? ) # 1. 12. 123. etc 1 12 123 etc 

206 ) 

207 # followed by optional exponent part if desired 

208 (?: [Ee] [+-]? \d+ ) ? 

209 """ 

210 rx = re.compile(numeric_const_pattern, re.VERBOSE) 

211 

212 nb = rx.findall(string) 

213 for i in enumerate(nb): 

214 nb[i[0]] = int(i[1]) 

215 

216 return np.array(nb)