def test_ric_add_ic(self): with path("saddle.test.data", "water.xyz") as mol_path: mol = Utils.load_file(mol_path) ri_mol = Internal(mol.coordinates, mol.numbers, 0, 1) ri_mol = ReducedInternal.update_to_reduced_internal(ri_mol) ri_mol.add_bond(1, 0) ri_mol.add_bond(1, 2) ri_mol.add_bond(0, 2) ri_mol.vspace ri_mol.add_angle(0, 1, 2) ri_mol.add_angle(1, 0, 2) ri_mol.select_key_ic(0, 2) vp_ref = np.array( [ [4.40930006e-01, -7.79280781e-01, 6.12072474e-17], [-5.61408260e-01, -6.12047068e-01, -3.33066907e-16], [-4.57920570e-01, -3.28254718e-02, -7.16200549e-01], [-5.22760813e-01, 4.87258745e-02, 5.58315734e-01], [8.62054537e-02, 1.21112047e-01, -4.18736570e-01], ] ) for i in range(vp_ref.shape[1]): assert np.allclose(ri_mol.vspace[:, i], vp_ref[:, i]) or np.allclose( ri_mol.vspace[:, i], -1 * vp_ref[:, i] ) ri_mol.set_key_ic_number(1) assert ri_mol._red_space is None assert ri_mol._non_red_space is None
class TestInternal(unittest.TestCase): """Test internal coordinates transform.""" def setUp(self): """Setup function.""" with path("saddle.test.data", "water.xyz") as mol_path: mol = Utils.load_file(mol_path) self.mol = Internal(mol.coordinates, mol.numbers, 0, 1) with path("saddle.test.data", "h2o2.xyz") as mol_path: mol2 = Utils.load_file(mol_path) self.h2o2 = Internal(mol2.coordinates, mol2.numbers, 0, 1) def test_ic_weights(self): """Test change internal coordinates weights.""" self.mol.auto_select_ic() assert_allclose(self.mol.ic_weights, [1, 1, 1]) self.mol.set_ic_weights(np.array([0.5, 0.5, 2])) assert_allclose(self.mol.ic_weights, [0.5, 0.5, 2]) self.h2o2.auto_select_ic() self.h2o2.set_dihed_weights(0) assert self.h2o2.ic[-1].weight == 0 def test_connectivity(self): """Test default connectivity.""" assert_allclose(self.mol.connectivity, np.eye(3) * -1) def test_file_title(self): """Test default file title.""" new_mol = Internal(self.mol.coordinates, self.mol.numbers, 0, 1) assert len(new_mol._title) == 15 def test_add_bond(self): """""" init_con = np.eye(3) * -1 assert_allclose(self.mol.connectivity, init_con) new_con = init_con.copy() # add a bond connection self.mol.add_bond(1, 0) new_con[0, 1] = 1 new_con[1, 0] = 1 # test same connectivity assert_allclose(self.mol.connectivity, new_con) assert_allclose(self.mol.ic_values, np.array([1.81413724])) assert self.mol.ic[0].atoms == (0, 1) # add dup bond self.mol.add_bond(0, 1) ref_hessian = np.array([[ [ 0.18374187, 0.25985046, 0.0, -0.18374187, -0.25985046, 0.0, 0.0, 0.0, 0.0, ], [ 0.25985046, 0.36748434, 0.0, -0.25985046, -0.36748434, 0.0, 0.0, 0.0, 0.0, ], [0.0, 0.0, 0.55122621, 0.0, 0.0, -0.55122621, 0.0, 0.0, 0.0], [ -0.18374187, -0.25985046, 0.0, 0.18374187, 0.25985046, 0.0, 0.0, 0.0, 0.0, ], [ -0.25985046, -0.36748434, 0.0, 0.25985046, 0.36748434, 0.0, 0.0, 0.0, 0.0, ], [0.0, 0.0, -0.55122621, 0.0, 0.0, 0.55122621, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], ]]) assert_allclose(self.mol._cc_to_ic_hessian, ref_hessian) assert len(self.mol.ic) == 1 # bond_type 1 == covalent bond assert_allclose(self.mol.connectivity, new_con) self.mol.add_bond(2, 1) assert len(self.mol.ic) == 2 assert self.mol.ic[1].atoms == (1, 2) assert_allclose( self.mol._cc_to_ic_gradient, np.array([ [ 0.81649681, -0.57734995, 0.0, -0.81649681, 0.57734995, 0.0, 0.0, 0.0, 0.0, ], [ 0.0, 0.0, 0.0, 0.81649681, 0.57734995, 0.0, -0.81649681, -0.57734995, 0.0, ], ]), ) def test_angle_add(self): """Test add angle to internal coordinates.""" self.mol.add_angle(0, 1, 2) assert len(self.mol.ic) == 0 self.mol.add_bond(0, 1) self.mol.add_bond(1, 2) connected_index = self.mol.connected_indices(1) assert_allclose(connected_index, np.array([0, 2])) self.mol.add_angle(0, 1, 2) assert len(self.mol.ic) == 3 assert_allclose(self.mol.ic[2].value, 1.9106340153991836) assert_allclose( self.mol.b_matrix[2], np.array([ 0.31825043, 0.45007444, 0.0, 0.0, -0.90014888, -0.0, -0.31825043, 0.45007444, 0.0, ]), ) assert_allclose( self.mol._cc_to_ic_hessian[2], np.array([ [ -2.86472766e-01, -1.01283669e-01, 0.00000000e00, 2.86472766e-01, 1.01283669e-01, 0.00000000e00, 2.08166817e-17, -6.93889390e-18, 0.00000000e00, ], [ -1.01283669e-01, 2.86472766e-01, 0.00000000e00, 1.01283669e-01, -2.86472766e-01, 0.00000000e00, 6.93889390e-18, 4.16333634e-17, 0.00000000e00, ], [ 0.00000000e00, 0.00000000e00, -1.07427583e-01, 0.00000000e00, 0.00000000e00, 4.29709622e-01, 0.00000000e00, 0.00000000e00, -3.22282039e-01, ], [ 2.86472766e-01, 1.01283669e-01, 0.00000000e00, -5.72945532e-01, 0.00000000e00, 0.00000000e00, 2.86472766e-01, -1.01283669e-01, 0.00000000e00, ], [ 1.01283669e-01, -2.86472766e-01, 0.00000000e00, 0.00000000e00, 5.72945532e-01, 0.00000000e00, -1.01283669e-01, -2.86472766e-01, 0.00000000e00, ], [ 0.00000000e00, 0.00000000e00, 4.29709622e-01, 0.00000000e00, 0.00000000e00, -8.59419245e-01, 0.00000000e00, 0.00000000e00, 4.29709622e-01, ], [ 2.08166817e-17, 6.93889390e-18, 0.00000000e00, 2.86472766e-01, -1.01283669e-01, 0.00000000e00, -2.86472766e-01, 1.01283669e-01, 0.00000000e00, ], [ -6.93889390e-18, 4.16333634e-17, 0.00000000e00, -1.01283669e-01, -2.86472766e-01, 0.00000000e00, 1.01283669e-01, 2.86472766e-01, 0.00000000e00, ], [ 0.00000000e00, 0.00000000e00, -3.22282039e-01, 0.00000000e00, 0.00000000e00, 4.29709622e-01, 0.00000000e00, 0.00000000e00, -1.07427583e-01, ], ]), ) self.mol.set_target_ic((1.6, 1.7, -0.5)) assert_allclose(self.mol.target_ic, np.array([1.6, 1.7, -0.5])) def test_dihedral_add(self): """Test add normal dihedral.""" with path("saddle.test.data", "2h-azirine.xyz") as mol_path: mol = Utils.load_file(mol_path) # create a water molecule internal = Internal(mol.coordinates, mol.numbers, 0, 1) internal.add_bond(0, 1) internal.add_bond(1, 2) internal.add_bond(1, 3) # fake add dihed internal.add_dihedral(0, 2, 3, 4) assert len(internal.ic) == 3 internal.add_dihedral(0, 1, 2, 3) assert len(internal.ic) == 4 assert internal.ic_values[3] == dihed_angle(internal.coordinates[:4]) def test_cost_function(self): """""" self.mol.add_bond(0, 1) self.mol.add_bond(1, 2) self.mol.add_angle(0, 1, 2) assert_allclose( self.mol.ic_values, [1.8141372422079882, 1.8141372422079882, 1.9106340153991836], ) self.mol.set_target_ic([1.7, 1.7, 1.5]) self.mol.swap_internal_coordinates(0, 2) assert_allclose( self.mol.ic_values, [1.9106340153991836, 1.8141372422079882, 1.8141372422079882], ) assert_allclose(self.mol.target_ic, [1.5, 1.7, 1.7]) self.mol.swap_internal_coordinates(0, 2) assert_allclose( self.mol.ic_values, [1.8141372422079882, 1.8141372422079882, 1.9106340153991836], ) assert_allclose(self.mol.target_ic, [1.7, 1.7, 1.5]) # test cost function in ic v = self.mol.tf_cost d = self.mol._cost_q_d dd = self.mol._cost_q_dd # calculate ref cost value ref_cost = (self.mol.ic_values[0] - 1.7)**2 * 2 + ( np.cos(self.mol.ic_values[-1]) - np.cos(1.5))**2 assert_allclose(ref_cost, v) ref_gradient = np.array( [0.22827448441597653, 0.22827448441597653, 0.76192388]) assert_allclose(d, ref_gradient) ref_hessian = np.array([[2.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 1.5083953582]]) assert_allclose(dd, ref_hessian) # assert False new_v, xd, xdd = self.mol.cost_value_in_cc assert new_v == v assert_allclose(xd, np.dot(self.mol._cc_to_ic_gradient.T, d)) ref_x_hessian = np.dot(np.dot(self.mol._cc_to_ic_gradient.T, dd), self.mol._cc_to_ic_gradient) K = np.tensordot(d, self.mol._cc_to_ic_hessian, 1) ref_x_hessian += K assert_allclose(xdd, ref_x_hessian) new_coor = np.array([ [1.40, -0.93019123, -0.0], [-0.0, 0.11720081, -0.0], [-1.40, -0.93019123, -0.0], ]) self.mol.set_new_coordinates(new_coor) assert_allclose(self.mol.ic_values, [1.7484364736491811, 1.7484364736491811, 1.85697699]) assert_allclose( self.mol._cc_to_ic_gradient[0, :6], np.array( [0.80071539, -0.59904495, 0.0, -0.80071539, 0.59904495, -0.0]), ) ref_hessian = np.array([ [0.20524329, 0.27433912, 0.0, -0.20524329, -0.27433912, -0.0], [0.27433912, 0.36669628, 0.0, -0.27433912, -0.36669628, -0.0], [0.0, 0.0, 0.57193957, -0.0, -0.0, -0.57193957], [-0.20524329, -0.27433912, -0.0, 0.20524329, 0.27433912, 0.0], [-0.27433912, -0.36669628, -0.0, 0.27433912, 0.36669628, 0.0], [-0.0, -0.0, -0.57193957, 0.0, 0.0, 0.57193957], ]) assert_allclose(self.mol._cc_to_ic_hessian[0, :6, :6], ref_hessian) def test_transform_function(self): self.mol.add_bond(0, 1) self.mol.add_bond(1, 2) self.mol.add_angle(0, 1, 2) self.mol.set_target_ic([1.7, 1.7, -0.4]) n_p = self.mol.create_geo_point() assert isinstance(n_p, Point) assert n_p.trust_radius == 1.7320508075688772 self.mol.converge_to_target_ic(max_iter=100) g_array = self.mol.cost_value_in_cc[1] assert len(g_array[abs(g_array) > 3e-4]) == 0 def test_auto_ic_select_water(self): self.mol.auto_select_ic() assert_allclose( self.mol.ic_values, [1.8141372422079882, 1.8141372422079882, 1.9106340153991836], ) def test_auto_ic_select_ethane(self): with path("saddle.test.data", "ethane.xyz") as mol_path: mol = Utils.load_file(mol_path) ethane = Internal(mol.coordinates, mol.numbers, 0, 1) ethane.auto_select_ic() assert len(ethane.ic) == 24 def test_auto_dihed_number_ethane(self): with path("saddle.test.data", "ethane.xyz") as mol_path: mol = Utils.load_file(mol_path) mol = Utils.load_file(mol_path) ethane = Internal(mol.coordinates, mol.numbers, 0, 1) ethane.auto_select_ic() counter = 0 for ic in ethane.ic: if isinstance(ic, DihedralAngle): counter += 1 assert counter == 5 def test_auto_select_improper_ch3_hf(self): with path("saddle.test.data", "ch3_hf.xyz") as mol_path: mol = Utils.load_file(mol_path) mol = Internal(mol.coordinates, mol.numbers, 0, 1) mol.auto_select_ic() ic_ref = np.array([ 2.02762919, 2.02769736, 2.02761705, 1.77505755, 4.27707385, 4.87406146, 2.08356856, 2.08391343, 1.64995596, 2.08364916, 1.64984524, 1.64881837, 1.06512165, 0.42765264, 3.14154596, 2.71390135, 0.59485389, -1.70630517, 1.7061358, -3.14152957, 2.09455878, -2.09427619, -2.87079827, ]) assert_allclose(mol.ic_values, ic_ref) def test_auto_ic_select_methanol(self): with path("saddle.test.data", "methanol.xyz") as mol_path: mol = Utils.load_file(mol_path) methanol = Internal(mol.coordinates, mol.numbers, 0, 1) methanol.auto_select_ic() assert len(methanol.ic) == 15 def test_wipe_ic(self): self.mol.add_bond(0, 1) self.mol.add_bond(1, 2) self.mol.add_bond(0, 2) assert len(self.mol.ic) == 3 self.mol.wipe_ic_info(False) assert len(self.mol.ic) == 3 self.mol.wipe_ic_info(True) assert len(self.mol.ic) == 0 def test_set_new_ic(self): mol1 = deepcopy(self.mol) mol2 = deepcopy(self.mol) mol1.add_bond(0, 1) mol1.add_bond(0, 2) mol1.add_angle(1, 0, 2) mol2.set_new_ics(mol1.ic) assert_allclose(mol2.ic_values, mol1.ic_values) mol2.wipe_ic_info(True) mol2.add_bond(2, 0) assert len(mol2.ic) == 1 assert not np.allclose(mol2.connectivity, mol1.connectivity) mol2.set_new_ics(mol1.ic) assert_allclose(mol1.connectivity, mol2.connectivity) def test_get_energy_from_fchk(self): with path("saddle.test.data", "water_1.fchk") as fchk_path: self.mol.add_bond(0, 1) self.mol.add_bond(1, 2) self.mol.add_angle(0, 1, 2) self.mol.energy_from_fchk(fchk_path) ref_g = self.mol.internal_gradient.copy() assert_allclose(self.mol.internal_gradient, ref_g) ic_ref = deepcopy(self.mol.ic) self.mol.add_bond(0, 2) assert not np.allclose(self.mol.internal_gradient.shape, ref_g.shape) self.mol.set_new_ics(ic_ref) assert_allclose(self.mol.internal_gradient, ref_g) self.mol.swap_internal_coordinates(0, 2) assert_allclose(self.mol.internal_gradient[2], ref_g[0]) assert_allclose(self.mol.internal_gradient[0], ref_g[2]) def test_delete_ic(self): with path("saddle.test.data", "ethane.xyz") as mol_path: mol = Utils.load_file(mol_path) ethane = Internal(mol.coordinates, mol.numbers, 0, 1) ethane.auto_select_ic() ethane._delete_ic_index(0) assert len(ethane.ic) == 23 ethane.auto_select_ic(keep_bond=True) assert len(ethane.ic) == 12 # print(ethane.ic) ethane.delete_ic(1, 2, 3) assert len(ethane.ic) == 9 # print(ethane.ic) # assert False def test_fragments_in_mole(self): with path("saddle.test.data", "ch3_hf.xyz") as mol_path: mol = Utils.load_file(mol_path) mol = Internal(mol.coordinates, mol.numbers, 0, 1) assert len(mol.fragments) == mol.natom mol.add_bond(0, 1) mol.add_bond(2, 3) # print(mol.fragments) assert len(mol.fragments) == mol.natom - 2 mol.add_bond(0, 2) assert len(mol.fragments) == mol.natom - 3 mol.add_bond(0, 3) assert len(mol.fragments) == mol.natom - 3 mol.add_bond(4, 5) assert len(mol.fragments) == mol.natom - 4 mol.add_bond(0, 5, b_type=3) assert len(mol.fragments) == 2 def test_fragments_bond_add(self): with path("saddle.test.data", "ch3_hf.xyz") as mol_path: mol = Utils.load_file(mol_path) mol = Internal(mol.coordinates, mol.numbers, 0, 1) mol._auto_select_fragment_bond() assert len(mol.ic) == 15 mol.wipe_ic_info(True) mol.add_bond(0, 1) mol._auto_select_fragment_bond() assert len(mol.ic) == 15 mol.wipe_ic_info(True) mol.add_bond(0, 1) mol.add_bond(0, 5) mol.add_bond(0, 3) mol.add_bond(4, 2) mol._auto_select_fragment_bond() assert len(mol.ic) == 6 mol.wipe_ic_info(True) mol.add_bond(0, 1) mol.add_bond(2, 3) mol.add_bond(4, 5) mol._auto_select_fragment_bond() assert len(mol.ic) == 9 # mol.wipe_ic_info(True) mol.add_bond(0, 1) mol.add_bond(0, 2) mol.add_bond(3, 4) mol.add_bond(4, 5) mol._auto_select_fragment_bond() assert_allclose(mol.ic_values[4], 2.02761704779693) assert mol.ic[4].atoms == (0, 3) assert_allclose(mol.ic_values[5], 3.501060110109399) assert mol.ic[5].atoms == (2, 3) assert len(mol.ic) == 6 def test_dihedral_rotation(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Utils.load_file(mol_path) h2o2 = Internal(mol.coordinates, mol.numbers, 0, 1) h2o2.auto_select_ic() ref_ic = np.array([ 2.47617635, 1.85058569, 1.85070922, 1.81937566, 1.81930967, 1.43966113 ]) assert_allclose(h2o2.ic_values, ref_ic) target_ic = [2.4, 1.8, 1.8, 1.6, 1.6, 1.57] h2o2.set_target_ic(target_ic) h2o2.converge_to_target_ic() assert_allclose(h2o2.ic_values, target_ic, atol=1e-3) target_ic = [2.4, 1.8, 1.8, 1.6, 1.6, 3.14] h2o2.set_target_ic(target_ic) h2o2.converge_to_target_ic() assert_allclose(h2o2.ic_values, target_ic, atol=1e-4) target_ic = [2.4, 1.8, 1.8, 1.6, 1.6, -1.57] h2o2.set_target_ic(target_ic) h2o2.converge_to_target_ic() assert_allclose(h2o2.ic_values, target_ic, atol=1e-3) def test_dihedral_repeak(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Utils.load_file(mol_path) h2o2 = Internal(mol.coordinates, mol.numbers, 0, 1) h2o2.add_bond(0, 1) h2o2.add_bond(1, 2) h2o2.add_bond(2, 3) h2o2.add_bond(3, 2) h2o2.add_bond(0, 2) h2o2.add_bond(1, 3) assert len(h2o2.ic) == 5 h2o2.add_dihedral(0, 1, 2, 3) assert len(h2o2.ic) == 6 h2o2.add_dihedral(0, 2, 1, 3) assert len(h2o2.ic) == 6 def test_new_dihed(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Utils.load_file(mol_path) h2o2 = Internal(mol.coordinates, mol.numbers, 0, 1) h2o2.add_bond(0, 1) h2o2.add_bond(1, 2) h2o2.add_bond(2, 3) assert len(h2o2.ic) == 3 h2o2.add_dihedral(0, 1, 2, 3, special=True) assert len(h2o2.ic) == 5 assert h2o2.b_matrix.shape == (5, 12) h2o2.add_dihedral(3, 1, 2, 0) assert len(h2o2.ic) == 5 h2o2.add_dihedral(3, 2, 1, 0, special=True) assert len(h2o2.ic) == 5 ref_b = h2o2.b_matrix.copy() h2o2._regenerate_ic() assert_allclose(h2o2.b_matrix, ref_b) def test_new_dihed_converge(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Utils.load_file(mol_path) mol = Utils.load_file(mol_path) h2o2 = Internal(mol.coordinates, mol.numbers, 0, 1) h2o2.auto_select_ic(dihed_special=True) assert len(h2o2.ic) == 7 # print(h2o2.ic_values) target_ic = [2.4, 1.8, 1.8, 1.6, 1.6, 0.8, 0.6] h2o2.set_target_ic(target_ic) h2o2.converge_to_target_ic() # print(h2o2.ic_values) assert_allclose(h2o2.ic_values, target_ic, atol=1e-2) # print(h2o2.ic_values) def test_bond_type(self): with path("saddle.test.data", "ch3_hf.xyz") as mol_path: mol = Internal.from_file(mol_path, charge=0, multi=1) mol._auto_select_cov_bond() # numbers [6 1 1 1 9 1] assert np.sum(mol.connectivity[0] == 1) == 3 assert np.sum(mol.connectivity[4] == 1) == 1 mol._auto_select_fragment_bond() assert np.sum(mol.connectivity[0] == 1) == 3 assert len(np.unique(mol.fragments)) == 1 assert np.sum(mol.connectivity[5] == 3) == 2 mol._regenerate_ic() assert np.sum(mol.connectivity[0] == 1) == 3 assert len(np.unique(mol.fragments)) == 1 assert np.sum(mol.connectivity[5] == 3) == 2 mol.wipe_ic_info(True) mol.auto_select_ic() assert np.sum(mol.connectivity[0] == 1) == 3 assert len(np.unique(mol.fragments)) == 1 assert np.sum(mol.connectivity[5] == 3) == 2 def test_h_bond(self): with path("saddle.test.data", "di_water.xyz") as mol_path: mol = Internal.from_file(mol_path, charge=0, multi=1) mol._auto_select_cov_bond() # numbers [8 1 1 8 1 1] assert np.sum(mol.connectivity[0] == 1) == 2 assert np.sum(mol.connectivity[3] == 1) == 2 assert len(mol.fragments) == 2 # print(mol.connectivity) mol._auto_select_h_bond() assert mol.connectivity[2][3] == 2 assert len(mol.fragments) == 2 def test_mini_dihed(self): with path("saddle.test.data", "methanol.xyz") as mol_path: mol = Internal.from_file(mol_path) mol._auto_select_cov_bond() mol._auto_select_h_bond() mol._auto_select_fragment_bond() mol._auto_select_angle() # start real parts ref = len(mol.ic) mol._auto_select_minimum_dihed_normal() assert len(mol.ic) - ref == 1 with path("saddle.test.data", "ethane.xyz") as mol2_path: mol2 = Internal.from_file(mol2_path) mol2._auto_select_cov_bond() mol2._auto_select_h_bond() mol2._auto_select_fragment_bond() mol2._auto_select_angle() # start real parts ref = len(mol2.ic) mol2._auto_select_minimum_dihed_normal() assert len(mol2.ic) - ref == 1 def test_b_matrix(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.add_bond(0, 1) mol.add_bond(1, 2) mol.add_angle(0, 1, 2) ref_mol = deepcopy(mol) q1 = mol.ic_values[0] for i in range(3): coor = mol.coordinates.copy() coor[0][i] += 1e-4 ref_mol.set_new_coordinates(coor) q2 = ref_mol.ic_values[0] fd = (q2 - q1) / 1e-4 b = mol.b_matrix[0][i] assert_allclose(fd, b, atol=1e-4) q1 = mol.ic_values[1] for i in range(3): coor = mol.coordinates.copy() coor[1][i] += 1e-4 ref_mol.set_new_coordinates(coor) q2 = ref_mol.ic_values[1] fd = (q2 - q1) / 1e-4 b = mol.b_matrix[1][3 + i] assert_allclose(fd, b, atol=1e-4) q1 = mol.ic_values[2] for i in range(3): coor = mol.coordinates.copy() coor[2][i] += 1e-4 ref_mol.set_new_coordinates(coor) q2 = ref_mol.ic_values[2] fd = (q2 - q1) / 1e-4 b = mol.b_matrix[2][6 + i] assert_allclose(fd, b, atol=1e-4) def test_b_matrix_dihed(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.auto_select_ic() ref_mol = deepcopy(mol) for j in range(4): q1 = mol.ic_values[j] for i in range(3): coor = mol.coordinates.copy() coor[j][i] += 1e-4 ref_mol.set_new_coordinates(coor) q2 = ref_mol.ic_values[j] fd = (q2 - q1) / 1e-4 b = mol.b_matrix[j][j * 3 + i] assert_allclose(fd, b, atol=1e-4) def test_tfm_hessian(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.add_bond(0, 1) mol.add_bond(1, 2) mol.add_angle(0, 1, 2) ref_mol = deepcopy(mol) qd1 = mol.b_matrix for i in range(3): coor = mol.coordinates.copy() coor[0][i] += 1e-4 ref_mol.set_new_coordinates(coor) qd2 = ref_mol.b_matrix fd_b = (qd2 - qd1) / 1e-4 analytic_b = mol._cc_to_ic_hessian[:, :, i] assert_allclose(fd_b, analytic_b, atol=1e-4) def test_tfm_hessian_dihed(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.auto_select_ic() ref_mol = deepcopy(mol) qd1 = mol.b_matrix for j in range(4): for i in range(3): coor = mol.coordinates.copy() coor[j][i] += 1e-4 ref_mol.set_new_coordinates(coor) qd2 = ref_mol.b_matrix fd_b = (qd2 - qd1) / 1e-4 analytic_b = mol._cc_to_ic_hessian[:, :, 3 * j + i] assert_allclose(fd_b, analytic_b, atol=1e-4) def test_cost_tfm_bond(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.add_bond(0, 1) ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values # print(mol.ic) target_ic[0] = 2 mol.set_target_ic(target_ic) # print(mol.ic[0].value - mol.ic[0].target) cost_v = mol._compute_tfm_cost() cost_g = mol._compute_tfm_gradient() diff = 1e-4 assert_allclose(cost_v, (2 - 2.47617635)**2) # finite diff test for i in range(4): for j in range(3): coor = ref_mol.coordinates.copy() coor[i][j] += diff mol.set_new_coordinates(coor) cost_v_2 = mol._compute_tfm_cost() fd = (cost_v_2 - cost_v) / 1e-4 print(fd, cost_g[i * 3 + j], i * 3 + j) assert_allclose(fd, cost_g[3 * i + j], atol=2e-4) # tests with bond and angle def test_cost_tfm_angle(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.add_bond(0, 1) mol.add_bond(0, 2) mol.add_angle(1, 0, 2) ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values # print(mol.ic) target_ic[2] = 2 target_ic[0] = 2 mol.set_target_ic(target_ic) # print(mol.ic[0].value - mol.ic[0].target) cost_v = mol._compute_tfm_cost() cost_g = mol._compute_tfm_gradient() diff = 1e-4 # assert_allclose(cost_v, (2 - 2.47617635) ** 2) # finite diff test for i in range(4): for j in range(3): coor = ref_mol.coordinates.copy() coor[i][j] += diff mol.set_new_coordinates(coor) cost_v_2 = mol._compute_tfm_cost() fd = (cost_v_2 - cost_v) / 1e-4 print(fd, cost_g[i * 3 + j], i * 3 + j) assert_allclose(fd, cost_g[3 * i + j], atol=2e-4) def test_cost_tfm_dihed(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.auto_select_ic() ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values # print(mol.ic) target_ic[0] = 2 target_ic[3] = 2 target_ic[5] = 2 mol.set_target_ic(target_ic) # print(mol.ic[0].value - mol.ic[0].target) cost_v = mol._compute_tfm_cost() cost_g = mol._compute_tfm_gradient() diff = 1e-4 # assert_allclose(cost_v, (2 - 2.47617635) ** 2) # finite diff test mol.list_ic for i in range(4): for j in range(3): coor = ref_mol.coordinates.copy() coor[i][j] += diff mol.set_new_coordinates(coor) cost_v_2 = mol._compute_tfm_cost() fd = (cost_v_2 - cost_v) / 1e-4 assert_allclose(fd, cost_g[3 * i + j], atol=2e-2) def test_cost_tfm_dihed_cmplx(self): with path("saddle.test.data", "ethane.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.auto_select_ic() ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values + 0.5 # print(mol.ic) mol.set_target_ic(target_ic) # print(mol.ic[0].value - mol.ic[0].target) cost_v = mol._compute_tfm_cost() cost_g = mol._compute_tfm_gradient() diff = 1e-4 # assert_allclose(cost_v, (2 - 2.47617635) ** 2) # finite diff test for i in range(8): for j in range(3): coor = ref_mol.coordinates.copy() coor[i][j] += diff mol.set_new_coordinates(coor) cost_v_2 = mol._compute_tfm_cost() fd = (cost_v_2 - cost_v) / 1e-4 assert_allclose(fd, cost_g[3 * i + j], atol=4e-2) def test_cost_hessian_bond(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.add_bond(0, 1) ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values + 0.5 # print(mol.ic) mol.set_target_ic(target_ic) # print(mol.ic[0].value - mol.ic[0].target) # cost_v = mol._compute_tfm_cost() cost_g = mol._compute_tfm_gradient() cost_h = mol._compute_tfm_hessian() diff = 1e-4 for j in range(4): for i in range(3): coor = ref_mol.coordinates.copy() coor[j, i] += diff mol.set_new_coordinates(coor) cost_g_2 = mol._compute_tfm_gradient() fd = (cost_g_2 - cost_g) / 1e-4 assert_allclose(fd, cost_h[3 * j + i], atol=4e-4) def test_cost_hessian_angle(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.add_bond(0, 1) mol.add_bond(0, 2) mol.add_angle(1, 0, 2) # print(mol.b_matrix) # print(mol.ic) # assert False ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values + 0.5 # print(mol.ic) mol.set_target_ic(target_ic) cost_g = mol._compute_tfm_gradient() cost_h = mol._compute_tfm_hessian() diff = 1e-4 for j in range(4): for i in range(3): coor = ref_mol.coordinates.copy() coor[j, i] += diff mol.set_new_coordinates(coor) cost_g_2 = mol._compute_tfm_gradient() fd = (cost_g_2 - cost_g) / 1e-4 assert_allclose(fd, cost_h[j * 3 + i], atol=4e-4) def test_cost_hessian_dihed(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.auto_select_ic() ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values + 0.5 mol.set_target_ic(target_ic) cost_g = mol._compute_tfm_gradient() cost_h = mol._compute_tfm_hessian() diff = 1e-4 for j in range(4): for i in range(3): coor = ref_mol.coordinates.copy() coor[j, i] += diff mol.set_new_coordinates(coor) cost_g_2 = mol._compute_tfm_gradient() fd = (cost_g_2 - cost_g) / 1e-4 assert_allclose(fd, cost_h[j * 3 + i], atol=4e-2) def test_cost_hessian_cmpl(self): with path("saddle.test.data", "methanol.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.auto_select_ic() ref_mol = deepcopy(mol) coor = mol.coordinates.copy() target_ic = mol.ic_values + 0.5 mol.set_target_ic(target_ic) cost_g = mol._compute_tfm_gradient() cost_h = mol._compute_tfm_hessian() diff = 1e-4 for j in range(6): for i in range(3): coor = ref_mol.coordinates.copy() coor[j, i] += diff mol.set_new_coordinates(coor) cost_g_2 = mol._compute_tfm_gradient() fd = (cost_g_2 - cost_g) / 1e-4 assert_allclose(fd, cost_h[j * 3 + i], atol=4e-2) def test_scipy_opt_tfm(self): with path("saddle.test.data", "h2o2.xyz") as mol_path: mol = Internal.from_file(mol_path) mol.auto_select_ic() target_ic = mol.ic_values target_ic[0] = 2 target_ic[3] = 2 target_ic[5] = 2 mol.set_target_ic(target_ic) mol.converge_to_target_ic() np.allclose(mol.ic_values[0], 2, atol=1e-4) np.allclose(mol.ic_values[3], 2, atol=1e-4) np.allclose(mol.ic_values[5], 2, atol=1e-4) def test_scipy_opt_tfm_cmpx(self): with path("saddle.test.data", "ethane.xyz") as mol_path: mol = Internal.from_file(mol_path) # conventional dihedral mol.auto_select_ic() target_ic = mol.ic_values target_ic[-1] = -1 mol.set_target_ic(target_ic) # print(mol.ic_values) mol.converge_to_target_ic() x_gradient = mol._compute_tfm_gradient() assert np.max(np.abs(x_gradient)) < 1e-4
def test_ic_ric_transform(self): with path("saddle.test.data", "water.xyz") as mol_path: mol = Utils.load_file(mol_path) ri_mol = Internal(mol.coordinates, mol.numbers, 0, 1) ri_mol.add_bond(1, 0) ri_mol.add_bond(1, 2) ri_mol.add_bond(0, 2) ri_mol.add_angle(0, 1, 2) ri_mol.add_angle(1, 0, 2) vc_ref = np.array([1.81413724, 1.81413724, 2.96247453, 1.91063401, 0.61547931]) assert np.allclose(ri_mol.ic_values, vc_ref) ri_mol = ReducedInternal.update_to_reduced_internal(ri_mol) assert isinstance(ri_mol, ReducedInternal) ri_mol.set_key_ic_number(2) ri_mol.select_key_ic(0, 2) print(ri_mol.vspace) vp_ref = np.array( [ [4.40930006e-01, -7.79280781e-01, 6.12072474e-17], [-5.61408260e-01, -6.12047068e-01, -3.33066907e-16], [-4.57920570e-01, -3.28254718e-02, -7.16200549e-01], [-5.22760813e-01, 4.87258745e-02, 5.58315734e-01], [8.62054537e-02, 1.21112047e-01, -4.18736570e-01], ] ) for i in range(vp_ref.shape[1]): assert np.allclose(ri_mol.vspace[:, i], vp_ref[:, i]) or np.allclose( ri_mol.vspace[:, i], -1 * vp_ref[:, i] ) ri_mol.set_key_ic_number(1) assert ri_mol._red_space is None assert ri_mol._non_red_space is None ri_mol.set_key_ic_number(2) for i in range(vp_ref.shape[1]): assert np.allclose(ri_mol.vspace[:, i], vp_ref[:, i]) or np.allclose( ri_mol.vspace[:, i], -1 * vp_ref[:, i] ) new_coor = np.array( [ [1.40, -0.93019123, -0.0], [-0.0, 0.11720081, -0.0], [-1.40, -0.93019123, -0.0], ] ) ri_mol.set_new_coordinates(new_coor) ref_ic = [ 1.7484364736491811, 2.8, 1.7484364736491811, 1.8569769819, 0.6423078258, ] assert np.allclose(ri_mol.ic_values, ref_ic) ri_mol.vspace assert ri_mol._red_space is not None assert ri_mol._non_red_space is not None print(ri_mol._red_space) ri_mol.add_angle(0, 2, 1) print(ri_mol._red_space) assert ri_mol._red_space is None assert ri_mol._non_red_space is None
class Test_TS_Construct(unittest.TestCase): file_list = [] def setUp(self): with path("saddle.test.data", "ch3_hf.xyz") as rct_path: self.rct = Utils.load_file(rct_path) with path("saddle.test.data", "ch3f_h.xyz") as prd_path: self.prd = Utils.load_file(prd_path) self.reactant_ic = Internal(self.rct.coordinates, self.rct.numbers, 0, 2) self.product_ic = Internal(self.prd.coordinates, self.prd.numbers, 0, 2) def test_auto_internal(self): ts_ins = TSConstruct(self.reactant_ic, self.product_ic) assert isinstance(ts_ins.reactant, Internal) assert isinstance(ts_ins.product, Internal) ts_ins.auto_select_ic() assert len(ts_ins.reactant.ic) == len(ts_ins.product.ic) self.reactant_ic.auto_select_ic() print(ts_ins.reactant.ic) print(self.reactant_ic.ic) # self.reactant_ic.add_bond(0, 4) # self.reactant_ic.add_angle(1, 0, 4) # self.reactant_ic.add_angle(2, 0, 4) # assert len(self.reactant_ic.ic) != len(ts_ins.reactant.ic) # self.reactant_ic.add_angle(3, 0, 4) assert len(ts_ins.reactant.ic_values) - len( self.reactant_ic.ic_values) == 11 def test_auto_ic_create(self): ts_ins = TSConstruct(self.reactant_ic, self.product_ic) ts_ins.auto_select_ic() ref_ic_rct = np.array([ 2.02762919, 2.02769736, 2.02761705, 1.77505755, 4.27707385, 4.87406146, 2.08356856, 2.08391343, 1.64995596, 2.08364916, 1.64984524, 1.64881837, 1.06512165, 0.427652638, 3.14154596, 2.71390135, 0.594853893, -1.70630517, 1.70613580, -3.14152957, 2.09455878, -2.09427619, -2.87079827, 6.05213140, 1.64996828, 1.64984426, 1.64880703, 1.36936807e-05, 3.29954545e-05, -0.452180460, 1.64217144, -2.54673936, 2.68941267, -1.49942229, ]) ref_ic_prd = np.array([ 2.03992597, 2.03991419, 2.03976417, 5.52444423, 8.17667938, 9.06322941, 1.91251903, 1.9119936, 1.92886636, 1.91202283, 1.88746552, 1.91077332, 1.01701674, 0.2138026, 0.01152089, 0.2133746, -1.50710794, -2.11774407, 2.06704189, 0.05432083, 2.10752341, -2.0822473, -2.09807877, 2.6533652, 1.90903961, 1.90907132, 1.90914538, 0.02398886, 3.1060829, -2.54607887, -0.4513039, 1.6429288, 0.60041547, 2.69383007, ]) print(ts_ins.reactant.ic_values, "r") print(ts_ins.product.ic_values, "p") assert np.allclose(ts_ins.reactant.ic_values, ref_ic_rct) assert np.allclose(ts_ins.product.ic_values, ref_ic_prd) def test_ts_construct(self): ts_ins = TSConstruct(self.reactant_ic, self.product_ic) ts_ins.auto_select_ic() ts_ins.create_ts_state(start_with="product", flex_sin=False) result = deepcopy(ts_ins.ts) ts_ins.create_ts_state(start_with="reactant", flex_sin=False) result_2 = deepcopy(ts_ins.ts) # print result_2.ic_values ref_tar_ic = ts_ins._reactant.ic_values * 0.5 + ts_ins._product.ic_values * 0.5 assert np.allclose(ref_tar_ic, result.target_ic) assert np.allclose(result.target_ic, result_2.target_ic) # assert np.allclose( # result.ic_values[:4], result.target_ic[:4], atol=1e-6) # TODO: need to check structure # assert np.allclose( # result_2.ic_values[:4], result_2.target_ic[:4], atol=1e-6) assert_allclose(result.ic_values[:16], result_2.ic_values[:16], atol=1e-3) ts_ins.select_key_ic(1) assert ts_ins.key_ic_counter == 1 assert np.allclose(ts_ins.ts.ic_values[:2][::-1], result_2.ic_values[:2]) assert np.allclose(ts_ins.ts._cc_to_ic_gradient[1], result_2._cc_to_ic_gradient[0]) def test_ts_union(self): self.reactant_ic.add_bond(0, 1) self.reactant_ic.add_bond(1, 2) self.reactant_ic.add_angle(0, 1, 2) self.product_ic.add_bond(1, 0) self.product_ic.add_bond(0, 2) self.product_ic.add_angle(1, 0, 2) ts_ins = TSConstruct(self.reactant_ic, self.product_ic) union_ic = ts_ins._get_union_of_ics() assert len(union_ic) == 5 def test_ts_union_reactant(self): self.reactant_ic.add_bond(0, 1) self.reactant_ic.add_bond(1, 2) self.reactant_ic.add_angle(0, 1, 2) ts_ins = TSConstruct(self.reactant_ic, self.product_ic) union_ic = ts_ins._get_union_of_ics(mode="reactant") assert len(union_ic) == 3 ts_ins.auto_select_ic(auto_select=False, mode="reactant") assert len(ts_ins.product.ic) == 3 def test_ts_union_product(self): self.product_ic.add_bond(1, 0) self.product_ic.add_bond(0, 2) self.product_ic.add_angle(1, 0, 2) ts_ins = TSConstruct(self.reactant_ic, self.product_ic) union_ic = ts_ins._get_union_of_ics(mode="product") assert len(union_ic) == 3 ts_ins.auto_select_ic(auto_select=False, mode="product") assert len(ts_ins.reactant.ic) == 3 flag = 1 try: ts_ins.auto_select_ic(auto_select=False, mode="wrong") except InvalidArgumentError: flag = 0 assert flag == 0 def test_ts_create(self): ts_ins = TSConstruct(self.reactant_ic, self.product_ic) ts_ins.auto_select_ic() ts_ins.create_ts_state(start_with="reactant") ts_ins.select_key_ic(3, 4) assert isinstance(ts_ins.ts.ic[0], type(ts_ins.product.ic[3])) assert isinstance(ts_ins.product.ic[3], type(ts_ins.ts.ic[0])) assert isinstance(ts_ins.ts.ic[1], type(ts_ins.product.ic[4])) assert isinstance(ts_ins.product.ic[4], type(ts_ins.ts.ic[1])) assert ts_ins.ts.key_ic_number == 2 new_ins = TSConstruct(self.reactant_ic, self.product_ic) assert new_ins is not ts_ins new_ins.auto_generate_ts() new_ins.select_key_ic(3, 4) assert np.allclose(new_ins.ts.ic_values, ts_ins.ts.ic_values) assert isinstance(new_ins.ts, ReducedInternal) def test_ts_combine(self): # maybe a problem self.reactant_ic.auto_select_ic() self.product_ic.auto_select_ic() new_ins = TSConstruct(self.reactant_ic, self.product_ic) new_ins.auto_generate_ts(start_with="product", reset_ic=False) # test gradient assert all(np.abs(new_ins.ts._compute_tfm_gradient()) < 3e-4) # test hessian eigenvalues e_v = np.linalg.eigh(new_ins.ts._compute_tfm_hessian())[0] assert all(e_v[np.abs(e_v) > 1e-4] > 0) def test_choices_auto_select_ic(self): self.reactant_ic.add_bond(2, 4) new_ins = TSConstruct(self.reactant_ic, self.product_ic) new_ins.auto_generate_ts(auto_select=False) print("rct", self.reactant_ic.ic) print("prd", self.product_ic.ic) ref_ic = (self.reactant_ic.distance(2, 4) + self.product_ic.distance(2, 4)) / 2 assert np.allclose(new_ins.ts.ic_values, ref_ic) new_ins = TSConstruct(self.reactant_ic, self.product_ic) print("rct", new_ins.reactant.ic) print("prd", new_ins.product.ic) new_ins.auto_generate_ts(auto_select=True, reset_ic=False, flex_sin=False) # print('rct', new_ins.reactant.ic) # print('prd', new_ins.product.ic) print("ts", new_ins.ts.ic) print("target_ic", new_ins.ts.target_ic) print("ts g", new_ins.ts._compute_tfm_gradient()) # print('ts g', new_ins.) # with deepcopy 31, no deepcopy 44 assert len(new_ins.ts.ic) == 31 # TODO: need to be reviewed # print(new_ins.ts.ic) print(new_ins.ts.tf_cost) assert_allclose(new_ins.ts.ic_values[0], new_ins.ts.target_ic[0], atol=2e-2) assert_allclose(new_ins.ts.ic_values[1:4], new_ins.ts.target_ic[1:4], atol=2e-2) new_ins = TSConstruct(self.reactant_ic, self.product_ic) new_ins.auto_generate_ts(auto_select=True, reset_ic=True) assert all(abs(new_ins.ts._compute_tfm_gradient()) < 3e-4) # def test_from_file_and_to_file(self): # with path('saddle.test.data', 'ch3_hf.xyz') as rct_p: # with path('saddle.test.data', 'ch3f_h.xyz') as prd_p: # ts = TSConstruct.from_file(rct_p, prd_p) # ts_ins = TSConstruct(self.reactant_ic, self.product_ic) # ts.auto_generate_ts() # ts_ins.auto_generate_ts() # with path('saddle.test.data', 'ts_nose_test_cons.xyz') as filepath: # ts.ts_to_file(filepath) # self.file_list.append(filepath) # mol = Utils.from_file(filepath) # assert np.allclose(mol.coordinates, ts.ts.coordinates) def test_from_file_to_path(self): with path("saddle.test.data", "rct.xyz") as rct_path: with path("saddle.test.data", "prd.xyz") as prd_path: ts_mol = TSConstruct.from_file(rct_path, prd_path) ts_mol.auto_generate_ts(task="path") assert isinstance(ts_mol.ts, PathRI) def test_update_rct_prd_structure(self): with path("saddle.test.data", "rct.xyz") as rct_path: with path("saddle.test.data", "prd.xyz") as prd_path: ts_mol = TSConstruct.from_file(rct_path, prd_path) ts_mol.auto_generate_ts(task="path") assert len(ts_mol.ts.ic) == 9 ts_mol.ts.auto_select_ic(keep_bond=True) assert len(ts_mol.ts.ic) == 12 ts_mol.update_rct_and_prd_with_ts() assert len(ts_mol.rct.ic) == 12 assert len(ts_mol.prd.ic) == 12 for i in range(12): assert ts_mol.rct.ic[i].atoms == ts_mol.prd.ic[i].atoms def test_dihed_special_structure(self): with path("saddle.test.data", "rct.xyz") as rct_path: with path("saddle.test.data", "prd.xyz") as prd_path: ts_mol = TSConstruct.from_file(rct_path, prd_path) ts_mol.auto_generate_ts(dihed_special=True) assert len(ts_mol.ts.ic) == 11 @classmethod def tearDownClass(cls): for i in cls.file_list: os.remove(i)