diff --git a/tests/test_epic.py b/tests/test_epic.py
index e8afe7a..e46e64e 100644
--- a/tests/test_epic.py
+++ b/tests/test_epic.py
@@ -1,78 +1,81 @@
# -*- coding: utf-8 -*-
# @file
# LICENSE
#
# Copyright (©) 2016-2021 EPFL (École Polytechnique Fédérale de Lausanne),
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
from __future__ import division, print_function
import pytest
from conftest import pkridfn
import tamaas as tm
from numpy.linalg import norm
from tamaas.nonlinear_solvers import DFSANESolver
@pytest.fixture(scope="module",
params=[tm.PolonskyKeerRey.pressure],
ids=pkridfn)
-def pkr_coarse(hertz_coarse, request):
- model = tm.ModelFactory.createModel(tm.model_type.basic_2d,
- [hertz_coarse.domain_size,
- hertz_coarse.domain_size],
- [hertz_coarse.n, hertz_coarse.n])
- model.E, model.nu = hertz_coarse.e_star, 0
- solver = tm.PolonskyKeerRey(model, hertz_coarse.surface, 1e-12,
- request.param,
- request.param)
- solver.solve(hertz_coarse.load)
+def model_setup(hertz_coarse, request):
+ models, solvers = [], []
- return model, hertz_coarse
+ for mtype in [tm.model_type.basic_2d, tm.model_type.volume_2d]:
+ dim = tm.type_traits[mtype].dimension
+ n = [hertz_coarse.n] * dim
+ d = [hertz_coarse.domain_size] * dim
+ if dim == 3:
+ n[0] = 2
+ d[0] = 0.001
-@pytest.mark.xfail(tm.TamaasInfo.backend == 'tbb',
- reason='TBB reductions are unstable?')
-def test_epic(pkr_coarse):
- """Test the full elastic-plastic solve step in elasticity"""
- # We use computed values from basic PKR to test
- model_elastic, hertz = pkr_coarse
+ model = tm.ModelFactory.createModel(mtype, d, n)
+ model.E, model.nu = hertz_coarse.e_star, 0
+
+ solver = tm.PolonskyKeerRey(model, hertz_coarse.surface, 1e-12,
+ request.param,
+ request.param)
- model = tm.ModelFactory.createModel(
- tm.model_type.volume_2d,
- [0.001, hertz.domain_size, hertz.domain_size],
- [2, hertz.n, hertz.n]
- )
+ models.append(model)
+ solvers.append(solver)
- model.E, model.nu = hertz.e_star, 0
- residual = tm.ModelFactory.createResidual(
+ epsolver = DFSANESolver(tm.ModelFactory.createResidual(
model,
sigma_y=1e2 * model.E,
hardening=0
- )
+ ))
+
+ solvers[1] = tm.EPICSolver(solvers[1], epsolver, 1e-12)
- epsolver = DFSANESolver(residual)
- csolver = tm.PolonskyKeerRey(model, hertz.surface, 1e-12)
+ for solver in solvers:
+ solver.solve(hertz_coarse.load)
- epic = tm.EPICSolver(csolver, epsolver, 1e-12)
- epic.solve(hertz.load)
+ return models, hertz_coarse
+
+
+@pytest.mark.xfail(tm.TamaasInfo.backend == 'tbb',
+ reason='TBB reductions are unstable?')
+def test_energy(model_setup):
+ """Test the full elastic-plastic solve step in elasticity"""
+ # We use computed values from basic PKR to test
+ (model_elastic, model_plastic), hertz = model_setup
- error = norm((model['traction'][..., 2] - model_elastic['traction'])
- * (model['displacement'][0, ..., 2]
- - model_elastic['displacement']))
+ error = norm(
+ (model_plastic.traction[..., 2] - model_elastic.traction)
+ * (model_plastic.displacement[0, ..., 2] - model_elastic.displacement))
error /= norm(hertz.pressure * hertz.displacement)
assert error < 1e-16
diff --git a/tests/test_saturated_pressure.py b/tests/test_saturated_pressure.py
index 270c15c..f104006 100644
--- a/tests/test_saturated_pressure.py
+++ b/tests/test_saturated_pressure.py
@@ -1,66 +1,73 @@
# -*- coding: utf-8 -*-
# @file
# LICENSE
#
# Copyright (©) 2016-2021 EPFL (École Polytechnique Fédérale de Lausanne),
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
from __future__ import print_function, division
import numpy as np
import tamaas as tm
+import pytest
-def test_saturated_pressure():
- tm.set_log_level(tm.LogLevel.debug)
+@pytest.fixture(scope="module")
+def saturated():
grid_size = 256
load = 0.06
p_sat = 0.4
iso = tm.Isopowerlaw2D()
iso.q0 = 4
iso.q1 = 4
iso.q2 = 16
iso.hurst = 0.8
sg = tm.SurfaceGeneratorFilter2D([grid_size] * 2)
sg.random_seed = 2
sg.spectrum = iso
surface = sg.buildSurface()
surface *= 0.01 / iso.rmsHeights()
surface -= np.max(surface)
model = tm.ModelFactory.createModel(tm.model_type.basic_2d,
[1., 1.], [grid_size, grid_size])
model.E = 1.
model.nu = 0
solver = tm.KatoSaturated(model, surface, 1e-12, p_sat)
solver.max_iter = 6000
- assert solver.solve(load) < 1e-12
+ solver.solve(load)
- tractions = model['traction']
+ return model, p_sat, load
- mean_pressure_error = abs(np.mean(tractions)-load)/load
- max_pressure_error = np.max(tractions)-p_sat
- gaps = model['gap']
- gaps[np.where(tractions == p_sat)] = 0.
- press = tractions
- orthogonality_error = np.max(press*gaps) / (press.max() * gaps.max())
+def test_mean_pressure(saturated):
+ model, _, load = saturated
+ assert abs(model.traction.mean() - load) / load < 1e-12
- assert mean_pressure_error < 1e-12 and max_pressure_error < 1e-12 and \
- orthogonality_error < 4e-8
+
+def test_max_pressure(saturated):
+ model, p_sat, _ = saturated
+ assert abs(model.traction.max() - p_sat) / p_sat < 1e-12
+
+
+def test_orthogonality(saturated):
+ model, _, _ = saturated
+ error = np.max(model.traction * model['gap']) \
+ / (model.traction.max() * model['gap'].max())
+ assert error < 4e-8
diff --git a/tests/test_surface.py b/tests/test_surface.py
index f85af92..74bad02 100644
--- a/tests/test_surface.py
+++ b/tests/test_surface.py
@@ -1,137 +1,135 @@
# -*- coding: utf-8 -*-
# @file
# LICENSE
#
# Copyright (©) 2016-2021 EPFL (École Polytechnique Fédérale de Lausanne),
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
from __future__ import print_function, division
import numpy as np
import tamaas as tm
import pytest
import scipy.integrate as integrate
from scipy.special import jv
from numpy import pi
from scipy.interpolate import interp2d
-def compute_mse(values, mean):
- return np.mean((values - mean)**2)
-
-
def spectrum(r, isopowerlaw):
kl, kr, ks = isopowerlaw.q0, isopowerlaw.q1, isopowerlaw.q2
H = isopowerlaw.hurst
C = 1.
if r > ks:
return 0
elif r > kr:
return C * (r/float(kr))**(-2.*(H+1))
elif r > kl:
return C
else:
return 0
def integrate_bessel(x, spectrum, n):
return 2 * pi * integrate.quad(lambda y: y*jv(0, y*x) * spectrum(n*y),
0, np.inf, limit=200)[0]
def radial_average(field):
x = np.linspace(-1, 1, field.shape[0])
y = np.linspace(-1, 1, field.shape[1])
interpolation = interp2d(x, y, field)
n = field.shape[0] // 2
radii = np.linspace(0, 1, n)
thetas = np.linspace(0, 2 * pi, endpoint=False)
sum = np.zeros_like(radii)
for Θ in thetas:
for i, r in enumerate(radii):
sum[i] += interpolation(r * np.cos(Θ), r * np.sin(Θ))
return sum / thetas.size
integrate_bessel = np.vectorize(integrate_bessel, otypes=[tm.dtype])
@pytest.fixture(scope="module",
params=[tm.SurfaceGeneratorFilter2D,
tm.SurfaceGeneratorRandomPhase2D])
-def isopowerlaw(request):
+def stats(request):
iso = tm.Isopowerlaw2D()
iso.q0 = 16
iso.q1 = 32
iso.q2 = 64
iso.hurst = 0.8
N = 243
sg = request.param()
sg.spectrum = iso
sg.shape = [N, N]
analytical_stats = {
"rms_heights": iso.rmsHeights(),
"rms_slopes_spectral": iso.rmsSlopes(),
"moments": iso.moments(),
"alpha": iso.alpha()
}
- return sg, analytical_stats
-
+ stats = {k: [] for k in analytical_stats}
-def test_surface_statistics(isopowerlaw):
- sg, analytical_stats = isopowerlaw
+ acf = np.zeros(sg.shape, dtype=tm.dtype)
realizations = 1000
- L = 1 * sg.spectrum.q0
- n = sg.shape[0] // 2
- x = np.linspace(0, L/2, n)
-
- true_acf = (L / (2 * pi))**2 \
- * integrate_bessel(x, lambda x: spectrum(x, sg.spectrum), L / (2 * pi))
-
- stats = {k: [] for k in analytical_stats}
- acf = np.zeros(sg.shape, dtype=tm.dtype)
-
for i in range(realizations):
sg.random_seed = i
s = sg.buildSurface()
stats['rms_heights'].append(
tm.Statistics2D.computeRMSHeights(s))
stats['rms_slopes_spectral'].append(
tm.Statistics2D.computeSpectralRMSSlope(s))
stats['moments'].append(tm.Statistics2D.computeMoments(s))
acf += tm.Statistics2D.computeAutocorrelation(s) / realizations
- # Testing only the more reliable measures
- for key in ['rms_heights', 'rms_slopes_spectral']:
- mu = np.mean(stats[key])
- error = np.abs(mu - analytical_stats[key]) / analytical_stats[key]
- assert error < 3e-3, "Error in measure of {}".format(key)
+ L = 1 * sg.spectrum.q0
+ n = sg.shape[0] // 2
+ x = np.linspace(0, L/2, n)
+
+ true_acf = (L / (2 * pi))**2 \
+ * integrate_bessel(x, lambda x: spectrum(x, sg.spectrum), L / (2 * pi))
+
+ return analytical_stats, stats, acf, true_acf
+
+
+@pytest.mark.parametrize('key', ['rms_heights', 'rms_slopes_spectral'])
+def test_statistics(stats, key):
+ analytical_stats, stats, _, _ = stats
+ mu = np.mean(stats[key])
+ error = np.abs(mu - analytical_stats[key]) / analytical_stats[key]
+ assert error < 3e-3
+
+def test_autocorrelation(stats):
+ _, _, acf, true_acf = stats
acf = radial_average(np.fft.fftshift(acf))
acf_error = np.sum((acf-true_acf)**2) / np.sum(true_acf**2)
- assert acf_error < 2e-3, "Error with analytical ACF"
+ assert acf_error < 2e-3