def test_unit_neutrality(self):
        tol = 1e-7
        # runs the same problem in two unit sets and checks whether results are
        # changed

        # Conversion factors
        length_c = 1. + np.random.rand()
        force_c = 1. + np.random.rand()
        pressure_c = force_c / length_c**2
        # energy_c = force_c * length_c

        # length_rc = (1., 1. / length_c)
        force_rc = (1., 1. / force_c)
        # pressure_rc = (1., 1. / pressure_c)
        # energy_rc = (1., 1. / energy_c)
        nb_grid_pts = (32, 32)
        young = (self.young, pressure_c * self.young)
        size = self.physical_sizes[0], 2 * self.physical_sizes[1]
        size = (size, tuple((length_c * s for s in size)))
        # print('SELF.SIZE = {}'.format(self.physical_sizes))

        disp = np.random.random(nb_grid_pts)
        disp -= disp.mean()
        disp = (disp, disp * length_c)

        forces = list()
        for i in range(2):
            sub = PeriodicFFTElasticHalfSpace(nb_grid_pts, young[i], size[i])
            force = sub.evaluate_force(disp[i])
            forces.append(force * force_rc[i])
        error = Tools.mean_err(forces[0], forces[1])
        self.assertTrue(error < tol,
                        "error = {} ≥ tol = {}".format(error, tol))
 def test_uniform_displacement(self):
     """ test whether uniform displacement returns stiffness_q0"""
     sq0 = 1.43
     hs = PeriodicFFTElasticHalfSpace(self.res,
                                      self.young,
                                      self.physical_sizes,
                                      stiffness_q0=sq0)
     force = hs.evaluate_force(-np.ones(self.res))
     self.assertAlmostEqual(force.sum() / np.prod(self.physical_sizes), sq0)
 def test_uniform_displacement_finite_height(self):
     """ test whether uniform displacement returns stiffness_q0"""
     h0 = 3.45
     hs = PeriodicFFTElasticHalfSpace(self.res,
                                      self.young,
                                      self.physical_sizes,
                                      thickness=h0,
                                      poisson=self.poisson)
     force = hs.evaluate_force(-np.ones(self.res))
     M = (1 - self.poisson) / ((1 - 2 * self.poisson) *
                               (1 + self.poisson)) * self.young
     self.assertAlmostEqual(force.sum() / np.prod(self.physical_sizes),
                            M / h0)
 def test_parabolic_shape_disp(self):
     """ test whether the Elastic energy is a quadratic function of the
         applied displacement"""
     hs = PeriodicFFTElasticHalfSpace(self.res, self.young,
                                      self.physical_sizes)
     disp = random(self.res)
     disp -= disp.mean()
     nb_tests = 4
     El = np.zeros(nb_tests)
     for i in range(nb_tests):
         force = hs.evaluate_force(i * disp)
         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)
예제 #5
0
def test_sineWave_disp(comm, pnp, nx, ny, basenpoints):
    """
    for given sinusoidal displacements, compares the pressures and the energies
    to the analytical solutions

    Special cases at the edges of the fourier domain are done

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

    Returns
    -------

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

    # equivalent Young's modulus
    E_s = 1.0

    for k in [(1, 0), (0, 1), (1, 2), (nx // 2, 0), (1, ny // 2), (0, 2),
              (nx // 2, ny // 2), (0, ny // 2)]:
        # print("testing wavevector ({}* np.pi * 2 / sx,
        # {}* np.pi * 2 / sy) ".format(*k))
        qx = k[0] * np.pi * 2 / sx
        qy = k[1] * np.pi * 2 / sy
        q = np.sqrt(qx**2 + qy**2)

        Y, X = np.meshgrid(
            np.linspace(0, sy, ny + 1)[:-1],
            np.linspace(0, sx, nx + 1)[:-1])
        disp = np.cos(qx * X + qy * Y) + np.sin(qx * X + qy * Y)

        refpressure = -disp * E_s / 2 * q

        substrate = PeriodicFFTElasticHalfSpace((nx, ny),
                                                E_s, (sx, sy),
                                                fft='mpi',
                                                communicator=comm)
        fftengine = FFT((nx, ny), fft='mpi', communicator=comm)
        fftengine.create_plan(1)

        kpressure = substrate.evaluate_k_force(
            disp[substrate.subdomain_slices]) / substrate.area_per_pt / (nx *
                                                                         ny)
        expected_k_disp = np.zeros((nx // 2 + 1, ny), dtype=complex)
        expected_k_disp[k[0], k[1]] += .5 - .5j

        # add the symetrics
        if k[0] == 0:
            expected_k_disp[0, -k[1]] += .5 + .5j
        if k[0] == nx // 2 and nx % 2 == 0:
            expected_k_disp[k[0], -k[1]] += .5 + .5j

        fft_disp = np.zeros(substrate.nb_fourier_grid_pts,
                            order='f',
                            dtype=complex)
        fftengine.fft(disp[substrate.subdomain_slices], fft_disp)
        np.testing.assert_allclose(fft_disp / (nx * ny),
                                   expected_k_disp[substrate.fourier_slices],
                                   rtol=1e-7,
                                   atol=1e-10)

        expected_k_pressure = -E_s / 2 * q * expected_k_disp
        np.testing.assert_allclose(
            kpressure,
            expected_k_pressure[substrate.fourier_slices],
            rtol=1e-7,
            atol=1e-10)

        computedpressure = substrate.evaluate_force(
            disp[substrate.subdomain_slices]) / substrate.area_per_pt
        np.testing.assert_allclose(computedpressure,
                                   refpressure[substrate.subdomain_slices],
                                   atol=1e-10,
                                   rtol=1e-7)

        computedenergy_kspace = \
            substrate.evaluate(disp[substrate.subdomain_slices], pot=True,
                               forces=False)[0]
        computedenergy = \
            substrate.evaluate(disp[substrate.subdomain_slices], pot=True,
                               forces=True)[0]
        refenergy = E_s / 8 * 2 * q * sx * sy

        # print(substrate.nb_domain_grid_pts[-1] % 2)
        # print(substrate.nb_fourier_grid_pts)
        # print(substrate.fourier_locations[-1] +
        # substrate.nb_fourier_grid_pts[-1] - 1)
        # print(substrate.nb_domain_grid_pts[-1] // 2 )
        # print(computedenergy)
        # print(computedenergy_kspace)
        # print(refenergy)
        np.testing.assert_allclose(
            computedenergy,
            refenergy,
            rtol=1e-10,
            err_msg="wavevektor {} for nb_domain_grid_pts {}, "
            "subdomain nb_grid_pts {}, nb_fourier_grid_pts {}".format(
                k, substrate.nb_domain_grid_pts,
                substrate.nb_subdomain_grid_pts,
                substrate.nb_fourier_grid_pts))
        np.testing.assert_allclose(
            computedenergy_kspace,
            refenergy,
            rtol=1e-10,
            err_msg="wavevektor {} for nb_domain_grid_pts {}, "
            "subdomain nb_grid_pts {}, nb_fourier_grid_pts {}".format(
                k, substrate.nb_domain_grid_pts,
                substrate.nb_subdomain_grid_pts,
                substrate.nb_fourier_grid_pts))