Skip to content

Commit 31e35e5

Browse files
authored
Merge devel into master (#385)
2 parents 2ac2f48 + 9936003 commit 31e35e5

File tree

24 files changed

+5629
-115
lines changed

24 files changed

+5629
-115
lines changed

.github/workflows/test.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@ jobs:
2222
- name: Install rdkit
2323
run: python -m pip install rdkit openbabel-wheel
2424
- name: Install dependencies
25-
run: python -m pip install .[amber,ase,pymatgen] coverage codecov
25+
run: python -m pip install .[amber,ase,pymatgen] coverage
2626
- name: Test
2727
run: cd tests && coverage run --source=../dpdata -m unittest && cd .. && coverage combine tests/.coverage && coverage report
2828
- name: Run codecov
29-
run: codecov
29+
uses: codecov/codecov-action@v3
30+
pass:
31+
needs: [build]
32+
runs-on: ubuntu-latest
33+
steps:
34+
- run: echo "All jobs passed"

README.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,11 +259,8 @@ If a valence of 3 is detected on carbon, the formal charge will be assigned to -
259259

260260
# Plugins
261261

262-
One can follow [a simple example](plugin_example/) to add their own format by creating and installing plugins. It's critical to add the [Format](dpdata/format.py) class to `entry_points['dpdata.plugins']` in `setup.py`:
263-
```py
264-
entry_points={
265-
'dpdata.plugins': [
266-
'random=dpdata_random:RandomFormat'
267-
]
268-
},
262+
One can follow [a simple example](plugin_example/) to add their own format by creating and installing plugins. It's critical to add the [Format](dpdata/format.py) class to `entry_points['dpdata.plugins']` in [`pyproject.toml`](plugin_example/pyproject.toml):
263+
```toml
264+
[project.entry-points.'dpdata.plugins']
265+
random = "dpdata_random:RandomFormat"
269266
```

dpdata/abacus/md.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import numpy as np
44
from .scf import ry2ev, bohr2ang, kbar2evperang3, get_block, get_geometry_in, get_cell, get_coords
55
import re
6+
import warnings
67

78
# Read in geometries from an ABACUS MD trajectory.
89
# The atomic coordinates are read in from generated files in OUT.XXXX.
@@ -80,6 +81,10 @@ def get_energy(outlines, ndump, dump_freq):
8081
if nenergy%dump_freq == 0:
8182
energy.append(float(line.split()[-2]))
8283
nenergy+=1
84+
elif "!! convergence has not been achieved" in line:
85+
if nenergy%dump_freq == 0:
86+
energy.append(np.nan)
87+
nenergy+=1
8388
assert(ndump == len(energy)), "Number of total energies in running_md.log = %d. Number of frames in MD_dump = %d. Please check."%(len(energy), ndump)
8489
energy = np.array(energy)
8590
return energy
@@ -113,6 +118,20 @@ def get_frame (fname):
113118
with open(os.path.join(path_out, "running_md.log"), 'r') as fp:
114119
outlines = fp.read().split('\n')
115120
energy = get_energy(outlines, ndump, dump_freq)
121+
122+
unconv_stru = ''
123+
for i,iene in enumerate(energy):
124+
if np.isnan(iene):
125+
coords = np.delete(coords,i-ndump,axis=0)
126+
cells = np.delete(cells,i-ndump,axis=0)
127+
force = np.delete(force,i-ndump,axis=0)
128+
stress = np.delete(stress,i-ndump,axis=0)
129+
energy = np.delete(energy,i-ndump,axis=0)
130+
unconv_stru += "%d " % i
131+
ndump = len(energy)
132+
if unconv_stru != '':
133+
warnings.warn(f"Structure %s are unconverged and not collected!" % unconv_stru)
134+
116135
for iframe in range(ndump):
117136
stress[iframe] *= np.linalg.det(cells[iframe, :, :].reshape([3, 3]))
118137
if np.sum(np.abs(stress[0])) < 1e-10:

dpdata/cli.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Command line interface for dpdata."""
22
import argparse
3+
from typing import Optional
34

45
from . import __version__
56
from .system import System, LabeledSystem, MultiSystems
@@ -47,11 +48,11 @@ def dpdata_cli():
4748
def convert(*,
4849
from_file: str,
4950
from_format: str = "auto",
50-
to_file: str = None,
51-
to_format: str = None,
51+
to_file: Optional[str] = None,
52+
to_format: Optional[str] = None,
5253
no_labeled: bool = False,
5354
multi: bool = False,
54-
type_map: list = None,
55+
type_map: Optional[list] = None,
5556
**kwargs):
5657
"""Convert files from one format to another one.
5758

dpdata/deepmd/hdf5.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Utils for deepmd/hdf5 format."""
2-
from typing import Union
2+
from typing import Optional, Union
33

44
import h5py
55
import numpy as np
@@ -11,7 +11,7 @@
1111

1212
def to_system_data(f: Union[h5py.File, h5py.Group],
1313
folder: str,
14-
type_map: list = None,
14+
type_map: Optional[list] = None,
1515
labels: bool = True) :
1616
"""Load a HDF5 file.
1717

dpdata/gaussian/gjf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# under LGPL 3.0 license
44
"""Generate Gaussian input file."""
55

6-
from typing import List, Tuple, Union
6+
from typing import Optional, List, Tuple, Union
77
import uuid
88
import itertools
99
import warnings
@@ -107,8 +107,8 @@ def make_gaussian_input(
107107
multiplicity: Union[str ,int] = "auto",
108108
charge: int = 0,
109109
fragment_guesses: bool = False,
110-
basis_set: str = None,
111-
keywords_high_multiplicity: str = None,
110+
basis_set: Optional[str] = None,
111+
keywords_high_multiplicity: Optional[str] = None,
112112
nproc: int = 1,
113113
) -> str:
114114
"""Make gaussian input file.

dpdata/lammps/dump.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ def get_atype(lines, type_idx_zero = False) :
3131
tidx = keys.index('type') - 2
3232
atype = []
3333
for ii in blk :
34-
atype.append([int(ii.split()[id_idx]), int(ii.split()[tidx])])
34+
atype.append([int(ii.split()[tidx]), int(ii.split()[id_idx])])
35+
# sort with type id
3536
atype.sort()
3637
atype = np.array(atype, dtype = int)
38+
atype = atype[:, ::-1]
3739
if type_idx_zero :
3840
return atype[:,1] - 1
3941
else :
@@ -76,16 +78,17 @@ def safe_get_posi(lines,cell,orig=np.zeros(3), unwrap=False) :
7678
assert coord_tp_and_sf is not None, 'Dump file does not contain atomic coordinates!'
7779
coordtype, sf, uw = coord_tp_and_sf
7880
id_idx = keys.index('id') - 2
81+
tidx = keys.index('type') - 2
7982
xidx = keys.index(coordtype[0])-2
8083
yidx = keys.index(coordtype[1])-2
8184
zidx = keys.index(coordtype[2])-2
8285
sel = (xidx, yidx, zidx)
8386
posis = []
8487
for ii in blk :
8588
words = ii.split()
86-
posis.append([float(words[id_idx]), float(words[xidx]), float(words[yidx]), float(words[zidx])])
89+
posis.append([float(words[tidx]), float(words[id_idx]), float(words[xidx]), float(words[yidx]), float(words[zidx])])
8790
posis.sort()
88-
posis = np.array(posis)[:,1:4]
91+
posis = np.array(posis)[:,2:5]
8992
if not sf:
9093
posis = (posis - orig) @ np.linalg.inv(cell) # Convert to scaled coordinates for unscaled coordinates
9194
if uw and unwrap:

dpdata/plugins/ase.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import TYPE_CHECKING, Type
1+
from typing import Optional, TYPE_CHECKING, Type
22
from dpdata.driver import Driver, Minimizer
33
from dpdata.format import Format
44
import numpy as np
@@ -93,7 +93,7 @@ def from_labeled_system(self, atoms: "ase.Atoms", **kwargs) -> dict:
9393
info_dict['virials'] = virials
9494
return info_dict
9595

96-
def from_multi_systems(self, file_name: str, begin: int=None, end: int=None, step: int=None, ase_fmt: str=None, **kwargs) -> "ase.Atoms":
96+
def from_multi_systems(self, file_name: str, begin: Optional[int] = None, end: Optional[int] = None, step: Optional[int] = None, ase_fmt: Optional[str] = None, **kwargs) -> "ase.Atoms":
9797
"""Convert a ASE supported file to ASE Atoms.
9898
9999
It will finally be converted to MultiSystems.
@@ -221,13 +221,16 @@ class ASEMinimizer(Minimizer):
221221
ase optimizer class
222222
fmax : float, optional, default=5e-3
223223
force convergence criterion
224+
max_steps : int, optional
225+
max steps to optimize
224226
optimizer_kwargs : dict, optional
225227
other parameters for optimizer
226228
"""
227229
def __init__(self,
228230
driver: Driver,
229-
optimizer: Type["Optimizer"] = None,
231+
optimizer: Optional[Type["Optimizer"]] = None,
230232
fmax: float = 5e-3,
233+
max_steps: Optional[int] = None,
231234
optimizer_kwargs: dict = {}) -> None:
232235
self.calculator = driver.ase_calculator
233236
if optimizer is None:
@@ -240,6 +243,7 @@ def __init__(self,
240243
**optimizer_kwargs.copy(),
241244
}
242245
self.fmax = fmax
246+
self.max_steps = max_steps
243247

244248
def minimize(self, data: dict) -> dict:
245249
"""Minimize the geometry.
@@ -261,7 +265,7 @@ def minimize(self, data: dict) -> dict:
261265
for atoms in structures:
262266
atoms.calc = self.calculator
263267
dyn = self.optimizer(atoms, **self.optimizer_kwargs)
264-
dyn.run(fmax=self.fmax)
268+
dyn.run(fmax=self.fmax, steps=self.max_steps)
265269
ls = dpdata.LabeledSystem(atoms, fmt="ase/structure", type_map=data['atom_names'])
266270
labeled_system.append(ls)
267-
return labeled_system.data
271+
return labeled_system.data

dpdata/plugins/deepmd.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Union, List
1+
from typing import Optional, Union, List
22

33
import dpdata
44
import dpdata.deepmd.raw
@@ -108,7 +108,7 @@ def _from_system(self, file_name: Union[str, h5py.Group, h5py.File], type_map: L
108108

109109
def from_system(self,
110110
file_name: Union[str, h5py.Group, h5py.File],
111-
type_map: List[str]=None,
111+
type_map: Optional[List[str]] = None,
112112
**kwargs) -> dict:
113113
"""Convert HDF5 file to System data.
114114
@@ -134,7 +134,7 @@ def from_system(self,
134134

135135
def from_labeled_system(self,
136136
file_name: Union[str, h5py.Group, h5py.File],
137-
type_map: List[str]=None,
137+
type_map: Optional[List[str]] = None,
138138
**kwargs) -> dict:
139139
"""Convert HDF5 file to LabeledSystem data.
140140

dpdata/system.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,11 @@ def perturb(self,
810810
perturbed_system : System
811811
The perturbed_system. It contains `pert_num` * frame_num of the input system frames.
812812
"""
813+
if type(self) is not dpdata.System:
814+
raise RuntimeError(
815+
f'Using method perturb() of an instance of {type(self)}. '
816+
f'Must use method perturb() of the instance of class dpdata.System.'
817+
)
813818
perturbed_system = System()
814819
nframes = self.get_nframes()
815820
for ii in range(nframes):
@@ -1125,11 +1130,6 @@ def affine_map_fv(self, trans, f_idx) :
11251130
if self.has_virial():
11261131
self.data['virials'][f_idx] = np.matmul(trans.T, np.matmul(self.data['virials'][f_idx], trans))
11271132

1128-
@post_funcs.register("rot_lower_triangular")
1129-
def rot_lower_triangular(self) :
1130-
for ii in range(self.get_nframes()) :
1131-
self.rot_frame_lower_triangular(ii)
1132-
11331133
def rot_frame_lower_triangular(self, f_idx = 0) :
11341134
trans = System.rot_frame_lower_triangular(self, f_idx = f_idx)
11351135
self.affine_map_fv(trans, f_idx = f_idx)

0 commit comments

Comments
 (0)