def test_force_disp_reversibility(self):
        # since only the zero-frequency is rejected, any force/disp field with
        # zero mean should be fully reversible
        tol = 1e-10
        for res in ((self.res[0], ), self.res, (self.res[0] + 1, self.res[1]),
                    (self.res[0], self.res[1] + 1)):
            hs = PeriodicFFTElasticHalfSpace(res, self.young,
                                             self.physical_sizes)
            disp = random(res)
            disp -= disp.mean()

            error = Tools.mean_err(disp,
                                   hs.evaluate_disp(hs.evaluate_force(disp)))
            self.assertTrue(
                error < tol,
                "for nb_grid_pts = {}, error = {} > tol = {}".format(
                    res, error, tol))

            force = random(res)
            force -= force.mean()

            error = Tools.mean_err(force,
                                   hs.evaluate_force(hs.evaluate_disp(force)))
            self.assertTrue(
                error < tol,
                "for nb_grid_pts = {}, error = {} > tol = {}".format(
                    res, error, tol))
    def test_energy(self):
        tol = 1e-10
        L = 2 + rand()  # domain length
        a = 3 + rand()  # amplitude of force
        E = 4 + rand()  # Young's Mod
        for res in [4, 8, 16]:
            area_per_pt = L / res
            x = np.arange(res) * area_per_pt
            force = a * np.cos(2 * np.pi / L * x)

            # theoretical FFT of force
            Fforce = np.zeros_like(x)
            Fforce[1] = Fforce[-1] = res / 2. * a

            # theoretical FFT of disp
            Fdisp = np.zeros_like(x)
            Fdisp[1] = Fdisp[-1] = res / 2. * a / E * L / (np.pi)

            # verify consistency
            hs = PeriodicFFTElasticHalfSpace(res, E, L)
            fforce = rfftn(force.T).T
            fdisp = hs.greens_function * fforce
            self.assertTrue(
                Tools.mean_err(fforce, Fforce, rfft=True) < tol,
                "fforce = \n{},\nFforce = \n{}".format(fforce.real, Fforce))
            self.assertTrue(
                Tools.mean_err(fdisp, Fdisp, rfft=True) < tol,
                "fdisp = \n{},\nFdisp = \n{}".format(fdisp.real, Fdisp))

            # Fourier energy
            E = .5 * np.dot(Fforce / area_per_pt, Fdisp) / res

            disp = hs.evaluate_disp(force)
            e = hs.evaluate_elastic_energy(force, disp)
            kdisp = hs.evaluate_k_disp(force)
            self.assertTrue(
                abs(disp - irfftn(kdisp.T).T).sum() < tol,
                ("disp   = {}\n"
                 "ikdisp = {}").format(disp,
                                       irfftn(kdisp.T).T))
            ee = hs.evaluate_elastic_energy_k_space(fforce, kdisp)
            self.assertTrue(
                abs(e - ee) < tol,
                "violate Parseval: e = {}, ee = {}, ee/e = {}".format(
                    e, ee, ee / e))

            self.assertTrue(
                abs(E - e) < tol,
                "theoretical E = {}, computed e = {}, diff(tol) = {}({})".
                format(E, e, E - e, tol))
 def test_parabolic_shape_force(self):
     """ test whether the Elastic energy is a quadratic function of the
         applied force"""
     hs = PeriodicFFTElasticHalfSpace(self.res, self.young,
                                      self.physical_sizes)
     force = random(self.res)
     force -= force.mean()
     nb_tests = 4
     El = np.zeros(nb_tests)
     for i in range(nb_tests):
         disp = hs.evaluate_disp(i * force)
         El[i] = hs.evaluate_elastic_energy(i * force, disp)
     tol = 1e-10
     error = norm(El / El[1] - np.arange(nb_tests)**2)
     self.assertTrue(error < tol)
Beispiel #4
0
def test_sineWave_force(comm, pnp, nx, ny, basenpoints):
    """
    for  a given sinusoidal force, compares displacement with a reference
    solution

    Parameters
    ----------
    comm
    pnp
    fftengine_class
    nx
    ny
    basenpoints

    Returns
    -------

    """
    nx += basenpoints
    ny += basenpoints
    sx = 2  # 30.0
    sy = 1.0

    # equivalent Young's modulus
    E_s = 1.0

    Y, X = np.meshgrid(
        np.linspace(0, sy, ny + 1)[:-1],
        np.linspace(0, sx, nx + 1)[:-1])

    qx = 1 * np.pi * 2 / sx
    qy = 4 * np.pi * 2 / sy

    q = np.sqrt(qx**2 + qy**2)
    p = np.cos(qx * X + qy * Y)

    refdisp = -p / E_s * 2 / q

    substrate = PeriodicFFTElasticHalfSpace((nx, ny),
                                            E_s, (sx, sy),
                                            fft='mpi',
                                            communicator=comm)
    computeddisp = substrate.evaluate_disp(p[substrate.subdomain_slices] *
                                           substrate.area_per_pt)
    np.testing.assert_allclose(computeddisp,
                               refdisp[substrate.subdomain_slices],
                               atol=1e-7,
                               rtol=1e-10)
    def test_consistency(self):
        pressure = list()
        base_res = 128
        tol = 1e-4
        for i in (1, 2):
            s_res = base_res * i
            test_res = (s_res, s_res)
            hs = PeriodicFFTElasticHalfSpace(test_res, self.young,
                                             self.physical_sizes)
            forces = np.zeros(test_res)
            forces[:s_res // 2, :s_res // 2] = 1.

            pressure.append(
                hs.evaluate_disp(forces)[::i, ::i] * hs.area_per_pt)
        error = ((pressure[0] - pressure[1])**2).sum().sum() / base_res**2
        self.assertTrue(error < tol, "error = {}".format(error))