def test_saving_loading_and_sphere(self): # domain physical_sizes (edge length of square) length = 8 + 4 * rand() R = 17 + 6 * rand() # sphere radius res = 2 # nb_grid_pts x_c = length * rand() # coordinates of center y_c = length * rand() x = np.arange(res, dtype=float) * length / res - x_c y = np.arange(res, dtype=float) * length / res - y_c r2 = np.zeros((res, res)) for i in range(res): for j in range(res): r2[i, j] = x[i] ** 2 + y[j] ** 2 h = np.sqrt(R ** 2 - r2) - R # profile of sphere S1 = Topography(h, h.shape) with tmp_dir() as dir: fname = os.path.join(dir, "surface") S1.to_matrix(fname) S2 = read_matrix(fname) self.assertTrue(np.allclose(S2.heights(), S1.heights())) S3 = make_sphere(R, (res, res), (length, length), (x_c, y_c)) self.assertTrue(np.array_equal(S1.heights(), S2.heights())) self.assertTrue(np.array_equal(S1.heights(), S3.heights()))
def test_saving_loading_and_sphere(self): # domain physical_sizes (edge length of square) length = 8 + 4 * rand() R = 17 + 6 * rand() # sphere radius res = 2 # nb_grid_pts x_c = length * rand() # coordinates of center y_c = length * rand() x = np.arange(res, dtype=float) * length / res - x_c y = np.arange(res, dtype=float) * length / res - y_c r2 = np.zeros((res, res)) for i in range(res): for j in range(res): r2[i, j] = x[i]**2 + y[j]**2 h = np.sqrt(R**2 - r2) - R # profile of sphere S1 = Topography(h, h.shape) with tmp_dir() as dir: fname = os.path.join(dir, "surface") S1.save(fname) # TODO: datafiles fixture may solve the problem # For some reason, this does not find the file... # S2 = read_asc(fname) S2 = S1 S3 = make_sphere(R, (res, res), (length, length), (x_c, y_c)) self.assertTrue(np.array_equal(S1.heights(), S2.heights())) self.assertTrue(np.array_equal(S1.heights(), S3.heights()))
def test_primal_hessian(s): nx = 64 ny = 32 sx = sy = s R = 10. Es = 50. substrate = Solid.PeriodicFFTElasticHalfSpace((nx, ny), young=Es, physical_sizes=(sx, sy)) topography = make_sphere(R, (nx, ny), (sx, sy), kind="paraboloid") system = NonSmoothContactSystem(substrate=substrate, surface=topography) obj = system.primal_objective(0, True, True) gaps = np.random.random(size=(nx, ny)) dgaps = np.random.random(size=(nx, ny)) _, grad = obj(gaps.reshape(-1)) h = 1. _, grad_d = obj((gaps + h * dgaps).reshape(-1)) dgrad = grad_d - grad dgrad_from_hess = system.primal_hessian_product((h * dgaps).reshape(-1)) np.testing.assert_allclose(dgrad_from_hess, dgrad)
def test_sphere_standoff(comm): nx = 33 ny = 11 sx = 6. sy = 7. R = 2. center = (3., 3.) standoff = 10. fftengine = FFT((nx, ny), fft="mpi", communicator=comm) topography = make_sphere( R, (nx, ny), (sx, sy), centre=center, nb_subdomain_grid_pts=fftengine.nb_subdomain_grid_pts, subdomain_locations=fftengine.subdomain_locations, communicator=comm, standoff=standoff) X, Y, Z = topography.positions_and_heights() sl_inner = (X - center[0])**2 + (Y - center[1])**2 < R**2 np.testing.assert_allclose( ((X - center[0])**2 + (Y - center[1])**2 + (R + Z)**2)[sl_inner], R**2) np.testing.assert_allclose(Z[np.logical_not(sl_inner)], -R - standoff)
def test_uniform_curvatures_1d(self): radius = 100. surface = make_sphere(radius, (13, ), (6., ), kind="paraboloid") detrended = surface.detrend(detrend_mode="curvature") if False: import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.contour(*surface.positions_and_heights()) ax.set_aspect(1) plt.show(block=True) self.assertAlmostEqual(abs(detrended.curvatures[0]), 1 / radius)
def test_primal_obj(s): nx, ny = 256, 256 sx = sy = s R = 10. surface = make_sphere(R, (nx, ny), (sx, sy), kind="paraboloid") Es = 50. substrate = Solid.PeriodicFFTElasticHalfSpace((nx, ny), young=Es, physical_sizes=(sx, sy)) system = Solid.Systems.NonSmoothContactSystem(substrate, surface) offset = 0.005 lbounds = np.zeros((nx, ny)) bnds = system._reshape_bounds(lbounds, ) init_gap = np.zeros((nx, ny)) # .flatten() disp = init_gap + surface.heights() + offset res = optim.minimize(system.primal_objective(offset, gradient=True), disp, method='L-BFGS-B', jac=True, bounds=bnds, options=dict(gtol=1e-8, ftol=1e-20)) assert res.success _lbfgsb = res.x.reshape((nx, ny)) res = system.minimize_proxy(offset=offset, pentol=1e-7) assert res.success _ccg = system.compute_gap(res.x, offset) # fig, (axg, axpl, axpc) = plt.subplots(3, 1) # # plt.colorbar(axpl.pcolormesh(_lbfgsb)) # plt.colorbar(axpc.pcolormesh(_ccg)) # axg.plot(system.surface.positions()[0][:,0], _lbfgsb[:,ny//2],'x', # label='lbfgsb' ) # axg.plot(system.surface.positions()[0][:,0], _ccg[:, ny // 2], '+', # label='ccg') # axg.legend() # plt.show() # fig.tight_layout() np.testing.assert_allclose(_lbfgsb, _ccg, atol=1e-6)
def test_sphere(comm): nx = 33 ny = 11 sx = 6. sy = 7. R = 20. center = (3., 3.) fftengine = FFT((nx, ny), fft="mpi", communicator=comm) print(fftengine.nb_subdomain_grid_pts) topography = make_sphere( R, (nx, ny), (sx, sy), centre=center, nb_subdomain_grid_pts=fftengine.nb_subdomain_grid_pts, subdomain_locations=fftengine.subdomain_locations, communicator=comm) X, Y, Z = topography.positions_and_heights() np.testing.assert_allclose( (X - center[0])**2 + (Y - center[1])**2 + (R + Z)**2, R**2)
def test_dual_obj(s): nx, ny = 128, 128 sx = sy = s R = 10. surface = make_sphere(R, (nx, ny), (sx, sy), kind="paraboloid") Es = 50. substrate = Solid.PeriodicFFTElasticHalfSpace((nx, ny), young=Es, physical_sizes=(sx, sy)) system = Solid.Systems.NonSmoothContactSystem(substrate, surface) offset = 0.005 lbounds = np.zeros((nx, ny)) bnds = system._reshape_bounds(lbounds, ) init_gap = np.zeros((nx, ny)) disp = init_gap + surface.heights() + offset init_pressure = substrate.evaluate_force(disp) res = optim.minimize(system.dual_objective(offset, gradient=True), init_pressure, method='L-BFGS-B', jac=True, bounds=bnds, options=dict(gtol=1e-6 * system.area_per_pt, ftol=1e-20)) assert res.success, res.message CA_lbfgsb = res.x.reshape((nx, ny)) > 0 # Contact area fun = system.dual_objective(offset, gradient=True) gap_lbfgsb = fun(res.x)[1] gap_lbfgsb = gap_lbfgsb.reshape((nx, ny)) res = system.minimize_proxy(offset=offset, pentol=1e-8) assert res.success, res.message CA_ccg = res.jac > 0 # Contact area # print("shape of disp_ccg {}".format(np.shape(res.x))) gap_ccg = system.compute_gap(res.x, offset) np.testing.assert_allclose(CA_lbfgsb, CA_ccg, 1e-8) np.testing.assert_allclose(gap_lbfgsb, gap_ccg, atol=1e-8)
def test_sphere_periodic(comm): nx = 33 ny = 11 sx = 6. sy = 7. R = 20. center = (1., 1.5) fftengine = FFT((nx, ny), fft="mpi", communicator=comm) extended_topography = make_sphere( R, (nx, ny), (sx, sy), centre=center, nb_subdomain_grid_pts=fftengine.nb_subdomain_grid_pts, subdomain_locations=fftengine.subdomain_locations, communicator=comm, periodic=True) X, Y, Z = extended_topography.positions_and_heights() np.testing.assert_allclose( (X - np.where(X < center[0] + sx / 2, center[0], center[0] + sx))**2 + (Y - np.where(Y < center[1] + sy / 2, center[1], center[1] + sy))**2 + (R + Z)**2, R**2)
def test_constrained_conjugate_gradients(nb_grid_pts, comm): # sphere radius: r_s = 20.0 # equivalent Young's modulus E_s = 102. nx, ny = nb_grid_pts for disp0, normal_force in [(0.1, None), (0, 15.0)]: sx = 5.0 substrate = FreeFFTElasticHalfSpace((nx, ny), E_s, (sx, sx), fft='mpi', communicator=comm) surface = make_sphere( r_s, (nx, ny), (sx, sx), nb_subdomain_grid_pts=substrate.topography_nb_subdomain_grid_pts, subdomain_locations=substrate.topography_subdomain_locations, communicator=substrate.communicator) system = NonSmoothContactSystem(substrate, surface) result = system.minimize_proxy(offset=disp0, external_force=normal_force) disp = result.x forces = -result.jac converged = result.success assert converged comp_normal_force = -Reduction(comm).sum(forces) if normal_force is not None: npt.assert_allclose( normal_force, comp_normal_force, rtol=1e-7, err_msg="Convergence Problem: resultant normal Force doesn't " "match imposed normal force") npt.assert_allclose( system.compute_normal_force(), normal_force, rtol=1e-7, err_msg="computed normal force doesn't match imposed force") # assert the disp is OK with analytical Solution # print("penetration: computed: {}" # " Hertz : {}".format(result.offset, # penetration(normal_force,r_s,E_s))) npt.assert_allclose( result.offset, Hz.penetration(normal_force, r_s, E_s), rtol=1e-2, err_msg="computed offset doesn't match with hertz theory for " "imposed Load {}".format(normal_force)) Eel_ref = Hz.elastic_energy(Hz.penetration(normal_force, r_s, E_s), r_s, E_s) elif disp0 is not None: Eel_ref = Hz.elastic_energy(disp0, r_s, E_s) npt.assert_allclose( disp0, result.offset, rtol=1e-7, err_msg="Convergence Problem: computed penetration doesn't " "match imposed penetration") npt.assert_allclose( comp_normal_force, Hz.normal_load(disp0, r_s, E_s), rtol=1e-2, err_msg="computed normal force doesn't match with hertz " "theory for imposed Penetration {}".format(disp0)) npt.assert_allclose( system.compute_normal_force(), Hz.normal_load(disp0, r_s, E_s), rtol=1e-2, err_msg="computed normal force doesn't match with hertz " "theory for imposed Penetration {}".format(disp0)) a, p0 = Hz.radius_and_pressure(comp_normal_force, r_s, E_s) npt.assert_allclose(system.compute_contact_area(), np.pi * a**2, rtol=1e-1, err_msg="Computed area doesn't match Hertz Theory") Eel_computed_kspace = \ system.substrate.evaluate(disp, pot=True, forces=False)[0] Eel_computed_rspace = \ system.substrate.evaluate(disp, pot=True, forces=True)[0] # print(Eel_computed_kspace, Eel_computed_rspace, Eel_ref) npt.assert_allclose(Eel_computed_kspace, Eel_ref, rtol=1e-2) npt.assert_allclose(Eel_computed_rspace, Eel_ref, rtol=1e-2) p_numerical = -forces * (nx * ny / (sx * sx)) p_analytical = np.zeros_like(p_numerical) if DEBUG: for i in range(substrate.fftengine.comm.Get_size()): substrate.fftengine.comm.barrier() if substrate.fftengine.comm.Get_rank() == i: print(i) print("subdom_res: %s" % substrate.nb_subdomain_grid_pts.__repr__()) print("shape p_numerical: %s" % p_numerical.shape.__repr__()) else: continue if np.prod(substrate.nb_subdomain_grid_pts) > 0: x = ((np.arange(nx) - nx / 2) * sx / nx) \ .reshape(-1, 1)[substrate.subdomain_slices[0], :] y = ((np.arange(ny) - ny / 2) * sx / ny) \ .reshape(1, -1)[:, substrate.subdomain_slices[1]] r = np.sqrt(x**2 + y**2) p_analytical[r < a] = p0 * np.sqrt(1 - (r[r < a] / a)**2) else: x = np.array([], dtype=p_analytical.dtype) y = np.array([], dtype=p_analytical.dtype) r = np.array([], dtype=p_analytical.dtype) # import matplotlib.pyplot as plt # plt.subplot(1,3,1) # plt.pcolormesh(p_analytical-p_numerical) # plt.colorbar() # plt.plot(x, np.sqrt(r_s**2-x**2)-(r_s-disp0)) # plt.subplot(1,3,2) # plt.pcolormesh(p_analytical) # plt.colorbar() # plt.subplot(1,3,3) # plt.pcolormesh(p_numerical) # plt.colorbar() # plt.show() msg = "" msg += "\np_numerical_type: {}".format(type(p_numerical)) msg += "\np_numerical_shape: {}".format(p_numerical.shape) msg += "\np_numerical_mean: {}".format( Reduction(comm).sum(p_numerical) / (nx * ny * 4)) msg += "\np_numerical_dtype: {}".format(p_numerical.dtype) msg += "\np_numerical_max: {}".format( Reduction(comm).max(p_numerical)) msg += "\np_analytical_max: {}".format( Reduction(comm).max(p_analytical)) msg += "\nslice_size: {}".format((r < .99 * a).sum()) msg += "\ncontact_radius a: {}".format(a) msg += "\ncomputed normal_force: {}".format(comp_normal_force) msg += "\n{}".format( Reduction(comm).max(result.jac) - Reduction(comm).min(result.jac)) if DEBUG: import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt fig, ax = plt.subplots(1, 3) plt.colorbar(ax[0].pcolormesh(p_analytical - p_numerical), ax=ax[0]) ax[0].set_title("difference") plt.colorbar(ax[1].pcolormesh(p_analytical), ax=ax[1]) ax[1].set_title("analytical") plt.colorbar(ax[2].pcolormesh(p_numerical), ax=ax[2]) ax[2].set_title("numerical") for ai in ax: ai.set_aspect("equal") # print(MPI.COMM_WORLD.Get_size()) fig.savefig("Hertz_plot_proc_%i.png" % Reduction(comm).comm.Get_rank()) try: assert Reduction(comm).max( np.abs(p_analytical[r < 0.99 * a] - p_numerical[r < 0.99 * a])) / E_s < 1e-3, msg # TODO: assert the Contact area is OK except ValueError as err: msg = str(err) + msg raise ValueError(msg)