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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,20 @@ Frame selection can be implemented by
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
perturbed_system = dpdata.System('./POSCAR').perturb(pert_num=3,
cell_pert_fraction=0.05,
atom_pert_distance=0.6,
atom_pert_style='normal')
print(perturbed_system.data)
```
136 changes: 136 additions & 0 deletions dpdata/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,142 @@ def add_atom_names(self, atom_names):
self.data['atom_names'].extend(atom_names)
self.data['atom_numbs'].extend([0 for _ in atom_names])

def replicate(self, ncopy):
"""
Replicate the each frame in the system in 3 dimensions.
Each frame in the system will become a supercell.

Parameters
----------
ncopy :
list: [4,2,3]
or tuple: (4,2,3,)
make `ncopy[0]` copys in x dimensions,
make `ncopy[1]` copys in y dimensions,
make `ncopy[2]` copys in z dimensions.

Returns
-------
tmp : System
The system after replication.
"""
if len(ncopy) !=3:
raise RuntimeError('ncopy must be a list or tuple with 3 int')
for ii in ncopy:
if type(ii) is not int:
raise RuntimeError('ncopy must be a list or tuple must with 3 int')

tmp = System()
nframes = self.get_nframes()
data = self.data
tmp.data['atom_names'] = list(np.copy(data['atom_names']))
tmp.data['atom_numbs'] = list(np.array(np.copy(data['atom_numbs'])) * np.prod(ncopy))
tmp.data['atom_types'] = np.sort(np.tile(np.copy(data['atom_types']),np.prod(ncopy)))
tmp.data['cells'] = np.copy(data['cells'])
for ii in range(3):
tmp.data['cells'][:,ii,:] *= ncopy[ii]
tmp.data['coords'] = np.tile(np.copy(data['coords']),tuple(ncopy)+(1,1,1))

for xx in range(ncopy[0]):
for yy in range(ncopy[1]):
for zz in range(ncopy[2]):
tmp.data['coords'][xx,yy,zz,:,:,:] += xx * np.reshape(data['cells'][:,0,:], [-1,1,3])\
+ yy * np.reshape(data['cells'][:,1,:], [-1,1,3])\
+ zz * np.reshape(data['cells'][:,2,:], [-1,1,3])
tmp.data['coords'] = np.reshape(np.transpose(tmp.data['coords'], [3,4,0,1,2,5]), (nframes, -1 , 3))
return tmp

def perturb(self,
pert_num,
cell_pert_fraction,
atom_pert_distance,
atom_pert_style='normal'):
"""
Perturb each frame in the system randomly.
The cell will be deformed randomly, and atoms will be displaced by a random distance in random direction.

Parameters
----------
pert_num : int
Each frame in the system will make `pert_num` copies,
and all the copies will be perturbed.
That means the system to be returned will contain `pert_num` * frame_num of the input system.
cell_pert_fraction : float
A fraction determines how much (relatively) will cell deform.
The cell of each frame is deformed by a symmetric matrix perturbed from identity.
The perturbation to the diagonal part is subject to a uniform distribution in [-cell_pert_fraction, cell_pert_fraction),
and the perturbation to the off-diagonal part is subject to a uniform distribution in [-0.5*cell_pert_fraction, 0.5*cell_pert_fraction).
atom_pert_distance: float
unit: Angstrom. A distance determines how far atoms will move.
Atoms will move about `atom_pert_distance` in random direction.
The distribution of the distance atoms move is determined by atom_pert_style
atom_pert_style : str
Determines the distribution of the distance atoms move is subject to.
Avaliable options are
- `'normal'`: the `distance` will be object to `chi-square distribution with 3 degrees of freedom` after normalization.
The mean value of the distance is `atom_pert_fraction*side_length`
- `'uniform'`: will generate uniformly random points in a 3D-balls with radius as `atom_pert_distance`.
These points are treated as vector used by atoms to move.
Obviously, the max length of the distance atoms move is `atom_pert_distance`.
- `'const'`: The distance atoms move will be a constant `atom_pert_distance`.

Returns
-------
perturbed_system : System
The perturbed_system. It contains `pert_num` * frame_num of the input system frames.
"""
perturbed_system = System()
nframes = self.get_nframes()
for ii in range(nframes):
for jj in range(pert_num):
tmp_system = self[ii].copy()
cell_perturb_matrix = get_cell_perturb_matrix(cell_pert_fraction)
tmp_system.data['cells'][0] = np.matmul(tmp_system.data['cells'][0],cell_perturb_matrix)
tmp_system.data['coords'][0] = np.matmul(tmp_system.data['coords'][0],cell_perturb_matrix)
for kk in range(len(tmp_system.data['coords'][0])):
atom_perturb_vector = get_atom_perturb_vector(atom_pert_distance, atom_pert_style)
tmp_system.data['coords'][0][kk] += atom_perturb_vector
tmp_system.rot_lower_triangular()
perturbed_system.append(tmp_system)
return perturbed_system

def get_cell_perturb_matrix(cell_pert_fraction):
if cell_pert_fraction<0:
raise RuntimeError('cell_pert_fraction can not be negative')
e0 = np.random.rand(6)
e = e0 * 2 *cell_pert_fraction - cell_pert_fraction
cell_pert_matrix = np.array(
[[1+e[0], 0.5 * e[5], 0.5 * e[4]],
[0.5 * e[5], 1+e[1], 0.5 * e[3]],
[0.5 * e[4], 0.5 * e[3], 1+e[2]]]
)
return cell_pert_matrix

def get_atom_perturb_vector(atom_pert_distance, atom_pert_style='normal'):
random_vector = None
if atom_pert_distance < 0:
raise RuntimeError('atom_pert_distance can not be negative')

if atom_pert_style == 'normal':
e = np.random.randn(3)
random_vector=(atom_pert_distance/np.sqrt(3))*e
elif atom_pert_style == 'uniform':
e = np.random.randn(3)
while np.linalg.norm(e) < 0.1:
e = np.random.randn(3)
random_unit_vector = e/np.linalg.norm(e)
v0 = np.random.rand(1)
v = np.power(v0,1/3)
random_vector = atom_pert_distance*v*random_unit_vector
elif atom_pert_style == 'const' :
e = np.random.randn(3)
while np.linalg.norm(e) < 0.1:
e = np.random.randn(3)
random_unit_vector = e/np.linalg.norm(e)
random_vector = atom_pert_distance*random_unit_vector
else:
raise RuntimeError('unsupported options atom_pert_style={}'.format(atom_pert_style))
return random_vector

class LabeledSystem (System):
'''
Expand Down
16 changes: 16 additions & 0 deletions tests/poscars/POSCAR.SiC
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
C4 Si4
1.0
4.1454462863815970e+00 0.0000000000000000e+00 0.0000000000000000e+00
1.3000000000000000e-01 3.9594462863815970e+00 0.0000000000000000e+00
2.5000000000000000e-01 3.7000000000000000e-01 4.0400062863815970e+00
C Si
4 4
cartesian
-0.0666948568 0.0604660432 2.1539831432
1.9907431432 -0.0864349568 0.0663397432
0.0885598432 2.0783031432 0.0622547432
2.0324731432 2.0217031432 2.0253831432
-0.0448649568 0.1153571432 0.0540263432
1.9664731432 1.9313831432 -0.1405848568
2.0807731432 0.0065058032 1.9956031432
0.0632185432 1.9999431432 2.0438931432
16 changes: 16 additions & 0 deletions tests/poscars/POSCAR.SiC.const
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
C4 Si4
1.0
3.9448633066729739e+00 -3.6344794672422329e-18 1.1581293029516294e-17
1.6817409381958889e-01 4.0320777239133783e+00 -8.7954588948930866e-19
1.4551929935812052e-01 3.9989012843738053e-01 3.9977352939318109e+00
C Si
4 4
Cartesian
0.0946327782 -0.2781320996 1.6927633385
2.1395921916 -0.5505295607 0.3561009428
-0.2623111485 2.0403483142 0.5289485573
2.0291102621 2.0166734366 1.4189102698
-0.4274609464 0.4275845699 -0.2870878166
1.8398859643 1.9175800522 -0.7344827910
1.5794721062 0.2698516856 1.5600233361
0.2272461445 2.4170250626 2.4545090907
16 changes: 16 additions & 0 deletions tests/poscars/POSCAR.SiC.normal
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
C4 Si4
1.0
4.0354487481064565e+00 1.1027270790560616e-17 2.5642993008475204e-17
2.0693526054669642e-01 4.1066892997402196e+00 -8.6715682899078028e-18
4.2891472979598610e-01 5.5796885749827474e-01 4.1100061517204542e+00
C Si
4 4
Cartesian
0.2840021179 -0.6003817253 2.7192043932
1.7870636884 0.4043686026 -0.3468222936
-0.4647946470 2.0243215781 -0.0624256251
2.1747504767 2.0704389063 2.4228997681
-0.3817468326 0.0611851697 0.1116535817
2.1483270977 2.3528212071 -0.3719335435
2.4540854549 0.7297685673 1.8434611305
0.1075358778 2.0300985762 2.0687710181
56 changes: 56 additions & 0 deletions tests/poscars/POSCAR.SiC.replicate123
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
C24 Si24
1.000000
4.14544629 0.00000000 0.00000000
0.26000000 7.91889257 0.00000000
0.75000000 1.11000000 12.12001886
C Si
24 24
Cartesian
-0.06669486 0.06046604 2.15398314
0.18330514 0.43046604 6.19398943
0.43330514 0.80046604 10.23399572
0.06330514 4.01991233 2.15398314
0.31330514 4.38991233 6.19398943
0.56330514 4.75991233 10.23399572
1.99074314 -0.08643496 0.06633974
2.24074314 0.28356504 4.10634603
2.49074314 0.65356504 8.14635232
2.12074314 3.87301133 0.06633974
2.37074314 4.24301133 4.10634603
2.62074314 4.61301133 8.14635232
0.08855984 2.07830314 0.06225474
0.33855984 2.44830314 4.10226103
0.58855984 2.81830314 8.14226732
0.21855984 6.03774943 0.06225474
0.46855984 6.40774943 4.10226103
0.71855984 6.77774943 8.14226732
2.03247314 2.02170314 2.02538314
2.28247314 2.39170314 6.06538943
2.53247314 2.76170314 10.10539572
2.16247314 5.98114943 2.02538314
2.41247314 6.35114943 6.06538943
2.66247314 6.72114943 10.10539572
-0.04486496 0.11535714 0.05402634
0.20513504 0.48535714 4.09403263
0.45513504 0.85535714 8.13403892
0.08513504 4.07480343 0.05402634
0.33513504 4.44480343 4.09403263
0.58513504 4.81480343 8.13403892
1.96647314 1.93138314 -0.14058486
2.21647314 2.30138314 3.89942143
2.46647314 2.67138314 7.93942772
2.09647314 5.89082943 -0.14058486
2.34647314 6.26082943 3.89942143
2.59647314 6.63082943 7.93942772
2.08077314 0.00650580 1.99560314
2.33077314 0.37650580 6.03560943
2.58077314 0.74650580 10.07561572
2.21077314 3.96595209 1.99560314
2.46077314 4.33595209 6.03560943
2.71077314 4.70595209 10.07561572
0.06321854 1.99994314 2.04389314
0.31321854 2.36994314 6.08389943
0.56321854 2.73994314 10.12390572
0.19321854 5.95938943 2.04389314
0.44321854 6.32938943 6.08389943
0.69321854 6.69938943 10.12390572
16 changes: 16 additions & 0 deletions tests/poscars/POSCAR.SiC.uniform
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
C4 Si4
1.0
4.0817852422279959e+00 -8.0334347485565818e-20 1.4195449766884313e-17
1.2315711101650186e-01 3.7860044730134366e+00 -1.7522489439993958e-18
4.0639226354941010e-01 3.2444019947671882e-01 4.2124083393682454e+00
C Si
4 4
Cartesian
-0.1022885809 0.5553879154 2.3401729917
1.4574918226 -0.0391762715 0.0190932943
-0.0904993945 1.7684440711 -0.1710987880
2.0638159391 2.1681985074 2.4580083474
-0.3261354126 0.1759255681 0.2236316249
2.0738703301 2.3024191125 -0.5031567813
2.3488610334 0.3825072268 1.7330866249
-0.0534780340 1.5938442575 1.8486892947
Loading