1
1
import numpy as np
2
2
3
+ atomic_numbers = {
4
+ "H" : 1 ,
5
+ "He" : 2 ,
6
+ "Li" : 3 ,
7
+ "Be" : 4 ,
8
+ "B" : 5 ,
9
+ "C" : 6 ,
10
+ "N" : 7 ,
11
+ "O" : 8 ,
12
+ "F" : 9 ,
13
+ "Ne" : 10 ,
14
+ "Na" : 11 ,
15
+ "Mg" : 12 ,
16
+ "Al" : 13 ,
17
+ "Si" : 14 ,
18
+ "P" : 15 ,
19
+ "S" : 16 ,
20
+ "Cl" : 17 ,
21
+ "Ar" : 18 ,
22
+ "K" : 19 ,
23
+ "Ca" : 20 ,
24
+ "Sc" : 21 ,
25
+ "Ti" : 22 ,
26
+ "V" : 23 ,
27
+ "Cr" : 24 ,
28
+ "Mn" : 25 ,
29
+ "Fe" : 26 ,
30
+ "Co" : 27 ,
31
+ "Ni" : 28 ,
32
+ "Cu" : 29 ,
33
+ "Zn" : 30 ,
34
+ "Ga" : 31 ,
35
+ "Ge" : 32 ,
36
+ "As" : 33 ,
37
+ "Se" : 34 ,
38
+ "Br" : 35 ,
39
+ "Kr" : 36 ,
40
+ "Rb" : 37 ,
41
+ "Sr" : 38 ,
42
+ "Y" : 39 ,
43
+ "Zr" : 40 ,
44
+ "Nb" : 41 ,
45
+ "Mo" : 42 ,
46
+ "Tc" : 43 ,
47
+ "Ru" : 44 ,
48
+ "Rh" : 45 ,
49
+ "Pd" : 46 ,
50
+ "Ag" : 47 ,
51
+ "Cd" : 48 ,
52
+ "In" : 49 ,
53
+ "Sn" : 50 ,
54
+ "Sb" : 51 ,
55
+ "Te" : 52 ,
56
+ "I" : 53 ,
57
+ "Xe" : 54 ,
58
+ "Cs" : 55 ,
59
+ "Ba" : 56 ,
60
+ "La" : 57 ,
61
+ "Ce" : 58 ,
62
+ "Pr" : 59 ,
63
+ "Nd" : 60 ,
64
+ "Pm" : 61 ,
65
+ "Sm" : 62 ,
66
+ "Eu" : 63 ,
67
+ "Gd" : 64 ,
68
+ "Tb" : 65 ,
69
+ "Dy" : 66 ,
70
+ "Ho" : 67 ,
71
+ "Er" : 68 ,
72
+ "Tm" : 69 ,
73
+ "Yb" : 70 ,
74
+ "Lu" : 71 ,
75
+ "Hf" : 72 ,
76
+ "Ta" : 73 ,
77
+ "W" : 74 ,
78
+ "Re" : 75 ,
79
+ "Os" : 76 ,
80
+ "Ir" : 77 ,
81
+ "Pt" : 78 ,
82
+ "Au" : 79 ,
83
+ "Hg" : 80 ,
84
+ "Tl" : 81 ,
85
+ "Pb" : 82 ,
86
+ "Bi" : 83 ,
87
+ "Po" : 84 ,
88
+ "At" : 85 ,
89
+ "Rn" : 86 ,
90
+ "Fr" : 87 ,
91
+ "Ra" : 88 ,
92
+ "Ac" : 89 ,
93
+ "Th" : 90 ,
94
+ "Pa" : 91 ,
95
+ "U" : 92 ,
96
+ "Np" : 93 ,
97
+ "Pu" : 94 ,
98
+ "Am" : 95 ,
99
+ "Cm" : 96 ,
100
+ "Bk" : 97 ,
101
+ "Cf" : 98 ,
102
+ "Es" : 99 ,
103
+ "Fm" : 100 ,
104
+ "Md" : 101 ,
105
+ "No" : 102 ,
106
+ "Lr" : 103 ,
107
+ "Rf" : 104 ,
108
+ "Db" : 105 ,
109
+ "Sg" : 106 ,
110
+ "Bh" : 107 ,
111
+ "Hs" : 108 ,
112
+ "Mt" : 109 ,
113
+ "Ds" : 110 ,
114
+ "Rg" : 111 ,
115
+ "Cn" : 112 ,
116
+ "Nh" : 113 ,
117
+ "Fl" : 114 ,
118
+ "Mc" : 115 ,
119
+ "Lv" : 116 ,
120
+ "Ts" : 117 ,
121
+ "Og" : 118 ,
122
+ }
123
+
124
+
3
125
default_config = {
4
126
"GLOBAL" : {"PROJECT" : "DPGEN" },
5
127
"FORCE_EVAL" : {
@@ -121,6 +243,46 @@ def iterdict(d, out_list, flag=None, indent=0):
121
243
out_list .insert (index , " " * indent + k + " " + v )
122
244
123
245
246
+ def calculate_multiplicity (atom_names , atom_types , charge = 0 ):
247
+ """
248
+ Calculate the multiplicity based on atom species, quantities, and system charge.
249
+
250
+ This function provides a basic heuristic for determining multiplicity:
251
+ - Even number of electrons -> singlet (multiplicity = 1)
252
+ - Odd number of electrons -> doublet (multiplicity = 2)
253
+
254
+ Note: This approach assumes that an odd electron count always results in a doublet state.
255
+ It does not account for systems with multiple unpaired electrons, which can have higher
256
+ multiplicities (e.g., triplet, quartet, etc.). Users should be aware of this limitation
257
+ and use the function accordingly.
258
+
259
+ :param atom_names: List of element symbols.
260
+ :param atom_types: List of atom type indices.
261
+ :param charge: System charge (default: 0).
262
+ :return: Multiplicity.
263
+ """
264
+ # Calculate the total number of electrons
265
+ total_electrons = 0
266
+ for idx in atom_types :
267
+ element = atom_names [idx ]
268
+ try :
269
+ total_electrons += atomic_numbers [element ]
270
+ except KeyError :
271
+ raise ValueError (f"Unknown element '{ element } ' encountered in atom_names." )
272
+
273
+ # Subtract/add electrons based on system charge
274
+ # Positive charge means we remove electrons, negative charge means we add electrons
275
+ total_electrons -= charge
276
+
277
+ # Determine multiplicity based on the total number of electrons
278
+ # Even number of electrons -> singlet (multiplicity = 1)
279
+ # Odd number of electrons -> doublet (multiplicity = 2)
280
+ if total_electrons % 2 == 0 :
281
+ return 1
282
+ else :
283
+ return 2
284
+
285
+
124
286
def make_cp2k_input (sys_data , fp_params ):
125
287
# covert cell to cell string
126
288
cell = sys_data ["cells" ][0 ]
@@ -132,14 +294,27 @@ def make_cp2k_input(sys_data, fp_params):
132
294
cell_c = np .array2string (cell [2 , :])
133
295
cell_c = cell_c [1 :- 1 ]
134
296
297
+ atom_names = sys_data ["atom_names" ]
298
+ atom_types = sys_data ["atom_types" ]
299
+ # Get system charge if provided, default to 0
300
+ charge = sys_data .get ("charge" , 0 )
301
+ dft_params = fp_params .get ("FORCE_EVAL" , {}).get ("DFT" , {})
302
+ if "MULTIPLICITY" in dft_params :
303
+ multiplicity = dft_params ["MULTIPLICITY" ]
304
+ else :
305
+ multiplicity = calculate_multiplicity (atom_names , atom_types , charge )
306
+
135
307
# get update from user
136
308
user_config = fp_params
137
309
# get update from cell
138
310
cell_config = {
139
311
"FORCE_EVAL" : {"SUBSYS" : {"CELL" : {"A" : cell_a , "B" : cell_b , "C" : cell_c }}}
140
312
}
313
+ # get update for multiplicity
314
+ multiplicity_config = {"FORCE_EVAL" : {"DFT" : {"MULTIPLICITY" : multiplicity }}}
141
315
update_dict (default_config , user_config )
142
316
update_dict (default_config , cell_config )
317
+ update_dict (default_config , multiplicity_config )
143
318
# output list
144
319
input_str = []
145
320
iterdict (default_config , input_str )
0 commit comments