def get_kernel_term(kernel_name, hyps_mask, hyps): hyps, cutoffs, hyps_mask = Parameters.get_component_mask(hyps_mask, kernel_name, hyps=hyps) kernel, _, ek, efk, _, _, _ = str_to_kernel_set([kernel_name], "mc", hyps_mask) return (ek, cutoffs, hyps, hyps_mask)
def test_force(kernels, diff_cutoff): """Check that the analytical force kernel matches finite difference of energy kernel.""" d1 = 1 d2 = 2 tol = 1e-3 cell = 1e7 * np.eye(3) delta = 1e-4 cutoffs = np.ones(3) * 1.2 np.random.seed(10) cutoffs, hyps, hm = generate_diff_hm(kernels, diff_cutoff) kernel, kg, en_kernel, fek, _, _, _ = str_to_kernel_set(kernels, "mc", hm) nterm = 0 for term in ["twobody", "threebody", "manybody"]: if term in kernels: nterm += 1 np.random.seed(10) env1 = generate_mb_envs(cutoffs, cell, delta, d1, hm) env2 = generate_mb_envs(cutoffs, cell, delta, d2, hm) # check force kernel kern_finite_diff = 0 if "manybody" in kernels and len(kernels) == 1: _, _, enm_kernel, _, _, _, _ = str_to_kernel_set(["manybody"], "mc", hm) mhyps, mcutoffs, mhyps_mask = Parameters.get_component_mask( hm, "manybody", hyps=hyps ) margs = from_mask_to_args(mhyps, mcutoffs, mhyps_mask) cal = 0 for i in range(3): for j in range(len(env1[0])): cal += enm_kernel(env1[1][i], env2[1][j], *margs) cal += enm_kernel(env1[2][i], env2[2][j], *margs) cal -= enm_kernel(env1[1][i], env2[2][j], *margs) cal -= enm_kernel(env1[2][i], env2[1][j], *margs) kern_finite_diff += cal / (4 * delta ** 2) elif "manybody" in kernels: # TODO: Establish why 2+3+MB fails (numerical error?) return if "twobody" in kernels: ntwobody = 1 _, _, en2_kernel, _, _, _, _ = str_to_kernel_set(["twobody"], "mc", hm) bhyps, bcutoffs, bhyps_mask = Parameters.get_component_mask( hm, "twobody", hyps=hyps ) args2 = from_mask_to_args(bhyps, bcutoffs, bhyps_mask) calc1 = en2_kernel(env1[1][0], env2[1][0], *args2) calc2 = en2_kernel(env1[2][0], env2[2][0], *args2) calc3 = en2_kernel(env1[1][0], env2[2][0], *args2) calc4 = en2_kernel(env1[2][0], env2[1][0], *args2) kern_finite_diff += 4 * (calc1 + calc2 - calc3 - calc4) / (4 * delta ** 2) else: ntwobody = 0 if "threebody" in kernels: _, _, en3_kernel, _, _, _, _ = str_to_kernel_set(["threebody"], "mc", hm) thyps, tcutoffs, thyps_mask = Parameters.get_component_mask( hm, "threebody", hyps=hyps ) args3 = from_mask_to_args(thyps, tcutoffs, thyps_mask) calc1 = en3_kernel(env1[1][0], env2[1][0], *args3) calc2 = en3_kernel(env1[2][0], env2[2][0], *args3) calc3 = en3_kernel(env1[1][0], env2[2][0], *args3) calc4 = en3_kernel(env1[2][0], env2[1][0], *args3) kern_finite_diff += 9 * (calc1 + calc2 - calc3 - calc4) / (4 * delta ** 2) args = from_mask_to_args(hyps, cutoffs, hm) kern_analytical = kernel(env1[0][0], env2[0][0], d1, d2, *args) assert isclose(kern_finite_diff, kern_analytical, rtol=tol)