Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 30 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,34 @@ The labels provided in the `OUTCAR`, i.e. energies, forces and virials (if any),

The `System` or `LabeledSystem` can be constructed from the following file formats with the `format key` in the table passed to argument `fmt`:

| Software| format | multi frames | labeled | class | format key |
| ------- | :--- | :---: | :---: | :--- | :--- |
| vasp | poscar | False | False | System | 'vasp/poscar' |
| vasp | outcar | True | True | LabeledSystem | 'vasp/outcar' |
| vasp | xml | True | True | LabeledSystem | 'vasp/xml' |
| lammps | lmp | False | False | System | 'lammps/lmp' |
| lammps | dump | True | False | System | 'lammps/dump' |
| deepmd | raw | True | False | System | 'deepmd/raw' |
| deepmd | npy | True | False | System | 'deepmd/npy' |
| deepmd | raw | True | True | LabeledSystem | 'deepmd/raw' |
| deepmd | npy | True | True | LabeledSystem | 'deepmd/npy' |
| gaussian| log | False | True | LabeledSystem | 'gaussian/log'|
| gaussian| log | True | True | LabeledSystem | 'gaussian/md' |
| siesta | output | False | True | LabeledSystem | 'siesta/output'|
| siesta | aimd_output | True | True | LabeledSystem | 'siesta/aimd_output' |
| cp2k | output | False | True | LabeledSystem | 'cp2k/output' |
| cp2k | aimd_output | True | True | LabeledSystem | 'cp2k/aimd_output' |
| QE | log | False | True | LabeledSystem | 'qe/pw/scf' |
| QE | log | True | False | System | 'qe/cp/traj' |
| QE | log | True | True | LabeledSystem | 'qe/cp/traj' |
|quip/gap|xyz|True|True|MultiSystems|'quip/gap/xyz'|
| PWmat | atom.config | False | False | System | 'pwmat/atom.config' |
| PWmat | movement | True | True | LabeledSystem | 'pwmat/movement' |
| PWmat | OUT.MLMD | True | True | LabeledSystem | 'pwmat/out.mlmd' |
| Amber | multi | True | True | LabeledSystem | 'amber/md' |
| Gromacs | gro | False | False | System | 'gromacs/gro' |


The Class `dpdata.MultiSystems` can read data from a dir which may contains many files of different systems, or from single xyz file which contains different systems.

Use `dpdata.MultiSystems.from_dir` to read from a directory, `dpdata.MultiSystems` will walk in the directory
Expand Down Expand Up @@ -82,35 +110,8 @@ xyz_multi_systems.systems['B1C9'].to_deepmd_raw('./my_work_dir/B1C9_raw')

# dump all systems
xyz_multi_systems.to_deepmd_raw('./my_deepmd_data/')


```

| Software| format | multi frames | labeled | class | format key |
| ------- | :--- | :---: | :---: | :--- | :--- |
| vasp | poscar | False | False | System | 'vasp/poscar' |
| vasp | outcar | True | True | LabeledSystem | 'vasp/outcar' |
| vasp | xml | True | True | LabeledSystem | 'vasp/xml' |
| lammps | lmp | False | False | System | 'lammps/lmp' |
| lammps | dump | True | False | System | 'lammps/dump' |
| deepmd | raw | True | False | System | 'deepmd/raw' |
| deepmd | npy | True | False | System | 'deepmd/npy' |
| deepmd | raw | True | True | LabeledSystem | 'deepmd/raw' |
| deepmd | npy | True | True | LabeledSystem | 'deepmd/npy' |
| gaussian| log | False | True | LabeledSystem | 'gaussian/log'|
| gaussian| log | True | True | LabeledSystem | 'gaussian/md' |
| siesta | output | False | True | LabeledSystem | 'siesta/output'|
| siesta | aimd_output | True | True | LabeledSystem | 'siesta/aimd_output' |
| cp2k | output | False | True | LabeledSystem | 'cp2k/output' |
| cp2k | aimd_output | True | True | LabeledSystem | 'cp2k/aimd_output' |
| QE | log | False | True | LabeledSystem | 'qe/pw/scf' |
| QE | log | True | False | System | 'qe/cp/traj' |
| QE | log | True | True | LabeledSystem | 'qe/cp/traj' |
|quip/gap|xyz|True|True|MultiSystems|'quip/gap/xyz'|
| PWmat | atom.config | False | False | System | 'pwmat/atom.config' |
| PWmat | movement | True | True | LabeledSystem | 'pwmat/movement' |
| PWmat | OUT.MLMD | True | True | LabeledSystem | 'pwmat/out.mlmd' |
| Amber | multi | True | True | LabeledSystem | 'amber/md' |
## Access data
These properties stored in `System` and `LabeledSystem` can be accessed by operator `[]` with the key of the property supplied, for example
```python
Expand All @@ -130,7 +131,6 @@ Available properties are (nframe: number of frames in the system, natoms: total
| 'virials' | np.ndarray | nframes x 3 x 3 | True | The virial tensor of each frame



## Dump data
The data stored in `System` or `LabeledSystem` can be dumped in 'lammps/lmp' or 'vasp/poscar' format, for example:
```python
Expand All @@ -142,7 +142,6 @@ d_outcar.to('vasp/poscar', 'POSCAR', frame_idx=-1)
```
The last frames of `d_outcar` will be dumped to 'POSCAR'.


The data stored in `LabeledSystem` can be dumped to deepmd-kit raw format, for example
```python
d_outcar.to('deepmd/raw', 'dpmd_raw')
Expand All @@ -157,13 +156,15 @@ dpdata.LabeledSystem('OUTCAR').sub_system([0,-1]).to('deepmd/raw', 'dpmd_raw')
```
by which only the first and last frames are dumped to `dpmd_raw`.


## replicate
dpdata will create a super cell of the current atom configuration.
```python
dpdata.System('./POSCAR').replicate((1,2,3,) )
```
tuple(1,2,3) means don't copy atom configuration in x direction, make 2 copys in y direction, make 3 copys in z direction.


## perturb
By the following example, each frame of the original system (`dpdata.System('./POSCAR')`) is perturbed to generate three new frames. For each frame, the cell is perturbed by 5% and the atom positions are perturbed by 0.6 Angstrom. `atom_pert_style` indicates that the perturbation to the atom positions is subject to normal distribution. Other available options to `atom_pert_style` are`uniform` (uniform in a ball), and `const` (uniform on a sphere).
```python
Expand Down
Empty file added dpdata/gromacs/__init__.py
Empty file.
55 changes: 55 additions & 0 deletions dpdata/gromacs/gro.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3

import numpy as np

nm2ang = 10.

def _get_line(line):
atom_name = line[10:15].split()[0]
atom_idx = int(line[15:20].split()[0])
posis = [float(line[ii:ii+8]) for ii in range(20,44,8)]
posis = np.array(posis) * nm2ang
return atom_name, atom_idx, posis

def _get_cell(line):
cell = np.zeros([3,3])
lengths = [float(ii) for ii in line.split()]
if len(lengths) >= 3:
for dd in range(3):
cell[dd][dd] = lengths[dd]
else:
raise RuntimeError('wrong box format: ', line)
if len(lengths) == 9:
cell[0][1] = lengths[3]
cell[0][2] = lengths[4]
cell[1][0] = lengths[5]
cell[1][2] = lengths[6]
cell[2][0] = lengths[7]
cell[2][1] = lengths[8]
cell = cell * nm2ang
return cell

def file_to_system_data(fname):
names = []
idxs = []
posis = []
with open(fname) as fp:
fp.readline()
natoms = int(fp.readline())
for ii in range(natoms):
n, i, p = _get_line(fp.readline())
names.append(n)
idxs.append(i)
posis.append(p)
cell = _get_cell(fp.readline())
posis = np.array(posis)
system = {}
system['orig'] = np.array([0, 0, 0])
system['atom_names'] = list(set(names))
system['atom_names'].sort()
system['atom_numbs'] = [names.count(ii) for ii in system['atom_names']]
system['atom_types'] = [system['atom_names'].index(ii) for ii in names]
system['atom_types'] = np.array(system['atom_types'], dtype = int)
system['coords'] = np.array([posis])
system['cells'] = np.array([cell])
return system
14 changes: 14 additions & 0 deletions dpdata/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import dpdata.pwmat.movement
import dpdata.pwmat.atomconfig
import dpdata.fhi_aims.output
import dpdata.gromacs.gro
from copy import deepcopy
from monty.json import MSONable
from monty.serialization import loadfn,dumpfn
Expand Down Expand Up @@ -607,6 +608,19 @@ def from_deepmd_raw(self, folder, type_map = None) :
if tmp_data is not None :
self.data = tmp_data

@register_from_funcs.register_funcs("gro")
@register_from_funcs.register_funcs("gromacs/gro")
def from_gromacs_gro(self, file_name) :
"""
Load gromacs .gro file

Parameters
----------
file_name : str
The input file name
"""
self.data = dpdata.gromacs.gro.file_to_system_data(file_name)

@register_to_funcs.register_funcs("deepmd/npy")
def to_deepmd_npy(self, folder, set_size = 5000, prec=np.float32) :
"""
Expand Down
12 changes: 12 additions & 0 deletions tests/gromacs/1h.gro
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

9
1SOL O 1 0.135 0.183 0.341
1SOL H 2 0.177 0.149 0.262
1SOL H 3 0.046 0.149 0.339
2SOL O 4 0.520 0.447 0.111
2SOL H 5 0.567 0.481 0.035
2SOL H 6 0.568 0.481 0.186
3SOL O 7 0.651 0.539 0.335
3SOL H 8 0.653 0.634 0.336
3SOL H 9 0.743 0.512 0.336
0.7822838765564372 0.7353572647182051 0.9036518515423753
12 changes: 12 additions & 0 deletions tests/gromacs/1h.tri.gro
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

9
1SOL O 1 0.135 0.183 0.341
1SOL H 2 0.177 0.149 0.262
1SOL H 3 0.046 0.149 0.339
2SOL O 4 0.520 0.447 0.111
2SOL H 5 0.567 0.481 0.035
2SOL H 6 0.568 0.481 0.186
3SOL O 7 0.651 0.539 0.335
3SOL H 8 0.653 0.634 0.336
3SOL H 9 0.743 0.512 0.336
0.7822838765564372 0.7353572647182051 0.9036518515423753 0.0 0.1 0.2 0.3 0.4 0.5
46 changes: 46 additions & 0 deletions tests/test_gromacs_gro.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import os
import numpy as np
import unittest
from context import dpdata

class TestGromacsGro(unittest.TestCase):
def test_read_file(self):
system = dpdata.System('gromacs/1h.gro')
self.assertEqual(system['atom_names'], ['H', 'O'])
self.assertEqual(system['atom_numbs'], [6, 3])
for cc,ii in enumerate([1, 0, 0, 1, 0, 0, 1, 0, 0]):
self.assertEqual(system['atom_types'][cc], ii)
self.assertEqual(len(system['cells']), 1)
self.assertEqual(len(system['coords']), 1)
for ii in range(3):
for jj in range(3):
if ii != jj:
self.assertAlmostEqual(system['cells'][0][ii][jj], 0)
self.assertAlmostEqual(system['cells'][0][0][0], 7.822838765564372)
self.assertAlmostEqual(system['cells'][0][1][1], 7.353572647182051)
self.assertAlmostEqual(system['cells'][0][2][2], 9.036518515423753)
self.assertAlmostEqual(system['coords'][0][8][0], 7.43)
self.assertAlmostEqual(system['coords'][0][8][1], 5.12)
self.assertAlmostEqual(system['coords'][0][8][2], 3.36)

def test_read_file_tri(self):
system = dpdata.System('gromacs/1h.tri.gro')
self.assertEqual(system['atom_names'], ['H', 'O'])
self.assertEqual(system['atom_numbs'], [6, 3])
for cc,ii in enumerate([1, 0, 0, 1, 0, 0, 1, 0, 0]):
self.assertEqual(system['atom_types'][cc], ii)
self.assertEqual(len(system['cells']), 1)
self.assertEqual(len(system['coords']), 1)
count = 0
for ii in range(3):
for jj in range(3):
if ii != jj:
self.assertAlmostEqual(system['cells'][0][ii][jj], count)
count += 1
self.assertAlmostEqual(system['cells'][0][0][0], 7.822838765564372)
self.assertAlmostEqual(system['cells'][0][1][1], 7.353572647182051)
self.assertAlmostEqual(system['cells'][0][2][2], 9.036518515423753)
self.assertAlmostEqual(system['coords'][0][8][0], 7.43)
self.assertAlmostEqual(system['coords'][0][8][1], 5.12)
self.assertAlmostEqual(system['coords'][0][8][2], 3.36)
system.to('vasp/poscar', 'POSCAR')