From 5e6da87abaa96c1a250250f98efebd0df13657f3 Mon Sep 17 00:00:00 2001 From: Yuan Fengbo Date: Fri, 27 Nov 2020 20:28:32 +0800 Subject: [PATCH 1/2] add the replace method to system, using for randomly substitute atom of specific type to anothor type --- dpdata/system.py | 34 +++++++++ tests/poscars/POSCAR.P42nmc | 104 ++++++++++++++++++++++++++++ tests/poscars/POSCAR.P42nmc.replace | 104 ++++++++++++++++++++++++++++ tests/test_replace.py | 40 +++++++++++ 4 files changed, 282 insertions(+) create mode 100644 tests/poscars/POSCAR.P42nmc create mode 100644 tests/poscars/POSCAR.P42nmc.replace create mode 100644 tests/test_replace.py diff --git a/dpdata/system.py b/dpdata/system.py index d2be7f879..bba7446f0 100644 --- a/dpdata/system.py +++ b/dpdata/system.py @@ -799,6 +799,40 @@ def replicate(self, ncopy): tmp.data['coords'] = np.reshape(np.transpose(tmp.data['coords'], [3,4,0,1,2,5]), (nframes, -1 , 3)) return tmp + def replace(self, initial_atom_type, end_atom_type, replace_num): + if type(self) is not dpdata.System: + raise RuntimeError('Must use method replace() of the instance of class dpdata.System') + if type(replace_num) is not int: + raise ValueError("replace_num must be a integer. Now is {replace_num}".format(replace_num=replace_num)) + if replace_num <= 0: + raise ValueError("replace_num must be larger than 0.Now is {replace_num}".format(replace_num=replace_num)) + + try: + initial_atom_index = self.data['atom_names'].index(initial_atom_type) + except ValueError as e: + raise ValueError("atom_type {initial_atom_type} not in {atom_names}" + .format(initial_atom_type=initial_atom_type, atom_names=self.data['atom_names'])) + max_replace_num = self.data['atom_numbs'][initial_atom_index] + + if replace_num > max_replace_num: + raise RuntimeError("not enough {initial_atom_type} atom, only {max_replace_num} available, less than {replace_num}.Please check." + .format(initial_atom_type=initial_atom_type,max_replace_num=max_replace_num, replace_num=replace_num)) + + may_replace_indices = [i for i, x in enumerate(self.data['atom_types']) if x == initial_atom_index] + to_replace_indices = np.random.choice(may_replace_indices, size=replace_num, replace=False) + + if end_atom_type not in self.data['atom_names']: + self.data['atom_names'].append(end_atom_type) + self.data['atom_numbs'].append(0) + + end_atom_index = self.data['atom_names'].index(end_atom_type) + for ii in to_replace_indices: + self.data['atom_types'][ii] = end_atom_index + self.data['atom_numbs'][initial_atom_index] -= replace_num + self.data['atom_numbs'][end_atom_index] += replace_num + self.sort_atom_types() + + def perturb(self, pert_num, cell_pert_fraction, diff --git a/tests/poscars/POSCAR.P42nmc b/tests/poscars/POSCAR.P42nmc new file mode 100644 index 000000000..130daa127 --- /dev/null +++ b/tests/poscars/POSCAR.P42nmc @@ -0,0 +1,104 @@ +Hf32 O64 +1.0 +10.001280 0.000000 0.000000 +0.000000 10.001280 0.000000 +0.000000 0.000000 10.163840 +Hf O +32 64 +direct +0.000000 0.000000 0.000000 Hf +0.000000 0.000000 0.500000 Hf +0.000000 0.500000 1.000000 Hf +0.000000 0.500000 0.500000 Hf +0.500000 0.000000 1.000000 Hf +0.500000 0.000000 0.500000 Hf +0.500000 0.500000 1.000000 Hf +0.500000 0.500000 0.500000 Hf +0.250000 0.000000 0.250000 Hf +0.250000 0.000000 0.750000 Hf +0.250000 0.500000 0.250000 Hf +0.250000 0.500000 0.750000 Hf +0.750000 0.000000 0.250000 Hf +0.750000 0.000000 0.750000 Hf +0.750000 0.500000 0.250000 Hf +0.750000 0.500000 0.750000 Hf +0.000000 0.250000 0.250000 Hf +0.000000 0.250000 0.750000 Hf +1.000000 0.750000 0.250000 Hf +1.000000 0.750000 0.750000 Hf +0.500000 0.250000 0.250000 Hf +0.500000 0.250000 0.750000 Hf +0.500000 0.750000 0.250000 Hf +0.500000 0.750000 0.750000 Hf +0.250000 0.250000 1.000000 Hf +0.250000 0.250000 0.500000 Hf +0.250000 0.750000 1.000000 Hf +0.250000 0.750000 0.500000 Hf +0.750000 0.250000 1.000000 Hf +0.750000 0.250000 0.500000 Hf +0.750000 0.750000 0.000000 Hf +0.750000 0.750000 0.500000 Hf +0.375000 0.375000 0.146120 O +0.375000 0.375000 0.646120 O +0.375000 0.875000 0.146120 O +0.375000 0.875000 0.646120 O +0.875000 0.375000 0.146120 O +0.875000 0.375000 0.646120 O +0.875000 0.875000 0.146120 O +0.875000 0.875000 0.646120 O +0.375000 0.375000 0.396120 O +0.375000 0.375000 0.896120 O +0.375000 0.875000 0.396120 O +0.375000 0.875000 0.896120 O +0.875000 0.375000 0.396120 O +0.875000 0.375000 0.896120 O +0.875000 0.875000 0.396120 O +0.875000 0.875000 0.896120 O +0.375000 0.125000 0.103880 O +0.375000 0.125000 0.603880 O +0.375000 0.625000 0.103880 O +0.375000 0.625000 0.603880 O +0.875000 0.125000 0.103880 O +0.875000 0.125000 0.603880 O +0.875000 0.625000 0.103880 O +0.875000 0.625000 0.603880 O +0.375000 0.125000 0.353880 O +0.375000 0.125000 0.853880 O +0.375000 0.625000 0.353880 O +0.375000 0.625000 0.853880 O +0.875000 0.125000 0.353880 O +0.875000 0.125000 0.853880 O +0.875000 0.625000 0.353880 O +0.875000 0.625000 0.853880 O +0.125000 0.375000 0.103880 O +0.125000 0.375000 0.603880 O +0.125000 0.875000 0.103880 O +0.125000 0.875000 0.603880 O +0.625000 0.375000 0.103880 O +0.625000 0.375000 0.603880 O +0.625000 0.875000 0.103880 O +0.625000 0.875000 0.603880 O +0.125000 0.375000 0.353880 O +0.125000 0.375000 0.853880 O +0.125000 0.875000 0.353880 O +0.125000 0.875000 0.853880 O +0.625000 0.375000 0.353880 O +0.625000 0.375000 0.853880 O +0.625000 0.875000 0.353880 O +0.625000 0.875000 0.853880 O +0.125000 0.125000 0.146120 O +0.125000 0.125000 0.646120 O +0.125000 0.625000 0.146120 O +0.125000 0.625000 0.646120 O +0.625000 0.125000 0.146120 O +0.625000 0.125000 0.646120 O +0.625000 0.625000 0.146120 O +0.625000 0.625000 0.646120 O +0.125000 0.125000 0.396120 O +0.125000 0.125000 0.896120 O +0.125000 0.625000 0.396120 O +0.125000 0.625000 0.896120 O +0.625000 0.125000 0.396120 O +0.625000 0.125000 0.896120 O +0.625000 0.625000 0.396120 O +0.625000 0.625000 0.896120 O diff --git a/tests/poscars/POSCAR.P42nmc.replace b/tests/poscars/POSCAR.P42nmc.replace new file mode 100644 index 000000000..e785d1286 --- /dev/null +++ b/tests/poscars/POSCAR.P42nmc.replace @@ -0,0 +1,104 @@ +Hf24 O64 Zr8 +1.0 +1.0001280000000000e+01 0.0000000000000000e+00 0.0000000000000000e+00 +0.0000000000000000e+00 1.0001280000000000e+01 0.0000000000000000e+00 +0.0000000000000000e+00 0.0000000000000000e+00 1.0163840000000000e+01 +Hf O Zr +24 64 8 +Cartesian + 0.0000000000 0.0000000000 0.0000000000 + 7.5009600000 7.5009600000 5.0819200000 + 7.5009600000 7.5009600000 0.0000000000 + 7.5009600000 2.5003200000 10.1638400000 + 2.5003200000 7.5009600000 5.0819200000 + 2.5003200000 7.5009600000 10.1638400000 + 2.5003200000 2.5003200000 5.0819200000 + 2.5003200000 2.5003200000 10.1638400000 + 5.0006400000 2.5003200000 7.6228800000 + 10.0012800000 7.5009600000 2.5409600000 + 0.0000000000 2.5003200000 7.6228800000 + 0.0000000000 2.5003200000 2.5409600000 + 7.5009600000 5.0006400000 7.6228800000 + 7.5009600000 5.0006400000 2.5409600000 + 10.0012800000 7.5009600000 7.6228800000 + 7.5009600000 0.0000000000 2.5409600000 + 0.0000000000 0.0000000000 5.0819200000 + 0.0000000000 5.0006400000 5.0819200000 + 7.5009600000 0.0000000000 7.6228800000 + 5.0006400000 0.0000000000 5.0819200000 + 2.5003200000 0.0000000000 2.5409600000 + 5.0006400000 0.0000000000 10.1638400000 + 2.5003200000 0.0000000000 7.6228800000 + 2.5003200000 5.0006400000 7.6228800000 + 1.2501600000 8.7511200000 1.0558196992 + 1.2501600000 8.7511200000 3.5967796992 + 1.2501600000 3.7504800000 8.6786996992 + 1.2501600000 3.7504800000 3.5967796992 + 6.2508000000 8.7511200000 6.1377396992 + 6.2508000000 8.7511200000 1.0558196992 + 6.2508000000 3.7504800000 6.1377396992 + 8.7511200000 1.2501600000 8.6786996992 + 6.2508000000 3.7504800000 1.0558196992 + 1.2501600000 3.7504800000 1.0558196992 + 1.2501600000 8.7511200000 8.6786996992 + 8.7511200000 6.2508000000 3.5967796992 + 8.7511200000 6.2508000000 8.6786996992 + 1.2501600000 8.7511200000 6.1377396992 + 1.2501600000 3.7504800000 6.1377396992 + 6.2508000000 3.7504800000 3.5967796992 + 6.2508000000 6.2508000000 1.4851403008 + 6.2508000000 8.7511200000 3.5967796992 + 6.2508000000 1.2501600000 9.1080203008 + 6.2508000000 1.2501600000 4.0261003008 + 1.2501600000 6.2508000000 9.1080203008 + 1.2501600000 6.2508000000 4.0261003008 + 1.2501600000 1.2501600000 9.1080203008 + 1.2501600000 1.2501600000 4.0261003008 + 6.2508000000 6.2508000000 6.5670603008 + 8.7511200000 1.2501600000 3.5967796992 + 6.2508000000 1.2501600000 6.5670603008 + 6.2508000000 1.2501600000 1.4851403008 + 1.2501600000 6.2508000000 6.5670603008 + 1.2501600000 6.2508000000 1.4851403008 + 1.2501600000 1.2501600000 6.5670603008 + 1.2501600000 1.2501600000 1.4851403008 + 6.2508000000 8.7511200000 8.6786996992 + 6.2508000000 3.7504800000 8.6786996992 + 3.7504800000 6.2508000000 8.6786996992 + 8.7511200000 8.7511200000 9.1080203008 + 3.7504800000 1.2501600000 8.6786996992 + 3.7504800000 3.7504800000 1.4851403008 + 3.7504800000 3.7504800000 6.5670603008 + 3.7504800000 8.7511200000 1.4851403008 + 3.7504800000 8.7511200000 6.5670603008 + 8.7511200000 3.7504800000 1.4851403008 + 8.7511200000 3.7504800000 6.5670603008 + 8.7511200000 8.7511200000 1.4851403008 + 8.7511200000 8.7511200000 6.5670603008 + 3.7504800000 6.2508000000 3.5967796992 + 3.7504800000 3.7504800000 9.1080203008 + 3.7504800000 8.7511200000 4.0261003008 + 3.7504800000 8.7511200000 9.1080203008 + 3.7504800000 3.7504800000 4.0261003008 + 8.7511200000 3.7504800000 9.1080203008 + 3.7504800000 1.2501600000 3.5967796992 + 8.7511200000 3.7504800000 4.0261003008 + 8.7511200000 6.2508000000 1.0558196992 + 8.7511200000 1.2501600000 6.1377396992 + 8.7511200000 1.2501600000 1.0558196992 + 8.7511200000 6.2508000000 6.1377396992 + 3.7504800000 6.2508000000 1.0558196992 + 3.7504800000 1.2501600000 6.1377396992 + 3.7504800000 1.2501600000 1.0558196992 + 6.2508000000 6.2508000000 4.0261003008 + 8.7511200000 8.7511200000 4.0261003008 + 3.7504800000 6.2508000000 6.1377396992 + 6.2508000000 6.2508000000 9.1080203008 + 7.5009600000 2.5003200000 5.0819200000 + 5.0006400000 7.5009600000 7.6228800000 + 5.0006400000 7.5009600000 2.5409600000 + 5.0006400000 2.5003200000 2.5409600000 + 2.5003200000 5.0006400000 2.5409600000 + 5.0006400000 5.0006400000 5.0819200000 + 5.0006400000 5.0006400000 10.1638400000 + 0.0000000000 5.0006400000 10.1638400000 diff --git a/tests/test_replace.py b/tests/test_replace.py new file mode 100644 index 000000000..a8dd917b5 --- /dev/null +++ b/tests/test_replace.py @@ -0,0 +1,40 @@ +import os +import numpy as np +import unittest +from context import dpdata +from comp_sys import CompSys, IsPBC + +from unittest.mock import Mock +from unittest.mock import patch, MagicMock + + +class ConstGenerator(object): + def __init__(self): + self.choice_generator = self.get_choice_generator() + def choice(self, a, size=None, replace=True, p=None): + return next(self.choice_generator) + + @staticmethod + def get_choice_generator(): + yield np.asarray([20, 6, 7, 22, 29, 2, 23, 10]) + +class TestReplace(unittest.TestCase, CompSys, IsPBC): + @patch('numpy.random') + def setUp(self, random_mock): + random_mock.choice = ConstGenerator().choice + self.system_1 = dpdata.System('poscars/POSCAR.P42nmc',fmt='vasp/poscar') + self.system_1.replace('Hf', 'Zr', 8) + # print(self.system_1.data) + self.system_2 = dpdata.System('poscars/POSCAR.P42nmc.replace',fmt='vasp/poscar') + # print(self.system_2.data) + self.places = 6 + +# class TestReplicate123_not_change_origin(unittest.TestCase, CompSys, IsPBC): +# def setUp (self) : +# self.system_1 = dpdata.System('poscars/POSCAR.SiC',fmt='vasp/poscar') +# self.system_1.replicate((1,2,3,)) +# self.system_2 = dpdata.System('poscars/POSCAR.SiC',fmt='vasp/poscar') +# self.places = 6 + +if __name__ == '__main__': + unittest.main() From b293324d7b0863e1e52c29114c458dbc064c47e2 Mon Sep 17 00:00:00 2001 From: Yuan Fengbo Date: Fri, 27 Nov 2020 20:39:34 +0800 Subject: [PATCH 2/2] add documents for replace() method --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 8dd9c8649..2f3dc0d3a 100644 --- a/README.md +++ b/README.md @@ -197,3 +197,13 @@ perturbed_system = dpdata.System('./POSCAR').perturb(pert_num=3, atom_pert_style='normal') print(perturbed_system.data) ``` + +## replace +By the following example, Random 8 Hf atoms in the system will be replaced by Zr atoms with the atom postion unchanged. +```python +s=dpdata.System('tests/poscars/POSCAR.P42nmc',fmt='vasp/poscar') +s.replace('Hf', 'Zr', 8) +s.to_vasp_poscar('POSCAR.P42nmc.replace') +``` + +