11import numpy as np
22
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+
3125default_config = {
4126 "GLOBAL" : {"PROJECT" : "DPGEN" },
5127 "FORCE_EVAL" : {
@@ -121,6 +243,46 @@ def iterdict(d, out_list, flag=None, indent=0):
121243 out_list .insert (index , " " * indent + k + " " + v )
122244
123245
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+
124286def make_cp2k_input (sys_data , fp_params ):
125287 # covert cell to cell string
126288 cell = sys_data ["cells" ][0 ]
@@ -132,14 +294,27 @@ def make_cp2k_input(sys_data, fp_params):
132294 cell_c = np .array2string (cell [2 , :])
133295 cell_c = cell_c [1 :- 1 ]
134296
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+
135307 # get update from user
136308 user_config = fp_params
137309 # get update from cell
138310 cell_config = {
139311 "FORCE_EVAL" : {"SUBSYS" : {"CELL" : {"A" : cell_a , "B" : cell_b , "C" : cell_c }}}
140312 }
313+ # get update for multiplicity
314+ multiplicity_config = {"FORCE_EVAL" : {"DFT" : {"MULTIPLICITY" : multiplicity }}}
141315 update_dict (default_config , user_config )
142316 update_dict (default_config , cell_config )
317+ update_dict (default_config , multiplicity_config )
143318 # output list
144319 input_str = []
145320 iterdict (default_config , input_str )
0 commit comments