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)
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))