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

1import numpy as np 

2from itertools import product 

3 

4 

5def write_fcs_gpumd(fname_fc, fname_clusters, fcs, order, tol=1e-10): 

6 """ 

7 Writes force constants of given order in GPUMD format. 

8 

9 Parameters 

10 ---------- 

11 fname_fc : str 

12 name of file which contains the lookup force constants 

13 fname_clusters : str 

14 name of file which contains the clusters and the fc lookup index 

15 fcs : ForceConstants 

16 force constants 

17 order : int 

18 force constants for this order will be written to file 

19 tol : float 

20 if the norm of a force constant is less than tol then it is not written. 

21 if two force-constants are within tol; they are considered equal. 

22 """ 

23 cluster_lookup, fc_lookup = _get_lookup_data_smart(fcs, order, tol) 

24 _write_clusters(fname_clusters, cluster_lookup, order) 

25 _write_fc_lookup(fname_fc, fc_lookup, order) 

26 

27 

28def _write_fc_lookup(fname, fc_lookup, order): 

29 """ Writes the lookup force constants to file """ 

30 fmt = '{}' + ' {}'*order 

31 with open(fname, 'w') as f: 

32 f.write(str(len(fc_lookup)) + '\n\n') 

33 for fc in fc_lookup: 

34 for xyz in product(range(3), repeat=order): 

35 f.write(fmt.format(*xyz, fc[xyz])+'\n') 

36 f.write('\n') 

37 

38 

39def _write_clusters(fname, cluster_lookup, order): 

40 """ Writes the cluster lookup to file """ 

41 fmt = '{}' + ' {}'*order 

42 with open(fname, 'w') as f: 

43 f.write(str(len(cluster_lookup)) + '\n\n') 

44 for c, i in cluster_lookup.items(): 

45 line = fmt.format(*c, i) + '\n' 

46 f.write(line) 

47 

48 

49def _get_lookup_data_smart(fcs, order, tol): 

50 """ Groups force constants for a given order into groups for which the 

51 force constant is identical. """ 

52 fc_lookup = [] 

53 cluster_lookup = dict() 

54 axis = tuple(range(1, order+1)) 

55 

56 clusters = [c for c in fcs._fc_dict.keys() if len(c) == order and np.linalg.norm(fcs[c]) > tol] 

57 fc_all = np.array([fcs[c] for c in clusters]) 

58 

59 indices = list(range(len(clusters))) 

60 while len(indices) > 0: 

61 i = indices[0] 

62 delta = fc_all[indices] - fc_all[i] 

63 delta_norm = np.sqrt(np.sum(delta**2, axis=axis)) 

64 

65 inds_to_del = [indices[x] for x in np.where(delta_norm < tol)[0]] 

66 assert i in inds_to_del 

67 

68 fc_lookup.append(fc_all[i]) 

69 for j in inds_to_del: 

70 indices.remove(j) 

71 cluster_lookup[clusters[j]] = len(fc_lookup)-1 

72 return cluster_lookup, fc_lookup 

73 

74 

75def _get_lookup_data_naive(fcs, order, tol): 

76 """ Groups force constants for a given order into groups for which the 

77 force constant is identical. """ 

78 fc_lookup = [] 

79 cluster_lookup = dict() 

80 clusters = [c for c in fcs._fc_dict.keys() if len(c) == order] 

81 for c in clusters: 

82 fc1 = fcs[c] 

83 if np.linalg.norm(fc1) < tol: 

84 continue 

85 for i, fc2 in enumerate(fc_lookup): 

86 if np.linalg.norm(fc1 - fc2) < tol: 

87 cluster_lookup[c] = i 

88 break 

89 else: 

90 cluster_lookup[c] = len(fc_lookup) 

91 fc_lookup.append(fc1) 

92 return cluster_lookup, fc_lookup 

93 

94 

95def write_fcp_txt(fname, path, n_types, max_order): 

96 """ Write driver potential file for GPUMD. 

97 

98 Parameters 

99 ---------- 

100 fname : str 

101 file name 

102 path : str 

103 path to directory with force constant file 

104 n_types : int 

105 number of atom types 

106 max_order : int 

107 maximum order of the force constant potential 

108 

109 Format 

110 ------ 

111 Format is a simple file containing the following 

112 

113 fcp number_of_atom_types 

114 highest_order 

115 path_to_force_constant_files 

116 

117 which in practice for a binary system with a sixth order model would mean 

118 

119 fcp 2 

120 6 

121 /path/to/your/folder 

122 """ 

123 

124 with open(fname, 'w') as f: 

125 f.write('fcp {}\n'.format(n_types)) 

126 f.write('{}\n'.format(max_order)) 

127 f.write('{}'.format(path.rstrip('/'))) # without a trailing '/' 

128 

129 

130def write_r0(fname, atoms): 

131 """ 

132 Write GPUMD r0 file, with reference atomic positions. 

133 

134 Parameters 

135 ---------- 

136 fname : str 

137 name of file to which to write the atomic positions 

138 atoms : ase.Atoms 

139 input structure 

140 

141 """ 

142 line = '{} {} {}\n' 

143 with open(fname, 'w') as f: 

144 for a in atoms: 

145 f.write(line.format(*a.position))