@@ -47,13 +47,213 @@ def get_block(lines, keyword, skip=0):
4747 return ret
4848
4949
50+ def _parse_lattice_parameters (lines ):
51+ """Parse lattice parameters from QE input lines."""
52+ params = {}
53+ for iline in lines :
54+ line = iline .replace ("=" , " " ).replace ("," , "" ).split ()
55+ if len (line ) >= 2 :
56+ if line [0 ] == "a" :
57+ params ["a" ] = float (line [1 ])
58+ elif line [0 ] == "b" :
59+ params ["b" ] = float (line [1 ])
60+ elif line [0 ] == "c" :
61+ params ["c" ] = float (line [1 ])
62+ elif line [0 ] == "cosab" :
63+ params ["cosab" ] = float (line [1 ])
64+ elif line [0 ] == "cosac" :
65+ params ["cosac" ] = float (line [1 ])
66+ elif line [0 ] == "cosbc" :
67+ params ["cosbc" ] = float (line [1 ])
68+ elif line [0 ].startswith ("celldm(" ):
69+ # Extract celldm index from celldm(1), celldm(2), etc.
70+ idx = int (line [0 ][7 :- 1 ]) # Extract number from celldm(n)
71+ if "celldm" not in params :
72+ params ["celldm" ] = {}
73+ params ["celldm" ][idx ] = float (line [1 ])
74+ return params
75+
76+
77+ def _convert_ibrav_to_cell (ibrav , params ):
78+ """Convert ibrav and lattice parameters to cell matrix."""
79+ # Extract parameters
80+ a = params .get ("a" )
81+ b = params .get ("b" )
82+ c = params .get ("c" )
83+ cosab = params .get ("cosab" , 0.0 )
84+ cosac = params .get ("cosac" , 0.0 )
85+ cosbc = params .get ("cosbc" , 0.0 )
86+ celldm = params .get ("celldm" , {})
87+
88+ # Convert celldm parameters if present (celldm is in atomic units)
89+ if 1 in celldm :
90+ a = celldm [1 ] * bohr2ang if a is None else a
91+ if 2 in celldm and a is not None :
92+ b = celldm [2 ] * a if b is None else b
93+ if 3 in celldm and a is not None :
94+ c = celldm [3 ] * a if c is None else c
95+ if 4 in celldm :
96+ cosab = celldm [4 ] if cosab == 0.0 else cosab
97+ if 5 in celldm :
98+ cosac = celldm [5 ] if cosac == 0.0 else cosac
99+ if 6 in celldm :
100+ cosbc = celldm [6 ] if cosbc == 0.0 else cosbc
101+
102+ # Set defaults only for ibrav types that don't require explicit b,c
103+ if ibrav in [1 , 2 , 3 , - 3 ]: # Cubic lattices
104+ if b is None :
105+ b = a
106+ if c is None :
107+ c = a
108+ elif ibrav in [6 , 7 ]: # Tetragonal lattices
109+ if b is None :
110+ b = a
111+ # c must be specified explicitly
112+
113+ # Validate required parameters
114+ if a is None :
115+ raise RuntimeError ("parameter 'a' or 'celldm(1)' cannot be found." )
116+
117+ # Generate cell matrix based on ibrav
118+ if ibrav == 1 : # simple cubic
119+ return np .array ([[a , 0.0 , 0.0 ], [0.0 , a , 0.0 ], [0.0 , 0.0 , a ]])
120+
121+ elif ibrav == 2 : # face-centered cubic
122+ return a * 0.5 * np .array ([[- 1 , 0 , 1 ], [0 , 1 , 1 ], [- 1 , 1 , 0 ]])
123+
124+ elif ibrav == 3 : # body-centered cubic
125+ return a * 0.5 * np .array ([[1 , 1 , 1 ], [- 1 , 1 , 1 ], [- 1 , - 1 , 1 ]])
126+
127+ elif ibrav == - 3 : # reverse body-centered cubic
128+ return a * 0.5 * np .array ([[- 1 , 1 , 1 ], [1 , - 1 , 1 ], [1 , 1 , - 1 ]])
129+
130+ elif ibrav == 4 : # hexagonal
131+ if c is None :
132+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=4" )
133+ return np .array ([[a , 0 , 0 ],
134+ [- a / 2 , a * np .sqrt (3 )/ 2 , 0 ],
135+ [0 , 0 , c ]])
136+
137+ elif ibrav == 6 : # simple tetragonal
138+ if c is None :
139+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=6" )
140+ return np .array ([[a , 0 , 0 ], [0 , a , 0 ], [0 , 0 , c ]])
141+
142+ elif ibrav == 7 : # body-centered tetragonal
143+ if c is None :
144+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=7" )
145+ return np .array ([[a / 2 , - a / 2 , c / 2 ],
146+ [a / 2 , a / 2 , c / 2 ],
147+ [- a / 2 , - a / 2 , c / 2 ]])
148+
149+ elif ibrav == 8 : # simple orthorhombic
150+ if b is None :
151+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=8" )
152+ if c is None :
153+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=8" )
154+ return np .array ([[a , 0 , 0 ], [0 , b , 0 ], [0 , 0 , c ]])
155+
156+ elif ibrav == 9 : # base-centered orthorhombic
157+ if b is None :
158+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=9" )
159+ if c is None :
160+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=9" )
161+ return np .array ([[a / 2 , b / 2 , 0 ],
162+ [- a / 2 , b / 2 , 0 ],
163+ [0 , 0 , c ]])
164+
165+ elif ibrav == - 9 : # reverse base-centered orthorhombic
166+ if b is None :
167+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=-9" )
168+ if c is None :
169+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=-9" )
170+ return np .array ([[a / 2 , - b / 2 , 0 ],
171+ [a / 2 , b / 2 , 0 ],
172+ [0 , 0 , c ]])
173+
174+ elif ibrav == 10 : # face-centered orthorhombic
175+ if b is None :
176+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=10" )
177+ if c is None :
178+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=10" )
179+ return np .array ([[a / 2 , 0 , c / 2 ],
180+ [a / 2 , b / 2 , 0 ],
181+ [0 , b / 2 , c / 2 ]])
182+
183+ elif ibrav == 11 : # body-centered orthorhombic
184+ if b is None :
185+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=11" )
186+ if c is None :
187+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=11" )
188+ return np .array ([[a / 2 , b / 2 , c / 2 ],
189+ [- a / 2 , b / 2 , c / 2 ],
190+ [- a / 2 , - b / 2 , c / 2 ]])
191+
192+ elif ibrav == 12 : # simple monoclinic
193+ if b is None :
194+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=12" )
195+ if c is None :
196+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=12" )
197+ sinab = np .sqrt (1 - cosab ** 2 )
198+ return np .array ([[a , 0 , 0 ],
199+ [b * cosab , b * sinab , 0 ],
200+ [0 , 0 , c ]])
201+
202+ elif ibrav == - 12 : # reverse monoclinic
203+ if b is None :
204+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=-12" )
205+ if c is None :
206+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=-12" )
207+ sinac = np .sqrt (1 - cosac ** 2 )
208+ return np .array ([[a , 0 , 0 ],
209+ [0 , b , 0 ],
210+ [c * cosac , 0 , c * sinac ]])
211+
212+ elif ibrav == 13 : # base-centered monoclinic
213+ if b is None :
214+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=13" )
215+ if c is None :
216+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=13" )
217+ sinab = np .sqrt (1 - cosab ** 2 )
218+ return np .array ([[a / 2 , 0 , - c / 2 ],
219+ [b * cosab , b * sinab , 0 ],
220+ [a / 2 , 0 , c / 2 ]])
221+
222+ elif ibrav == - 13 : # reverse base-centered monoclinic
223+ if b is None :
224+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=-13" )
225+ if c is None :
226+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=-13" )
227+ sinac = np .sqrt (1 - cosac ** 2 )
228+ return np .array ([[a / 2 , - b / 2 , 0 ],
229+ [a / 2 , b / 2 , 0 ],
230+ [c * cosac , 0 , c * sinac ]])
231+
232+ elif ibrav == 14 : # triclinic
233+ if b is None :
234+ raise RuntimeError ("parameter 'b' or 'celldm(2)' required for ibrav=14" )
235+ if c is None :
236+ raise RuntimeError ("parameter 'c' or 'celldm(3)' required for ibrav=14" )
237+ sinab = np .sqrt (1 - cosab ** 2 )
238+ sinac = np .sqrt (1 - cosac ** 2 )
239+ cosbc_prime = (cosbc - cosab * cosac ) / (sinab * sinac )
240+ sinbc_prime = np .sqrt (1 - cosbc_prime ** 2 )
241+ return np .array ([[a , 0 , 0 ],
242+ [b * cosab , b * sinab , 0 ],
243+ [c * cosac , c * sinac * cosbc_prime , c * sinac * sinbc_prime ]])
244+
245+ else :
246+ raise RuntimeError (f"ibrav = { ibrav } is not supported yet." )
247+
248+
50249def get_cell (lines ):
51250 ret = []
52251 for idx , ii in enumerate (lines ):
53252 if "ibrav" in ii :
54253 break
55254 blk = lines [idx : idx + 2 ]
56255 ibrav = int (blk [0 ].replace ("," , "" ).split ("=" )[- 1 ])
256+
57257 if ibrav == 0 :
58258 for iline in lines :
59259 if "CELL_PARAMETERS" in iline and "angstrom" not in iline .lower ():
@@ -64,21 +264,11 @@ def get_cell(lines):
64264 for ii in blk :
65265 ret .append ([float (jj ) for jj in ii .split ()[0 :3 ]])
66266 ret = np .array (ret )
67- elif ibrav == 1 :
68- a = None
69- for iline in lines :
70- line = iline .replace ("=" , " " ).replace ("," , "" ).split ()
71- if len (line ) >= 2 and "a" == line [0 ]:
72- # print("line = ", line)
73- a = float (line [1 ])
74- if len (line ) >= 2 and "celldm(1)" == line [0 ]:
75- a = float (line [1 ]) * bohr2ang
76- # print("a = ", a)
77- if not a :
78- raise RuntimeError ("parameter 'a' or 'celldm(1)' cannot be found." )
79- ret = np .array ([[a , 0.0 , 0.0 ], [0.0 , a , 0.0 ], [0.0 , 0.0 , a ]])
80267 else :
81- raise RuntimeError ("ibrav > 1 not supported yet." )
268+ # Parse lattice parameters and convert based on ibrav
269+ params = _parse_lattice_parameters (lines )
270+ ret = _convert_ibrav_to_cell (ibrav , params )
271+
82272 return ret
83273
84274
0 commit comments