def test_fmm_force_ewald_2(): R = 3 eps = 10.**-6 free_space = True N = 2 E = 4. rc = E / 8 A = state.State() A.domain = domain.BaseDomainHalo(extent=(E, E, E)) A.domain.boundary_condition = domain.BoundaryTypePeriodic() ASYNC = False DIRECT = True if MPISIZE == 1 else False DIRECT = True EWALD = True fmm = PyFMM(domain=A.domain, r=R, eps=eps, free_space=free_space) A.npart = N rng = np.random.RandomState(seed=1234) A.P = data.PositionDat(ncomp=3) A.F = data.ParticleDat(ncomp=3) A.FE = data.ParticleDat(ncomp=3) A.Q = data.ParticleDat(ncomp=1) A.crr = data.ScalarArray(ncomp=1) A.cri = data.ScalarArray(ncomp=1) A.crs = data.ScalarArray(ncomp=1) if N == 4: ra = 0.25 * E nra = -0.25 * E A.P[0, :] = (0.21, 0.21, 0.00) A.P[1, :] = (-0.21, 0.21, 0.00) A.P[2, :] = (-0.21, -0.21, 0.00) A.P[3, :] = (0.21, -0.21, 0.00) #A.P[0,:] = ( 0.00, 0.21, 0.21) #A.P[1,:] = ( 0.00, 0.21,-0.21) #A.P[2,:] = ( 0.00, -0.21,-0.21) #A.P[3,:] = ( 0.00, -0.21, 0.21) #A.P[0,:] = ( 1.01, 1.01, 0.00) #A.P[1,:] = (-1.01, 1.01, 0.00) #A.P[2,:] = (-1.01, -1.01, 0.00) #A.P[3,:] = ( 1.01, -1.01, 0.00) A.Q[0, 0] = -1. A.Q[1, 0] = 1. A.Q[2, 0] = -1. A.Q[3, 0] = 1. elif N == 1: A.P[0, :] = (0.25 * E, 0.25 * E, 0.25 * E) A.P[0, :] = (10.**-6, 10.**-6, 10.**-6) #A.P[0,:] = (0, -0.25*E, 0) #A.P[1,:] = (0, 0.25*E, 0) #A.P[0,:] = (0, 0, -0.25*E) #A.P[1,:] = (0, 0, 0.25*E) #A.Q[:,0] = 1. A.Q[0, 0] = 1. elif N == 2: #A.P[0,:] = ( 0.25*E, 0.25*E, 0.25*E) #A.P[1,:] = ( -0.25*E, -0.25*E, 0) #A.P[0,:] = (0, -0.25*E, 0) #A.P[1,:] = (0, 0.25*E, 0) #A.P[0,:] = (0, 0, -0.25*E) #A.P[1,:] = (0, 0, 0.25*E) #A.Q[:,0] = 1. ra = 0.25 * E nra = -0.25 * E eps = 0.00 epsx = 0 epsy = 0 epsz = 0 A.P[0, :] = (1.999999, 0., 0.) A.P[1, :] = (0., 0., 0.) #A.P[:2:,:] = rng.uniform(low=-0.4999*E, high=0.4999*E, size=(N,3)) A.Q[0, 0] = -1. A.Q[1, 0] = 1. elif N == 8: for px in range(8): phi = (float(px) / 8) * 2. * math.pi pxr = 0.25 * E pxx = pxr * math.cos(phi) pxy = pxr * math.sin(phi) A.P[px, :] = (pxx, pxy, 0) A.Q[px, 0] = 1. - 2. * (px % 2) #A.Q[px, 0] = -1. #A.P[0,:] += eps eps = 0.00001 #A.P[0:N:2,0] += eps #A.P[0,0] -= eps A.P[4, 0] -= eps A.P[:, 2] -= 0.200 A.P[:, 1] -= 0.200 #A.Q[0,0] = 0. A.Q[1, 0] = 0. A.Q[4, 0] = 0. A.Q[3, 0] = 0. A.Q[5, 0] = 0. A.Q[6, 0] = 0. A.Q[7, 0] = 0. else: assert N % 2 == 0 for px in range(N // 2): pos = rng.uniform(low=-0.4999 * E, high=0.4999 * E, size=(1, 3)) cha = rng.uniform(low=-1., high=1.) A.P[px, :] = pos A.Q[px, 0] = cha A.P[-1 * (px + 1), :] = -1.0 * pos A.Q[-1 * (px + 1), 0] = cha bias = np.sum(A.Q[:]) A.Q[:, 0] -= bias / N dipole = np.zeros(3) for px in range(N): dipole[:] += A.P[px, :] * A.Q[px, 0] bias = np.sum(A.Q[:]) print("DIPOLE:\t", dipole, "TOTAL CHARGE:\t", bias) A.scatter_data_from(0) print("boundary", A.domain.boundary) t0 = time.time() phi_py = fmm(A.P, A.Q, forces=A.F, execute_async=ASYNC) t1 = time.time() if MPIRANK == 0 and DEBUG: print("\n") #print(60*"-") #opt.print_profile() #print(60*"-") print("TIME FMM:\t", t1 - t0) print("ENERGY FMM:\t", phi_py) A.gather_data_on(0) if MPIRANK == 0: for px in range(N): print("PX:", px) print("\t\tFORCE FMM:", A.F[px, :]) fmm.free()
def test_fmm_force_direct_3(): R = 3 L = 12 free_space = True N = 2 E = 4. rc = E / 4 A = state.State() A.domain = domain.BaseDomainHalo(extent=(E, E, E)) A.domain.boundary_condition = domain.BoundaryTypePeriodic() ASYNC = False DIRECT = True if MPISIZE == 1 else False DIRECT = True EWALD = True fmm = PyFMM(domain=A.domain, r=R, eps=None, l=L, free_space=free_space) A.npart = N rng = np.random.RandomState(seed=1234) A.P = data.PositionDat(ncomp=3) A.F = data.ParticleDat(ncomp=3) A.FE = data.ParticleDat(ncomp=3) A.Q = data.ParticleDat(ncomp=1) A.crr = data.ScalarArray(ncomp=1) A.cri = data.ScalarArray(ncomp=1) A.crs = data.ScalarArray(ncomp=1) if N == 2: eps = 0.00 epsx = 0 epsy = 0 epsz = 0 A.P[0, :] = (-0.0001, 0.0001, 1.0001) A.P[1, :] = (-0.0001, 0.0001, -0.0001) A.Q[0, 0] = 1. A.Q[1, 0] = 1. A.scatter_data_from(0) t0 = time.time() #phi_py = fmm._test_call(A.P, A.Q, execute_async=ASYNC) phi_py = fmm(A.P, A.Q, forces=A.F, execute_async=ASYNC) t1 = time.time() direct_forces = np.zeros((N, 3)) if DIRECT: #print("WARNING 0-th PARTICLE ONLY") phi_direct = 0.0 # compute phi from image and surrounding 26 cells for ix in range(N): phi_part = 0.0 for jx in range(ix + 1, N): rij = np.linalg.norm(A.P[jx, :] - A.P[ix, :]) phi_direct += A.Q[ix, 0] * A.Q[jx, 0] / rij phi_part += A.Q[ix, 0] * A.Q[jx, 0] / rij direct_forces[ix,:] -= A.Q[ix, 0] * A.Q[jx, 0] * \ (A.P[jx,:] - A.P[ix,:]) / (rij**3.) direct_forces[jx,:] += A.Q[ix, 0] * A.Q[jx, 0] * \ (A.P[jx,:] - A.P[ix,:]) / (rij**3.) if free_space == '27': for ofx in cube_offsets: cube_mid = np.array(ofx) * E for jx in range(N): rij = np.linalg.norm(A.P[jx, :] + cube_mid - A.P[ix, :]) phi_direct += 0.5 * A.Q[ix, 0] * A.Q[jx, 0] / rij phi_part += 0.5 * A.Q[ix, 0] * A.Q[jx, 0] / rij direct_forces[ix,:] -= A.Q[ix, 0] * A.Q[jx, 0] * \ (A.P[jx,:] - A.P[ix,:] + cube_mid) \ / (rij**3.) local_err = abs(phi_py - phi_direct) if local_err > eps: serr = red(local_err) else: serr = green(local_err) if MPIRANK == 0 and DEBUG: print("\n") #print(60*"-") #opt.print_profile() #print(60*"-") print("TIME FMM:\t", t1 - t0) print("ENERGY DIRECT:\t{:.20f}".format(phi_direct)) print("ENERGY FMM:\t", phi_py) print("ERR:\t\t", serr) for px in range(N): cell = A._fmm_cell[px, 0] stride = fmm.tree_plain[0].shape[-1] ss = fmm.tree_plain[R - 1].shape[0:3:] cx = cell % ss[2] cy = ((cell - cx) // ss[2]) % ss[1] cz = (((cell - cx) // ss[2]) - cy) // ss[1] mom = fmm.tree_plain[fmm.R - 1][cz, cy, cx, :] mid = (0.5 * E / 2.** (R - 1)) * np.ones(3) + (E / 2.**(R - 1)) * np.array( (cx, cy, cz)) - 0.5 * E * np.ones(3) disp_cart = A.P[px, :] - mid disp = spherical(disp_cart) print(cell, "|", cx, cy, cz, "|", mid) fpy = force_from_multipole(mom, fmm, disp.reshape(1, 3), A.Q[px, 0]) err_re_c = red_tol( np.linalg.norm(direct_forces[px, :] - A.F[px, :], ord=np.inf), 10.**-6) err_re_p = red_tol( np.linalg.norm(direct_forces[px, :] - fpy, ord=np.inf), 10.**-6) print("PX:", px) print("\t\tFORCE DIR :", direct_forces[px, :]) print("\t\tFORCE FMMC:", A.F[px, :], err_re_c) print("\t\tFORCE py :", fpy, err_re_p) fmm.free()
def test_fmm_force_ewald_1(): R = 3 eps = 10.**-8 free_space = False N = 32 E = 4. #N = 10000 #E = 100. rc = E / 8 A = state.State() A.domain = domain.BaseDomainHalo(extent=(E, E, E)) A.domain.boundary_condition = domain.BoundaryTypePeriodic() ASYNC = False CUDA = False fmm = PyFMM(domain=A.domain, r=R, l=22, free_space=free_space, cuda=CUDA) A.npart = N rng = np.random.RandomState(seed=1234) rng = np.random.RandomState(seed=95235) A.P = data.PositionDat(ncomp=3) A.F = data.ParticleDat(ncomp=3) A.FE = data.ParticleDat(ncomp=3) A.Q = data.ParticleDat(ncomp=1) A.crr = data.ScalarArray(ncomp=1) A.cri = data.ScalarArray(ncomp=1) A.crs = data.ScalarArray(ncomp=1) if N == 4: ra = 0.25 * E nra = -0.25 * E A.P[0, :] = (0.21, 0.21, 0.00) A.P[1, :] = (-0.21, 0.21, 0.00) A.P[2, :] = (-0.21, -0.21, 0.00) A.P[3, :] = (0.21, -0.21, 0.00) #A.P[0,:] = ( 0.00, 0.21, 0.21) #A.P[1,:] = ( 0.00, 0.21,-0.21) #A.P[2,:] = ( 0.00, -0.21,-0.21) #A.P[3,:] = ( 0.00, -0.21, 0.21) #A.P[0,:] = ( 1.01, 1.01, 0.00) #A.P[1,:] = (-1.01, 1.01, 0.00) #A.P[2,:] = (-1.01, -1.01, 0.00) #A.P[3,:] = ( 1.01, -1.01, 0.00) A.Q[0, 0] = -1. A.Q[1, 0] = 1. A.Q[2, 0] = -1. A.Q[3, 0] = 1. elif N == 1: A.P[0, :] = (0.25 * E, 0.25 * E, 0.25 * E) A.P[0, :] = (10.**-6, 10.**-6, 10.**-6) #A.P[0,:] = (0, -0.25*E, 0) #A.P[1,:] = (0, 0.25*E, 0) #A.P[0,:] = (0, 0, -0.25*E) #A.P[1,:] = (0, 0, 0.25*E) #A.Q[:,0] = 1. A.Q[0, 0] = 1. elif N == 2: #A.P[0,:] = ( 0.25*E, 0.25*E, 0.25*E) #A.P[1,:] = ( -0.25*E, -0.25*E, 0) #A.P[0,:] = (0, -0.25*E, 0) #A.P[1,:] = (0, 0.25*E, 0) #A.P[0,:] = (0, 0, -0.25*E) #A.P[1,:] = (0, 0, 0.25*E) #A.Q[:,0] = 1. ra = 0.25 * E nra = -0.25 * E epsx = 0 epsy = 0 epsz = 0 A.P[0, :] = (0.001, 0.001, 1.001) A.P[1, :] = (0.001, 0.001, -1.001) #A.P[:2:,:] = rng.uniform(low=-0.4999*E, high=0.4999*E, size=(N,3)) A.Q[0, 0] = -1. A.Q[1, 0] = 1. elif N == 8: for px in range(8): phi = (float(px) / 8) * 2. * math.pi pxr = 0.25 * E pxx = pxr * math.cos(phi) pxy = pxr * math.sin(phi) A.P[px, :] = (pxx, pxy, 0) A.Q[px, 0] = 1. - 2. * (px % 2) #A.Q[px, 0] = -1. #A.P[0,:] += eps #A.P[0:N:2,0] += eps #A.P[0,0] -= eps A.P[4, 0] -= eps A.P[:, 2] -= 0.200 A.P[:, 1] -= 0.200 #A.Q[0,0] = 0. A.Q[1, 0] = 0. A.Q[4, 0] = 0. A.Q[3, 0] = 0. A.Q[5, 0] = 0. A.Q[6, 0] = 0. A.Q[7, 0] = 0. else: assert N % 2 == 0 for px in range(N // 2): pos = rng.uniform(low=-0.4999 * E, high=0.4999 * E, size=(1, 3)) cha = rng.uniform(low=-1., high=1.) A.P[px, :] = pos A.Q[px, 0] = cha A.P[-1 * (px + 1), :] = -1.0 * pos A.Q[-1 * (px + 1), 0] = cha bias = np.sum(A.Q[:]) A.Q[:, 0] -= bias / N dipole = np.zeros(3) for px in range(N): dipole[:] += A.P[px, :] * A.Q[px, 0] bias = np.sum(A.Q[:]) Q = np.sum(np.abs(A.Q[:N:, 0])) A.scatter_data_from(0) t0 = time.time() phi_py = fmm(A.P, A.Q, forces=A.F, execute_async=ASYNC) t1 = time.time() ewald = EwaldOrthoganalHalf(domain=A.domain, real_cutoff=rc, eps=eps, shared_memory=SHARED_MEMORY) t2 = time.time() ewald.evaluate_contributions(positions=A.P, charges=A.Q) A.cri[0] = 0.0 ewald.extract_forces_energy_reciprocal(A.P, A.Q, A.FE, A.cri) A.crr[0] = 0.0 ewald.extract_forces_energy_real(A.P, A.Q, A.FE, A.crr) A.crs[0] = 0.0 ewald.evaluate_self_interactions(A.Q, A.crs) t3 = time.time() phi_ewald = A.cri[0] + A.crr[0] + A.crs[0] local_err = abs(phi_py - phi_ewald) / Q if local_err > eps: serr = red(local_err) else: serr = green(local_err) for px in range(A.npart_local): assert np.linalg.norm(A.FE[px, :] - A.F[px, :], ord=np.inf) < 10.**-6 if MPIRANK == 0 and DEBUG: print("\n") #print(60*"-") #opt.print_profile() #print(60*"-") print("TIME EWALD:\t", t3 - t2) print("TIME FMM:\t", t1 - t0) print("ENERGY EWALD:\t{:.20f}".format(phi_ewald)) print("ENERGY FMM:\t", phi_py) print("ERR:\t\t", serr) # run the same again A.F[:] = 0.0 t0 = time.time() phi_py = fmm(A.P, A.Q, forces=A.F, execute_async=ASYNC) t1 = time.time() local_err = abs(phi_py - phi_ewald) / Q if local_err > eps: serr = red(local_err) else: serr = green(local_err) A.gather_data_on(0) if MPIRANK == 0: for px in range(N): err_re_c = red_tol( np.linalg.norm(A.FE[px, :] - A.F[px, :], ord=np.inf), 10.**-6) assert np.linalg.norm(A.FE[px, :] - A.F[px, :], ord=np.inf) < 10.**-6 if MPIRANK == 0 and DEBUG: print("TIME FMM:\t", t1 - t0) print("ENERGY FMM:\t", phi_py) print("ERR:\t\t", serr) fmm.free()
def test_fmm_force_direct_1(): R = 3 eps = 10.**-6 free_space = '27' N = 4 E = 4. rc = E / 4 A = state.State() A.domain = domain.BaseDomainHalo(extent=(E, E, E)) A.domain.boundary_condition = domain.BoundaryTypePeriodic() ASYNC = False DIRECT = True if MPISIZE == 1 else False DIRECT = True EWALD = True fmm = PyFMM(domain=A.domain, r=R, eps=eps, free_space=free_space) A.npart = N rng = np.random.RandomState(seed=1234) A.P = data.PositionDat(ncomp=3) A.F = data.ParticleDat(ncomp=3) A.FE = data.ParticleDat(ncomp=3) A.Q = data.ParticleDat(ncomp=1) A.crr = data.ScalarArray(ncomp=1) A.cri = data.ScalarArray(ncomp=1) A.crs = data.ScalarArray(ncomp=1) if N == 4: ra = 0.25 * E nra = -0.25 * E A.P[0, :] = (1.01, 1.01, 0.0) A.P[1, :] = (-1.01, 1.01, 0.0) A.P[2, :] = (-1.01, -1.01, 0.0) A.P[3, :] = (1.01, -1.01, 0.0) A.Q[0, 0] = -1. A.Q[1, 0] = 1. A.Q[2, 0] = -1. A.Q[3, 0] = 1. elif N == 1: A.P[0, :] = (0.25 * E, 0.25 * E, 0.25 * E) A.P[0, :] = (10.**-6, 10.**-6, 10.**-6) #A.P[0,:] = (0, -0.25*E, 0) #A.P[1,:] = (0, 0.25*E, 0) #A.P[0,:] = (0, 0, -0.25*E) #A.P[1,:] = (0, 0, 0.25*E) #A.Q[:,0] = 1. A.Q[0, 0] = 1. elif N == 2: #A.P[0,:] = ( 0.25*E, 0.25*E, 0.25*E) #A.P[1,:] = ( -0.25*E, -0.25*E, 0) #A.P[0,:] = (0, -0.25*E, 0) #A.P[1,:] = (0, 0.25*E, 0) #A.P[0,:] = (0, 0, -0.25*E) #A.P[1,:] = (0, 0, 0.25*E) #A.Q[:,0] = 1. ra = 0.25 * E nra = -0.25 * E eps = 0.00 epsx = 0 epsy = 0 epsz = 0 A.P[0, :] = (1.000, 0.001, 0.001) A.P[1, :] = (-1.001, 0.001, 0.001) #A.P[:2:,:] = rng.uniform(low=-0.4999*E, high=0.4999*E, size=(N,3)) A.Q[0, 0] = -1. A.Q[1, 0] = 1. elif N == 8: for px in range(8): phi = (float(px) / 8) * 2. * math.pi pxr = 0.25 * E pxx = pxr * math.cos(phi) pxy = pxr * math.sin(phi) A.P[px, :] = (pxx, pxy, 0) A.Q[px, 0] = 1. - 2. * (px % 2) #A.Q[px, 0] = -1. #A.P[0,:] += eps eps = 0.00001 #A.P[0:N:2,0] += eps #A.P[0,0] -= eps A.P[4, 0] -= eps A.P[:, 2] -= 0.200 A.P[:, 1] -= 0.200 #A.Q[0,0] = 0. A.Q[1, 0] = 0. A.Q[4, 0] = 0. A.Q[3, 0] = 0. A.Q[5, 0] = 0. A.Q[6, 0] = 0. A.Q[7, 0] = 0. else: assert N % 2 == 0 for px in range(N // 2): pos = rng.uniform(low=-0.4999 * E, high=0.4999 * E, size=(1, 3)) cha = rng.uniform(low=-1., high=1.) A.P[px, :] = pos A.Q[px, 0] = cha A.P[-1 * (px + 1), :] = -1.0 * pos A.Q[-1 * (px + 1), 0] = cha bias = np.sum(A.Q[:]) A.Q[:, 0] -= bias / N dipole = np.zeros(3) for px in range(N): dipole[:] += A.P[px, :] * A.Q[px, 0] bias = np.sum(A.Q[:]) print("DIPOLE:\t", dipole, "TOTAL CHARGE:\t", bias) A.scatter_data_from(0) t0 = time.time() #phi_py = fmm._test_call(A.P, A.Q, execute_async=ASYNC) phi_py = fmm(A.P, A.Q, forces=A.F, execute_async=ASYNC) t1 = time.time() direct_forces = np.zeros((N, 3)) if DIRECT: #print("WARNING 0-th PARTICLE ONLY") phi_direct = 0.0 # compute phi from image and surrounding 26 cells for ix in range(N): phi_part = 0.0 for jx in range(ix + 1, N): rij = np.linalg.norm(A.P[jx, :] - A.P[ix, :]) phi_direct += A.Q[ix, 0] * A.Q[jx, 0] / rij phi_part += A.Q[ix, 0] * A.Q[jx, 0] / rij direct_forces[ix,:] -= A.Q[ix, 0] * A.Q[jx, 0] * \ (A.P[jx,:] - A.P[ix,:]) / (rij**3.) direct_forces[jx,:] += A.Q[ix, 0] * A.Q[jx, 0] * \ (A.P[jx,:] - A.P[ix,:]) / (rij**3.) if free_space == '27': for ofx in cube_offsets: cube_mid = np.array(ofx) * E for jx in range(N): rij = np.linalg.norm(A.P[jx, :] + cube_mid - A.P[ix, :]) phi_direct += 0.5 * A.Q[ix, 0] * A.Q[jx, 0] / rij phi_part += 0.5 * A.Q[ix, 0] * A.Q[jx, 0] / rij direct_forces[ix,:] -= A.Q[ix, 0] * A.Q[jx, 0] * \ (A.P[jx,:] - A.P[ix,:] + cube_mid) \ / (rij**3.) local_err = abs(phi_py - phi_direct) if local_err > eps: serr = red(local_err) else: serr = green(local_err) if MPIRANK == 0 and DEBUG: print("\n") #print(60*"-") #opt.print_profile() #print(60*"-") print("TIME FMM:\t", t1 - t0) print("ENERGY DIRECT:\t{:.20f}".format(phi_direct)) print("ENERGY FMM:\t", phi_py) print("ERR:\t\t", serr) for px in range(N): err_re_c = red_tol( np.linalg.norm(direct_forces[px, :] - A.F[px, :], ord=np.inf), 10.**-6) print("PX:", px) print("\t\tFORCE DIR :", direct_forces[px, :]) print("\t\tFORCE FMMC:", A.F[px, :], err_re_c) fmm.free()
def test_fmm_sim_1(): input_data = np.load(get_res_file_path('coulomb/CO2cuboid.npy')) N = input_data.shape[0] E = 50. A = state.State() A.npart = N A.domain = domain.BaseDomainHalo(extent=(E, E, E)) A.domain.boundary_condition = domain.BoundaryTypePeriodic() eps = 10.**-6 fmm = PyFMM(domain=A.domain, r=3, N=N, eps=eps, free_space=True) A.P = data.PositionDat(ncomp=3) A.Q = data.ParticleDat(ncomp=1) if MPIRANK == 0: A.P[:] = input_data[:, 0:3:] A.Q[:, 0] = input_data[:, 3] A.scatter_data_from(0) if MPISIZE == 1: # compute potential energy to point across all charges directly P2 = data.PositionDat(npart=N, ncomp=3) Q2 = data.ParticleDat(npart=N, ncomp=1) P2[:, :] = A.P[:N:, :] Q2[:, :] = A.Q[:N:, :] phi_ga = data.ScalarArray(ncomp=1, dtype=ctypes.c_double) src = """ const double d0 = P.j[0] - P.i[0]; const double d1 = P.j[1] - P.i[1]; const double d2 = P.j[2] - P.i[2]; phi[0] += 0.5 * Q.i[0] * Q.j[0] / sqrt(d0*d0 + d1*d1 + d2*d2); """ phi_kernel = kernel.Kernel('all_to_all_phi', src, headers=(kernel.Header('math.h'), )) phi_loop = pairloop.AllToAllNS(kernel=phi_kernel, dat_dict={ 'P': P2(access.READ), 'Q': Q2(access.READ), 'phi': phi_ga(access.INC_ZERO) }) phi_loop.execute() phi_direct = phi_ga[0] else: phi_direct = None t0 = time.time() phi_fmm = fmm(A.P, A.Q) t1 = time.time() if DEBUG and MPIRANK == 0: print("Time:", t1 - t0) print("MPISIZE", MPISIZE) print("phi_fmm", phi_fmm) if MPISIZE == 1: print("phi_direct: {:.30f}".format(phi_direct)) print("phi_fmm", phi_fmm) print("ERROR:", abs(phi_direct - phi_fmm)) fmm.free()
def test_fmm_init_2_1(): E = 20. A = state.State() A.domain = domain.BaseDomainHalo(extent=(E, E, E)) A.domain.boundary_condition = domain.BoundaryTypePeriodic() eps = 10.**-3 fmm = PyFMM(domain=A.domain, r=3, eps=eps, free_space=True) ncubeside = 2**(fmm.R - 1) N = ncubeside**3 N = 100 A.npart = N rng = np.random.RandomState(seed=1234) #rng = np.random A.P = data.PositionDat(ncomp=3) A.Q = data.ParticleDat(ncomp=1) A.U = data.ParticleDat(ncomp=1) A.F = data.ParticleDat(ncomp=3) A.P[:] = rng.uniform(low=-0.5 * E, high=0.5 * E, size=(N, 3)) A.Q[:] = rng.uniform(low=-0.5 * E, high=0.5 * E, size=(N, 1)) bias = np.sum(A.Q[:]) / N A.Q[:] -= bias #A.Q[:] = 1.0 #A.Q[0:-2] = 0.0 #A.P[2,:] = (-7.5, -7.5, 2.5) #A.Q[2, 0] = -1. #A.P[0,:] = (-6., 2., -1.) #A.P[1,:] = (5.000000001, 5.000000001, -4.5) #A.Q[0, 0] = 1.0 #A.Q[1, 0] = -1.0 A.scatter_data_from(0) maxt = 5 for tx in itertools.product(range(-1 * maxt, maxt + 1), range(-1 * maxt, maxt + 1), range(-1 * maxt, maxt + 1)): dispt = (tx[0] * E, tx[1] * E, tx[2] * E) dispt_sph = spherical(dispt) dispt_fmm = fmm._image_to_sph(tx) assert abs(dispt_sph[0] - dispt_fmm[0]) < 10.**-16, "bad radius" assert abs(dispt_sph[2] - dispt_fmm[1]) < 10.**-16, "bad phi" assert abs(dispt_sph[1] - dispt_fmm[2]) < 10.**-16, "bad theta" fmm._check_aux_dat(A.P) fmm._compute_cube_contrib(A.P, A.Q, A._fmm_cell) # compute potential energy to point across all charges directly P2 = data.PositionDat(npart=N, ncomp=3) Q2 = data.ParticleDat(npart=N, ncomp=1) U2 = data.ParticleDat(npart=N, ncomp=1) P2[:, :] = A.P[:N:, :] Q2[:, :] = A.Q[:N:, :] phi_ga = data.ScalarArray(ncomp=1, dtype=ctypes.c_double) src = """ const double d0 = P.j[0] - P.i[0]; const double d1 = P.j[1] - P.i[1]; const double d2 = P.j[2] - P.i[2]; const double contrib = Q.i[0] * Q.j[0] / sqrt(d0*d0 + d1*d1 + d2*d2); phi[0] += 0.5 * contrib; U.i[0] += contrib; """ phi_kernel = kernel.Kernel('all_to_all_phi', src, headers=(kernel.Header('math.h'), )) phi_loop = pairloop.AllToAllNS(kernel=phi_kernel, dat_dict={ 'P': P2(access.READ), 'Q': Q2(access.READ), 'phi': phi_ga(access.INC_ZERO), 'U': U2(access.INC_ZERO) }) phi_loop.execute() if DEBUG: phi_py = 0.0 for ix in range(N): for jx in range(ix + 1, N): r2 = np.linalg.norm(A.P[jx, :] - A.P[ix, :]) phi_py += A.Q[ix, 0] * A.Q[jx, 0] / r2 print("Direct", phi_ga[0], phi_py) extent = A.domain.extent cube_ilen = 2**(fmm.R - 1) / extent[:] cube_half_len = 0.5 * extent[:] / (2**(fmm.R - 1)) shift_pos = A.P[:] + 0.5 * extent[:] shift_pos[:, 0] = shift_pos[:, 0] * cube_ilen[0] shift_pos[:, 1] = shift_pos[:, 1] * cube_ilen[1] shift_pos[:, 2] = shift_pos[:, 2] * cube_ilen[2] shift_pos = np.array(shift_pos, dtype='int') phi_local = fmm._compute_local_interaction(A.P, A.Q) #print("phi_local:", phi_local) #print("------------------------------------------------") phi_local_pair = fmm._compute_local_interaction_pairloop(A.P, A.Q) #print("correct :", phi_local) assert abs(phi_local - phi_local_pair) < 10.**-12 level = fmm.R - 1 phi_sph_re = 0.0 phi_sph_im = 0.0 lsize = fmm.tree_plain[level][:, :, :, 0].shape sep = A.domain.extent[0] / float(2.**level) start_point = -0.5 * E + 0.5 * sep for px in range(N): point = A.P[px, :] charge = A.Q[px, 0] if DEBUG: print(px, point, charge, shift_pos[px, :]) cubex = shift_pos[px, :] for momx in itertools.product(range(lsize[0]), range(lsize[1]), range(lsize[2])): dist = ((momx[2] - cubex[0])**2 + (momx[1] - cubex[1])**2 + (momx[0] - cubex[2])**2) if dist > 3: center = np.array((start_point + (momx[2]) * sep, start_point + (momx[1]) * sep, start_point + (momx[0]) * sep)) disp = point - center moments = fmm.tree_halo[level][momx[0] + 2, momx[1] + 2, momx[2] + 2, :] disp_sph = spherical(np.reshape(disp, (1, 3))) phi_sph_re1, phi_sph_im1 = compute_phi(fmm.L, moments, disp_sph) phi_sph_re += phi_sph_re1 * charge * 0.5 phi_sph_im += phi_sph_im1 * charge * 0.5 if DEBUG: print("direct:", phi_ga[0]) print("multipole:", phi_sph_re + phi_local, "local:", phi_local, "expansions:", phi_sph_re) assert abs(phi_ga[0] - phi_sph_re - phi_local) < eps, "bad real part" phi_py2 = fmm(A.P, A.Q, forces=A.F, potential=A.U) for px in range(A.npart_local): assert abs(U2[px, 0] - A.U[px, 0]) < eps fmm.free()
def _direct(): _phi_direct = fmm(positions=B.P, charges=B.Q) return _phi_direct