def compute(self, function, data): """ Compute descriptor for one structure to the database. """ if function['type'] in ['BehlerParrinello', 'ACSF']: from pyxtal_ff.descriptors.ACSF import ACSF d = ACSF(function['parameters'], function['Rc'], function['force'], function['stress'], False).calculate(data['structure']) elif function['type'] in ['wACSF', 'wacsf']: from pyxtal_ff.descriptors.ACSF import ACSF d = ACSF(function['parameters'], function['Rc'], function['force'], function['stress'], True).calculate(data['structure']) elif function['type'] in ['SO4', 'Bispectrum', 'bispectrum']: from pyxtal_ff.descriptors.SO4 import SO4_Bispectrum d = SO4_Bispectrum( function['parameters']['lmax'], function['Rc'], derivative=function['force'], stress=function['stress'], normalize_U=function['parameters']['normalize_U']).calculate( data['structure']) elif function['type'] in ['SO3', 'SOAP', 'soap']: from pyxtal_ff.descriptors.SO3 import SO3 d = SO3(function['parameters']['nmax'], function['parameters']['lmax'], function['Rc'], derivative=function['force'], stress=function['stress']).calculate(data['structure']) elif function['type'] in ['EAMD', 'eamd']: from pyxtal_ff.descriptors.EAMD import EAMD d = EAMD(function['parameters'], function['Rc'], function['force'], function['stress']).calculate(data['structure']) else: msg = f"{function['type']} is not implemented" raise NotImplementedError(msg) if d['rdxdr'] is not None: N = d['x'].shape[0] L = d['x'].shape[1] rdxdr = np.zeros([N, L, 3, 3]) for _m in range(N): ids = np.where(d['seq'][:, 0] == _m)[0] rdxdr[_m, :, :, :] += np.einsum('ijkl->jkl', d['rdxdr'][ids, :, :, :]) d['rdxdr'] = rdxdr.reshape([N, L, 9])[:, :, [0, 4, 8, 1, 2, 5]] #d['rdxdr'] = np.einsum('ijklm->iklm', d['rdxdr'])\ #.reshape([shp[0], shp[2], shp[3]*shp[4]])[:, :, [0, 4, 8, 1, 2, 5]] #need to change d['energy'] = np.asarray(data['energy']) d['force'] = np.asarray(data['force']) if data['stress'] is not None: d['stress'] = np.asarray(data['stress']) else: d['stress'] = data['stress'] d['group'] = data['group'] return d
class TestSO4(unittest.TestCase): from pyxtal_ff.descriptors.SO4 import SO4_Bispectrum struc = get_rotated_struc(cu) b0_poly = SO4_Bispectrum(lmax=1, rcut=rcut, stress=True, derivative=True).calculate(struc)#, backend='pymatgen') struc = get_rotated_struc(cu, 20, 'x') b1_poly = SO4_Bispectrum(lmax=1, rcut=rcut, stress=True, derivative=True).calculate(struc)#, backend='pymatgen') struc = get_perturbed_struc(cu, eps) b2_poly = SO4_Bispectrum(lmax=1, rcut=rcut, derivative=False).calculate(struc)#, backend='pymatgen') def test_B_poly_rotation_variance(self): array1 = self.b0_poly['x'].flatten() array2 = self.b1_poly['x'].flatten() self.assertTrue(np.allclose(array1, array2)) def test_dBdr_poly_rotation_variance(self): array1 = np.linalg.norm(self.b0_poly['dxdr'][0,:,:], axis=1) array2 = np.linalg.norm(self.b1_poly['dxdr'][0,:,:], axis=1) self.assertTrue(np.allclose(array1, array2)) def test_dBdr_poly_vs_numerical(self): array1 = (self.b2_poly['x'][0] - self.b0_poly['x'][0]).flatten()/eps array2 = self.b0_poly['dxdr'][0, :, 0].flatten() self.assertTrue(np.allclose(array1, array2, rtol=1e-2, atol=1e-2))
def compute_descriptor(function, structure): """ Compute descriptor for one structure. """ if function['type'] in ['BehlerParrinello', 'ACSF']: from pyxtal_ff.descriptors.ACSF import ACSF d = ACSF(function['parameters'], function['Rc'], function['force'], function['stress'], function['cutoff'], False).calculate(structure) elif function['type'] in ['wACSF', 'wacsf']: from pyxtal_ff.descriptors.ACSF import ACSF d = ACSF(function['parameters'], function['Rc'], function['force'], function['stress'], function['cutoff'], True).calculate(structure) elif function['type'] in ['SO4', 'Bispectrum', 'bispectrum']: from pyxtal_ff.descriptors.SO4 import SO4_Bispectrum d = SO4_Bispectrum( function['parameters']['lmax'], function['Rc'], derivative=True, stress=True, normalize_U=function['parameters']['normalize_U'], cutoff_function=function['cutoff']).calculate(structure) elif function['type'] in ['SO3', 'SOAP', 'soap']: from pyxtal_ff.descriptors.SO3 import SO3 d = SO3(function['parameters']['nmax'], function['parameters']['lmax'], function['Rc'], derivative=True, stress=True).calculate(structure) elif function['type'] in ['EAD', 'ead']: from pyxtal_ff.descriptors.EAD import EAD d = EAMD(function['parameters'], function['Rc'], True, True, function['cutoff']).calculate(structure) elif function['type'] in ['SNAP', 'snap']: from pyxtal_ff.descriptors.SNAP import SO4_Bispectrum d = SO4_Bispectrum( function['weights'], function['parameters']['lmax'], function['Rc'], derivative=True, stress=True, normalize_U=function['parameters']['normalize_U'], cutoff_function=function['cutoff']).calculate(structure) else: msg = f"{function['type']} is not implemented" raise NotImplementedError(msg) if d['rdxdr'] is not None: #shp = d['rdxdr'].shape #d['rdxdr'] = np.einsum('ijklm->iklm', d['rdxdr'])\ # .reshape([shp[0], shp[2], shp[3]*shp[4]])[:, :, [0,4,8,1,2,5]] N = d['x'].shape[0] L = d['x'].shape[1] rdxdr = np.zeros([N, L, 3, 3]) for _m in range(N): ids = np.where(d['seq'][:, 0] == _m)[0] rdxdr[_m, :, :, :] += np.einsum('ijkl->jkl', d['rdxdr'][ids, :, :, :]) d['rdxdr'] = rdxdr.reshape([N, L, 9])[:, :, [0, 4, 8, 1, 2, 5]] return d