Skip to content

Commit 99f62d2

Browse files
jsukparkjanosh
andauthored
Bugfix: io.pwscf.PWInput.from_str() (#3931)
* Bugfix: `io.pwscf.PWInput.from_str()` Fixes wrong parsing of: - Namelist options ending with comma (`,`) - `ATOMIC_SPECIES` and `ATOMIC_POSITIONS` cards for structures with oxidation states * Additional fix in regexp - Must only have one of either + or - in oxidation states, not one of both --------- Co-authored-by: Janosh Riebesell <[email protected]>
1 parent 4ffec03 commit 99f62d2

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

src/pymatgen/io/pwscf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ def input_mode(line):
292292
if match := re.match(r"(\w+)\(?(\d*?)\)?\s*=\s*(.*)", line):
293293
key = match[1].strip()
294294
key_ = match[2].strip()
295-
val = match[3].strip()
295+
val = match[3].strip().rstrip(",")
296296
if key_ != "":
297297
if sections[section].get(key) is None:
298298
val_ = [0.0] * 20 # MAX NTYP DEFINITION
@@ -306,7 +306,7 @@ def input_mode(line):
306306
sections[section][key] = PWInput.proc_val(key, val)
307307

308308
elif mode[0] == "pseudo":
309-
if match := re.match(r"(\w+)\s+(\d*.\d*)\s+(.*)", line):
309+
if match := re.match(r"(\w+\d*[\+-]?)\s+(\d*.\d*)\s+(.*)", line):
310310
pseudo[match[1].strip()] = match[3].strip()
311311

312312
elif mode[0] == "kpoints":
@@ -318,7 +318,7 @@ def input_mode(line):
318318

319319
elif mode[0] == "structure":
320320
m_l = re.match(r"(-?\d+\.?\d*)\s+(-?\d+\.?\d*)\s+(-?\d+\.?\d*)", line)
321-
m_p = re.match(r"(\w+)\s+(-?\d+\.\d*)\s+(-?\d+\.?\d*)\s+(-?\d+\.?\d*)", line)
321+
m_p = re.match(r"(\w+\d*[\+-]?)\s+(-?\d+\.\d*)\s+(-?\d+\.?\d*)\s+(-?\d+\.?\d*)", line)
322322
if m_l:
323323
lattice += [
324324
float(m_l[1]),

tests/io/test_pwscf.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,32 @@ def test_read_str(self):
376376
assert_allclose(lattice, pw_in.structure.lattice.matrix)
377377
assert pw_in.sections["system"]["smearing"] == "cold"
378378

379+
def test_write_and_read_str(self):
380+
struct = self.get_structure("Graphite")
381+
struct.remove_oxidation_states()
382+
pw = PWInput(
383+
struct,
384+
pseudo={"C": "C.pbe-n-kjpaw_psl.1.0.0.UPF"},
385+
control={"calculation": "scf", "pseudo_dir": "./"},
386+
system={"ecutwfc": 45},
387+
)
388+
pw_str = str(pw)
389+
assert pw_str.strip() == str(PWInput.from_str(pw_str)).strip()
390+
391+
def test_write_and_read_str_with_oxidation(self):
392+
struct = self.get_structure("Li2O")
393+
pw = PWInput(
394+
struct,
395+
control={"calculation": "scf", "pseudo_dir": "./"},
396+
pseudo={
397+
"Li+": "Li.pbe-n-kjpaw_psl.0.1.UPF",
398+
"O2-": "O.pbe-n-kjpaw_psl.0.1.UPF",
399+
},
400+
system={"ecutwfc": 50},
401+
)
402+
pw_str = str(pw)
403+
assert pw_str.strip() == str(PWInput.from_str(pw_str)).strip()
404+
379405

380406
class TestPWOutput(PymatgenTest):
381407
def setUp(self):

0 commit comments

Comments
 (0)