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()))
Exemple #2
0
    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)
Exemple #5
0
    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)