def base_multipole_fields(self, options): mol = cache.molecule["pna"] cppe_state = CppeState(options, mol, lambda s: None) cppe_state.calculate_static_energies_and_fields() multipole_fields = cppe_state.multipole_fields potentials = cppe_state.potentials polsites = get_polarizable_sites(potentials) ref = np.zeros((len(potentials), 3)) for i, p1 in enumerate(polsites): for j, p2 in enumerate(polsites): if not p1.is_polarizable: continue if p1.index == p2.index: continue if p1.excludes_site(p2.index): continue diff = p1.position - p2.position for m in p2.multipoles: M_full = symmetry.unfold_tensor(m.values, m.k) if options.get("damp_multipole", False): a_i = p1.polarizability.isotropic_value a_j = p2.polarizability.isotropic_value damp = cppe_state.options["damping_factor_multipole"] a = 1/(a_i*a_j)**(1/6) * damp ref[p1.index, :] += polfields.thole_exp_field( diff, m.k, M_full, 1, a) else: ref[p1.index, :] += polfields.field( diff, m.k, M_full, 1) np.testing.assert_allclose(ref.flatten(), multipole_fields, atol=1e-14)
def test_nuclear_fields(self): mol = cache.molecule["pna"] options = {"potfile": self.potfile_path} cppe_state = CppeState(options, mol, lambda s: None) cppe_state.calculate_static_energies_and_fields() nuclear_fields = cppe_state.nuclear_fields potentials = cppe_state.potentials ref = np.zeros((len(potentials), 3)) for i, p in enumerate(potentials): for a in mol: diff = p.position - a.position ref[i, :] += a.charge * diff / np.linalg.norm(diff)**3 np.testing.assert_allclose(ref.flatten(), nuclear_fields, atol=1e-14)
def test_solver_by_inversion(self): mol = cache.molecule["pna"] options = {"potfile": self.potfile_path, "induced_thresh": 1e-12} cppe_state = CppeState(options, mol, print_callback) cppe_state.calculate_static_energies_and_fields() static_fields = cppe_state.static_fields zeros = np.zeros_like(static_fields) cppe_state.update_induced_moments(zeros, False) potentials = cppe_state.potentials polsites = get_polarizable_sites(potentials) npolsites = cppe_state.get_polarizable_site_number() bmat = np.zeros((3 * npolsites, 3 * npolsites)) for s1, pot1 in enumerate(polsites): pol = pot1.polarizability inv_alpha = triangle_to_mat(pol.values) bmat[block(s1, s1)] = np.linalg.inv(inv_alpha) for s2, pot2 in enumerate(polsites): if pot1.excludes_site(pot2.index) or s1 == s2: continue diff = pot2.position - pot1.position T12 = T_recursive(2, diff) if s1 > s2: bmat[block(s1, s2)] = -triangle_to_mat(T12) bmat[block(s2, s1)] = -triangle_to_mat(T12) # Test the matrix apply bmatrix_cpp = BMatrix(polsites, options) ret = bmatrix_cpp.compute_apply(static_fields) ret_ref = bmat @ static_fields np.testing.assert_allclose(ret, ret_ref, atol=1e-12) ret1 = bmatrix_cpp.compute_apply_slice(static_fields, 0, 8) ret2 = bmatrix_cpp.compute_apply_slice(static_fields, 8, npolsites) ret_all = ret1 + ret2 np.testing.assert_allclose(ret_all, ret_ref, atol=1e-12) # build the Bmatrix from C++ A = LinearOperator(2 * (static_fields.size,), matvec=bmatrix_cpp.compute_apply) Afull = A @ np.eye(static_fields.size) np.testing.assert_allclose(Afull, bmat, atol=1e-20) induced_moments_direct = np.linalg.inv(bmat) @ static_fields induced_moments_solver = cppe_state.get_induced_moments() np.testing.assert_almost_equal(induced_moments_solver, induced_moments_direct, decimal=9) ind_mom = InducedMoments(potentials, options) res_cg = ind_mom.compute_cg(static_fields) np.testing.assert_allclose(res_cg, induced_moments_direct, atol=1e-10) binv = bmatrix_cpp.direct_inverse() np.testing.assert_allclose(binv @ static_fields, induced_moments_direct, atol=1e-15)
def test_set_all(self): custom_options = { "potfile": self.potfile_path, "iso_pol": True, "induced_thresh": 1e-4, "maxiter": 500, "damp_induced": True, "damp_multipole": True, "damping_factor_induced": 213.04, "damping_factor_multipole": 213.04, # summation "summation_induced_fields": "fmm", "tree_expansion_order": 4, "tree_ncrit": 12, "theta": 0.2, # border "pe_border": True, "border_type": "redist", "border_rmin": 2.6, "border_nredist": 2, "border_redist_order": 2, "border_redist_pol": True, } cppe_state = CppeState(custom_options) for k in custom_options: assert custom_options[k] == cppe_state.options[k]
def solve_induced_moments(options, mol): cppe_state = CppeState(options, mol) cppe_state.calculate_static_energies_and_fields() static_fields = np.array(cppe_state.get_static_fields()) zeros = np.zeros_like(static_fields) cppe_state.update_induced_moments(zeros, False) return cppe_state
def test_defaults(self): options_dict = {"potfile": self.potfile_path} cppe_state = CppeState(options_dict) defaults = self.default_options.copy() defaults.pop("potfile") cppe_options = cppe_state.options.copy() cppe_options.pop("potfile") assert len(defaults) == len(cppe_options) for k in defaults: assert defaults[k] == cppe_state.options[k]
def test_solver_by_inversion(self): f = h5py.File(self.pna_path, 'r') mol = Molecule() options = PeOptions() options.potfile = self.potfile_path options.induced_thresh = 12 for z, coord in zip(f['atom_charges'], f['atom_coords']): mol.append(Atom(z, *coord)) cppe_state = CppeState(options, mol) cppe_state.calculate_static_energies_and_fields() static_fields = np.array(cppe_state.get_static_fields()) zeros = np.zeros_like(static_fields) cppe_state.update_induced_moments(zeros, False) potentials = cppe_state.get_potentials() polsites = get_polarizable_sites(potentials) npolsites = cppe_state.get_polarizable_site_number() bmat = np.zeros((3 * npolsites, 3 * npolsites)) coeffs = Tk_coefficients(5) for s1, pot1 in enumerate(polsites): for pol in pot1.get_polarizabilities(): inv_alpha = triangle_to_mat(pol.get_values()) bmat[block(s1, s1)] = np.linalg.inv(inv_alpha) for s2, pot2 in enumerate(polsites): if pot1.excludes_site(pot2.index) or s1 == s2: continue diff = pot2.get_site_position() - pot1.get_site_position() T12 = Tk_tensor(2, diff, coeffs) if s1 > s2: bmat[block(s1, s2)] = -triangle_to_mat(T12) bmat[block(s2, s1)] = -triangle_to_mat(T12) induced_moments_direct = np.linalg.inv(bmat) @ static_fields induced_moments_solver = cppe_state.get_induced_moments() np.testing.assert_almost_equal(induced_moments_solver, induced_moments_direct, decimal=10)
def solve_induced_moments(options, mol): cppe_state = CppeState(options, mol, print_callback) cppe_state.calculate_static_energies_and_fields() static_fields = cppe_state.static_fields np.testing.assert_allclose( static_fields, cppe_state.nuclear_fields + cppe_state.multipole_fields ) zeros = np.zeros_like(static_fields) cppe_state.update_induced_moments(zeros, False) return cppe_state
def test_compute_nuclear_interaction_energy(self): f = h5py.File(self.pna_path, 'r') mol = Molecule() options = PeOptions() options.potfile = self.potfile_path for z, coord in zip(f['atom_charges'], f['atom_coords']): mol.append(Atom(z, *coord)) cppe_state = CppeState(options, mol) assert cppe_state.get_polarizable_site_number() == 18 cppe_state.calculate_static_energies_and_fields() en_el_nuc = cppe_state.get_energies().get("Electrostatic/Nuclear") ref = -0.321349401430 # pelib np.testing.assert_almost_equal(en_el_nuc, ref, decimal=9)
def test_compute_nuclear_interaction_energy(self): mol = cache.molecule["pna"] options = {"potfile": self.potfile_path} cppe_state = CppeState(options, mol, print_callback) assert cppe_state.get_polarizable_site_number() == 18 cppe_state.calculate_static_energies_and_fields() en_el_nuc = cppe_state.energies["Electrostatic"]["Nuclear"] ref = -0.321349401430 # pelib np.testing.assert_almost_equal(en_el_nuc, ref, decimal=9) # TODO: split these tests up, use cache # test writing to the energy container from Python bla = cppe_state.energies["Electrostatic"] bla["Nuclear"] = -10.0 assert bla["Nuclear"] == -10.0 cppe_state.energies["Electrostatic"]["Nuclear"] = -20.0 assert cppe_state.energies["Electrostatic"]["Nuclear"] == -20.0 cppe_state.energies["Electrostatic"]["Electronic"] = 1.0 cppe_state.energies["Electrostatic"]["Nuclear"] = 2.0 cppe_state.energies["Electrostatic"]["Multipoles"] = 3.0 cppe_state.energies["Polarization"]["Electronic"] = 4.0 cppe_state.energies["Polarization"]["Nuclear"] = 5.0 cppe_state.energies["Polarization"]["Multipole"] = 6.0 total_energy = ( cppe_state.energies["Electrostatic"]["Electronic"] + cppe_state.energies["Electrostatic"]["Nuclear"] + cppe_state.energies["Electrostatic"]["Multipoles"] + cppe_state.energies["Polarization"]["Electronic"] + cppe_state.energies["Polarization"]["Nuclear"] + cppe_state.energies["Polarization"]["Multipole"] ) assert cppe_state.total_energy == total_energy
def test_invalid_key(self): defaults = self.default_options.copy() defaults["invalid_key"] = 42 with pytest.raises(ValueError): CppeState(defaults)