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 re 

2import os 

3 

4from ase.data import atomic_masses, atomic_numbers 

5from ase.calculators.lammpsrun import LAMMPS 

6from ase.calculators.lammpslib import LAMMPSlib 

7from ase.calculators.lammps import convert 

8 

9from .kimmodel import KIMModelCalculator 

10from .exceptions import KIMCalculatorError 

11 

12 

13def KIMCalculator(model_name, options, debug): 

14 """ 

15 Used only for Portable Models 

16 """ 

17 

18 options_not_allowed = ["modelname", "debug"] 

19 

20 _check_conflict_options(options, options_not_allowed, simulator="kimmodel") 

21 

22 return KIMModelCalculator(model_name, debug=debug, **options) 

23 

24 

25def LAMMPSRunCalculator( 

26 model_name, model_type, supported_species, options, debug, **kwargs 

27): 

28 """ 

29 Used for Portable Models or LAMMPS Simulator Models if specifically requested 

30 """ 

31 

32 def get_params(model_name, supported_units, supported_species, atom_style): 

33 """ 

34 Extract parameters for LAMMPS calculator from model definition lines. 

35 Returns a dictionary with entries for "pair_style" and "pair_coeff". 

36 Expects there to be only one "pair_style" line. There can be multiple 

37 "pair_coeff" lines (result is returned as a list). 

38 """ 

39 parameters = {} 

40 

41 # In case the SM supplied its own atom_style in its model-init -- only needed 

42 # because lammpsrun writes data files and needs to know the proper format 

43 if atom_style: 

44 parameters["atom_style"] = atom_style 

45 

46 # Set units to prevent them from defaulting to metal 

47 parameters["units"] = supported_units 

48 

49 parameters["model_init"] = [ 

50 "kim_init {} {}{}".format(model_name, supported_units, os.linesep) 

51 ] 

52 

53 parameters["kim_interactions"] = "kim_interactions {}{}".format( 

54 (" ").join(supported_species), os.linesep 

55 ) 

56 

57 # For every species in "supported_species", add an entry to the 

58 # "masses" key in dictionary "parameters". 

59 parameters["masses"] = [] 

60 for i, species in enumerate(supported_species): 

61 if species not in atomic_numbers: 

62 raise KIMCalculatorError( 

63 "Could not determine mass of unknown species " 

64 "{} listed as supported by model".format(species) 

65 ) 

66 massstr = str( 

67 convert( 

68 atomic_masses[atomic_numbers[species]], 

69 "mass", 

70 "ASE", 

71 supported_units, 

72 ) 

73 ) 

74 parameters["masses"].append(str(i + 1) + " " + massstr) 

75 

76 return parameters 

77 

78 options_not_allowed = ["parameters", "files", "specorder", "keep_tmp_files"] 

79 

80 _check_conflict_options(options, options_not_allowed, simulator="lammpsrun") 

81 

82 # If no atom_style kwarg is passed, lammpsrun will default to atom_style atomic, 

83 # which is what we want for KIM Portable Models 

84 atom_style = kwargs.get("atom_style", None) 

85 

86 # Simulator Models will supply their own units from their metadata. For Portable 

87 # Models, we use "metal" units. 

88 supported_units = kwargs.get("supported_units", "metal") 

89 

90 # Set up kim_init and kim_interactions lines 

91 parameters = get_params(model_name, supported_units, supported_species, atom_style) 

92 

93 return LAMMPS( 

94 **parameters, specorder=supported_species, keep_tmp_files=debug, **options 

95 ) 

96 

97 

98def LAMMPSLibCalculator(model_name, supported_species, supported_units, options): 

99 """ 

100 Only used for LAMMPS Simulator Models 

101 """ 

102 options_not_allowed = [ 

103 "lammps_header", 

104 "lmpcmds", 

105 "atom_types", 

106 "log_file", 

107 "keep_alive", 

108 ] 

109 

110 _check_conflict_options(options, options_not_allowed, simulator="lammpslib") 

111 # Set up LAMMPS header commands lookup table 

112 

113 # This units command actually has no effect, but is necessary because 

114 # LAMMPSlib looks in the header lines for units in order to set them 

115 # internally 

116 model_init = ["units " + supported_units + os.linesep] 

117 

118 model_init.append( 

119 "kim_init {} {}{}".format(model_name, supported_units, os.linesep) 

120 ) 

121 model_init.append("atom_modify map array sort 0 0" + os.linesep) 

122 

123 # Assign atom types to species 

124 atom_types = {} 

125 for i_s, s in enumerate(supported_species): 

126 atom_types[s] = i_s + 1 

127 

128 kim_interactions = ["kim_interactions {}".format((" ").join(supported_species))] 

129 

130 # Return LAMMPSlib calculator 

131 return LAMMPSlib( 

132 lammps_header=model_init, 

133 lammps_name=None, 

134 lmpcmds=kim_interactions, 

135 post_changebox_cmds=kim_interactions, 

136 atom_types=atom_types, 

137 log_file="lammps.log", 

138 keep_alive=True, 

139 **options 

140 ) 

141 

142 

143def ASAPCalculator(model_name, model_type, options, **kwargs): 

144 """ 

145 Can be used with either Portable Models or Simulator Models 

146 """ 

147 import asap3 

148 

149 options_not_allowed = {"pm": ["name", "verbose"], "sm": ["Params"]} 

150 

151 _check_conflict_options(options, options_not_allowed[model_type], simulator="asap") 

152 

153 if model_type == "pm": 

154 

155 return asap3.OpenKIMcalculator( 

156 name=model_name, verbose=kwargs["verbose"], **options 

157 ) 

158 

159 elif model_type == "sm": 

160 model_defn = kwargs["model_defn"] 

161 supported_units = kwargs["supported_units"] 

162 

163 # Verify units (ASAP models are expected to work with "ase" units) 

164 if supported_units != "ase": 

165 raise KIMCalculatorError( 

166 'KIM Simulator Model units are "{}", but expected to ' 

167 'be "ase" for ASAP.'.format(supported_units) 

168 ) 

169 

170 # Check model_defn to make sure there's only one element in it that is a 

171 # non-empty string 

172 if len(model_defn) == 0: 

173 raise KIMCalculatorError( 

174 "model-defn is an empty list in metadata file of Simulator Model {}" 

175 "".format(model_name) 

176 ) 

177 elif len(model_defn) > 1: 

178 raise KIMCalculatorError( 

179 "model-defn should contain only one entry for an ASAP model (found {} " 

180 "lines)".format(len(model_defn)) 

181 ) 

182 

183 if "" in model_defn: 

184 raise KIMCalculatorError( 

185 "model-defn contains an empty string in metadata file of Simulator " 

186 "Model {}".format(model_name) 

187 ) 

188 

189 model_defn = model_defn[0].strip() 

190 

191 # Instantiate calculator from ASAP. Currently, this must be one of: 

192 # (1) EMT 

193 # (2) EMT(EMTRasmussenParameters) 

194 # (3) EMT(EMTMetalGlassParameters) 

195 model_defn_is_valid = False 

196 if model_defn.startswith("EMT"): 

197 # Pull out potential parameters 

198 mobj = re.search(r"\(([A-Za-z0-9_\(\)]+)\)", model_defn) 

199 if mobj is None: 

200 asap_calc = asap3.EMT() 

201 else: 

202 pp = mobj.group(1) 

203 

204 # Currently we only supported two specific EMT models that are built 

205 # into ASAP 

206 if pp.startswith("EMTRasmussenParameters"): 

207 asap_calc = asap3.EMT(parameters=asap3.EMTRasmussenParameters()) 

208 model_defn_is_valid = True 

209 elif pp.startswith("EMTMetalGlassParameters"): 

210 asap_calc = asap3.EMT(parameters=asap3.EMTMetalGlassParameters()) 

211 model_defn_is_valid = True 

212 

213 if not model_defn_is_valid: 

214 raise KIMCalculatorError( 

215 'Unknown model "{}" requested for simulator asap.'.format(model_defn) 

216 ) 

217 

218 # Disable undocumented feature for the EMT self.calculators to take the 

219 # energy of an isolated atoms as zero. (Otherwise it is taken to be that of 

220 # perfect FCC.) 

221 asap_calc.set_subtractE0(False) 

222 

223 return asap_calc 

224 

225 

226def _check_conflict_options(options, options_not_allowed, simulator): 

227 """Check whether options intended to be passed to a given calculator are allowed. 

228 Some options are not allowed because they must be set internally in this package. 

229 """ 

230 s1 = set(options) 

231 s2 = set(options_not_allowed) 

232 common = s1.intersection(s2) 

233 

234 if common: 

235 options_in_not_allowed = ", ".join(['"{}"'.format(s) for s in common]) 

236 

237 msg = ( 

238 'Simulator "{}" does not support argument(s): {} provided in "options", ' 

239 "because it is (they are) determined internally within the KIM " 

240 "calculator".format(simulator, options_in_not_allowed) 

241 ) 

242 

243 raise KIMCalculatorError(msg)