Skip to content

Commit ec08ebb

Browse files
shigeandtomoyaotang.zhangchouyoudou
authored
Add new format for OpenMX (#585)
Dear developers, I added a new format key, `openmx` to read output files from OpenMX. I wrote the codes with reference to the `qe/cp/traj` format ones. Thank you in advance. --------- Co-authored-by: yaotang.zhang <[email protected]> Co-authored-by: Zhang Yaotang <[email protected]>
1 parent e948661 commit ec08ebb

File tree

7 files changed

+1802
-0
lines changed

7 files changed

+1802
-0
lines changed

.DS_Store

8 KB
Binary file not shown.

dpdata/openmx/__init__.py

Whitespace-only changes.

dpdata/openmx/omx.py

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#!/usr/bin/python3
2+
import numpy as np
3+
4+
from ..unit import (
5+
EnergyConversion,
6+
ForceConversion,
7+
LengthConversion,
8+
PressureConversion,
9+
)
10+
11+
ry2ev = EnergyConversion("rydberg", "eV").value()
12+
kbar2evperang3 = PressureConversion("kbar", "eV/angstrom^3").value()
13+
14+
length_convert = LengthConversion("bohr", "angstrom").value()
15+
energy_convert = EnergyConversion("hartree", "eV").value()
16+
force_convert = ForceConversion("hartree/bohr", "eV/angstrom").value()
17+
18+
from collections import OrderedDict
19+
20+
### iterout.c from OpenMX soure code: column numbers and physical quantities ###
21+
# /* 1: */
22+
# /* 2,3,4: */
23+
# /* 5,6,7: force *
24+
# /* 8: x-component of velocity */
25+
# /* 9: y-component of velocity */
26+
# /* 10: z-component of velocity */
27+
# /* 11: Net charge, electron charge is defined to be negative. */
28+
# /* 12: magnetic moment (muB) */
29+
# /* 13,14: angles of spin */
30+
31+
32+
def load_atom(lines):
33+
atom_names = []
34+
atom_names_mode = False
35+
for line in lines:
36+
if "<Atoms.SpeciesAndCoordinates" in line:
37+
atom_names_mode = True
38+
elif "Atoms.SpeciesAndCoordinates>" in line:
39+
atom_names_mode = False
40+
elif atom_names_mode:
41+
parts = line.split()
42+
atom_names.append(parts[1])
43+
natoms = len(atom_names)
44+
atom_names_original = atom_names
45+
atom_names = list(OrderedDict.fromkeys(set(atom_names))) # Python>=3.7
46+
atom_names = sorted(
47+
atom_names, key=atom_names_original.index
48+
) # Unique ordering of atomic species
49+
ntypes = len(atom_names)
50+
atom_numbs = [0] * ntypes
51+
atom_types = []
52+
atom_types_mode = False
53+
for line in lines:
54+
if "<Atoms.SpeciesAndCoordinates" in line:
55+
atom_types_mode = True
56+
elif "Atoms.SpeciesAndCoordinates>" in line:
57+
atom_types_mode = False
58+
elif atom_types_mode:
59+
parts = line.split()
60+
for i, atom_name in enumerate(atom_names):
61+
if parts[1] == atom_name:
62+
atom_numbs[i] += 1
63+
atom_types.append(i)
64+
atom_types = np.array(atom_types)
65+
return atom_names, atom_types, atom_numbs
66+
67+
68+
def load_cells(lines):
69+
cell, cells = [], []
70+
for index, line in enumerate(lines):
71+
if "Cell_Vectors=" in line:
72+
parts = line.split()
73+
cell.append([float(parts[12]), float(parts[13]), float(parts[14])])
74+
cell.append([float(parts[15]), float(parts[16]), float(parts[17])])
75+
cell.append([float(parts[18]), float(parts[19]), float(parts[20])])
76+
cells.append(cell)
77+
cell = []
78+
cells = np.array(cells)
79+
return cells
80+
81+
82+
# load atom_names, atom_numbs, atom_types, cells
83+
def load_param_file(fname, mdname):
84+
with open(fname) as dat_file:
85+
lines = dat_file.readlines()
86+
atom_names, atom_types, atom_numbs = load_atom(lines)
87+
88+
with open(mdname) as md_file:
89+
lines = md_file.readlines()
90+
cells = load_cells(lines)
91+
return atom_names, atom_numbs, atom_types, cells
92+
93+
94+
def load_coords(lines, atom_names, natoms):
95+
cnt = 0
96+
coord, coords = [], []
97+
for index, line in enumerate(lines):
98+
if "time=" in line:
99+
continue
100+
for atom_name in atom_names:
101+
atom_name += " "
102+
if atom_name in line:
103+
cnt += 1
104+
parts = line.split()
105+
for_line = [float(parts[1]), float(parts[2]), float(parts[3])]
106+
coord.append(for_line)
107+
if cnt == natoms:
108+
coords.append(coord)
109+
cnt = 0
110+
coord = []
111+
coords = np.array(coords)
112+
return coords
113+
114+
115+
def load_data(mdname, atom_names, natoms):
116+
with open(mdname) as md_file:
117+
lines = md_file.readlines()
118+
coords = load_coords(lines, atom_names, natoms)
119+
steps = [str(i) for i in range(1, coords.shape[0] + 1)]
120+
return coords, steps
121+
122+
123+
def to_system_data(fname, mdname):
124+
data = {}
125+
(
126+
data["atom_names"],
127+
data["atom_numbs"],
128+
data["atom_types"],
129+
data["cells"],
130+
) = load_param_file(fname, mdname)
131+
data["coords"], steps = load_data(
132+
mdname,
133+
data["atom_names"],
134+
np.sum(data["atom_numbs"]),
135+
)
136+
data["orig"] = np.zeros(3)
137+
return data, steps
138+
139+
140+
def load_energy(lines):
141+
energy = []
142+
for line in lines:
143+
if "time=" in line:
144+
parts = line.split()
145+
ene_line = float(parts[4]) # Hartree
146+
energy.append(ene_line)
147+
continue
148+
energy = energy_convert * np.array(energy) # Hartree -> eV
149+
return energy
150+
151+
152+
def load_force(lines, atom_names, atom_numbs):
153+
cnt = 0
154+
field, fields = [], []
155+
for index, line in enumerate(lines):
156+
if "time=" in line:
157+
continue
158+
for atom_name in atom_names:
159+
atom_name += " "
160+
if atom_name in line:
161+
cnt += 1
162+
parts = line.split()
163+
for_line = [float(parts[4]), float(parts[5]), float(parts[6])]
164+
field.append(for_line)
165+
if cnt == np.sum(atom_numbs):
166+
fields.append(field)
167+
cnt = 0
168+
field = []
169+
force = force_convert * np.array(fields)
170+
return force
171+
172+
173+
# load energy, force
174+
def to_system_label(fname, mdname):
175+
atom_names, atom_numbs, atom_types, cells = load_param_file(fname, mdname)
176+
with open(mdname) as md_file:
177+
lines = md_file.readlines()
178+
energy = load_energy(lines)
179+
force = load_force(lines, atom_names, atom_numbs)
180+
return energy, force
181+
182+
183+
if __name__ == "__main__":
184+
file_name = "Cdia"
185+
fname = f"{file_name}.dat"
186+
mdname = f"{file_name}.md"
187+
atom_names, atom_numbs, atom_types, cells = load_param_file(fname, mdname)
188+
coords, steps = load_data(mdname, atom_names, np.sum(atom_numbs))
189+
data, steps = to_system_data(fname, mdname)
190+
energy, force = to_system_label(fname, mdname)
191+
print(atom_names)
192+
print(atom_numbs)
193+
print(atom_types)
194+
# print(cells.shape)
195+
# print(coords.shape)
196+
# print(len(energy))
197+
# print(force.shape)

dpdata/plugins/openmx.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import dpdata.md.pbc
2+
import dpdata.openmx.omx
3+
from dpdata.format import Format
4+
5+
6+
@Format.register("openmx/out")
7+
class OPENMXFormat(Format):
8+
"""Format for the `OpenMX <https://www.openmx-square.org/>`.
9+
10+
OpenMX (Open source package for Material eXplorer) is a nano-scale material simulation package based on DFT, norm-conserving pseudopotentials, and pseudo-atomic localized basis functions.
11+
12+
Note that two output files, System.Name.dat and System.Name.md, are required.
13+
14+
Use the `openmx/out` keyword argument to supply this format.
15+
"""
16+
17+
@Format.post("rot_lower_triangular")
18+
def from_system(self, file_name: str, **kwargs) -> dict:
19+
"""Read from OpenMX output.
20+
21+
Parameters
22+
----------
23+
file_name : str
24+
file name, which is specified by a input file, i.e. System.Name.dat
25+
**kwargs : dict
26+
other parameters
27+
28+
Returns
29+
-------
30+
dict
31+
data dict
32+
"""
33+
fname = f"{file_name}.dat"
34+
mdname = f"{file_name}.md"
35+
36+
data, _ = dpdata.openmx.omx.to_system_data(fname, mdname)
37+
data["coords"] = dpdata.md.pbc.apply_pbc(
38+
data["coords"],
39+
data["cells"],
40+
)
41+
return data
42+
43+
@Format.post("rot_lower_triangular")
44+
def from_labeled_system(self, file_name: str, **kwargs) -> dict:
45+
"""Read from OpenMX output.
46+
47+
Parameters
48+
----------
49+
file_name : str
50+
file name, which is specified by a input file, i.e. System.Name.dat
51+
**kwargs : dict
52+
other parameters
53+
54+
Returns
55+
-------
56+
dict
57+
data dict
58+
"""
59+
fname = f"{file_name}.dat"
60+
mdname = f"{file_name}.md"
61+
62+
data, cs = dpdata.openmx.omx.to_system_data(fname, mdname)
63+
data["coords"] = dpdata.md.pbc.apply_pbc(
64+
data["coords"],
65+
data["cells"],
66+
)
67+
data["energies"], data["forces"] = dpdata.openmx.omx.to_system_label(
68+
fname, mdname
69+
)
70+
return data

tests/openmx/Methane.dat

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#
2+
# File Name
3+
#
4+
5+
System.CurrrentDirectory ./ # default=./
6+
System.Name Methane
7+
level.of.stdout 1 # default=1 (1-3)
8+
level.of.fileout 1 # default=1 (0-2)
9+
10+
#
11+
# Definition of Atomic Species
12+
#
13+
14+
Species.Number 2
15+
<Definition.of.Atomic.Species
16+
H H6.0-s2p1 H_PBE19
17+
C C6.0-s2p2d1 C_PBE19
18+
Definition.of.Atomic.Species>
19+
20+
#
21+
# Atoms
22+
#
23+
24+
Atoms.Number 5
25+
Atoms.SpeciesAndCoordinates.Unit Ang # Ang|AU
26+
<Atoms.SpeciesAndCoordinates
27+
1 C 0.000000 0.000000 0.000000 2.0 2.0
28+
2 H -0.889981 -0.629312 0.000000 0.5 0.5
29+
3 H 0.000000 0.629312 -0.889981 0.5 0.5
30+
4 H 0.000000 0.629312 0.889981 0.5 0.5
31+
5 H 0.889981 -0.629312 0.000000 0.5 0.5
32+
Atoms.SpeciesAndCoordinates>
33+
Atoms.UnitVectors.Unit Ang # Ang|AU
34+
<Atoms.UnitVectors
35+
10.0 0.0 0.0
36+
0.0 10.0 0.0
37+
0.0 0.0 10.0
38+
Atoms.UnitVectors>
39+
40+
#
41+
# SCF or Electronic System
42+
#
43+
44+
scf.XcType GGA-PBE # LDA|LSDA-CA|LSDA-PW|GGA-PBE
45+
scf.SpinPolarization off # On|Off|NC
46+
scf.ElectronicTemperature 300.0 # default=300 (K)
47+
scf.energycutoff 120.0 # default=150 (Ry)
48+
scf.maxIter 100 # default=40
49+
scf.EigenvalueSolver cluster # DC|GDC|Cluster|Band
50+
scf.Kgrid 1 1 1 # means n1 x n2 x n3
51+
scf.Mixing.Type rmm-diis # Simple|Rmm-Diis|Gr-Pulay|Kerker|Rmm-Diisk
52+
scf.Init.Mixing.Weight 0.200 # default=0.30
53+
scf.Min.Mixing.Weight 0.001 # default=0.001
54+
scf.Max.Mixing.Weight 0.200 # default=0.40
55+
scf.Mixing.History 7 # default=5
56+
scf.Mixing.StartPulay 4 # default=6
57+
scf.criterion 1.0e-10 # default=1.0e-6 (Hartree)
58+
scf.lapack.dste dstevx # dstevx|dstedc|dstegr,default=dstevx
59+
60+
#
61+
# MD or Geometry Optimization
62+
#
63+
64+
MD.Type NVT_NH # Nomd|Opt|NVE|NVT_VS|NVT_NH
65+
MD.maxIter 200 # default=1
66+
MD.TimeStep 1.0 # default=0.5 (fs)
67+
NH.Mass.HeatBath 30.0 # default = 20.0
68+
69+
<MD.TempControl
70+
2
71+
1 300.0
72+
100 300.0
73+
MD.TempControl>

0 commit comments

Comments
 (0)