test updates
- move generalizable fixtures out into conftest.py - move some other functions out to utils - fix test_poynting_planes() for fdtd
This commit is contained in:
parent
9f4a515eca
commit
8fc96c13ab
92
meanas/test/conftest.py
Normal file
92
meanas/test/conftest.py
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
from typing import List, Tuple
|
||||||
|
import numpy
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
PRNG = numpy.random.RandomState(12345)
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# Test fixtures
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module',
|
||||||
|
params=[(5, 5, 1),
|
||||||
|
(5, 1, 5),
|
||||||
|
(5, 5, 5),
|
||||||
|
#(7, 7, 7),
|
||||||
|
])
|
||||||
|
def shape(request):
|
||||||
|
yield (3, *request.param)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module', params=[1.0, 1.5])
|
||||||
|
def epsilon_bg(request):
|
||||||
|
yield request.param
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module', params=[1.0, 2.5])
|
||||||
|
def epsilon_fg(request):
|
||||||
|
yield request.param
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module', params=['center', '000', 'random'])
|
||||||
|
def epsilon(request, shape, epsilon_bg, epsilon_fg):
|
||||||
|
is3d = (numpy.array(shape) == 1).sum() == 0
|
||||||
|
if is3d:
|
||||||
|
if request.param == '000':
|
||||||
|
pytest.skip('Skipping 000 epsilon because test is 3D (for speed)')
|
||||||
|
if epsilon_bg != 1:
|
||||||
|
pytest.skip('Skipping epsilon_bg != 1 because test is 3D (for speed)')
|
||||||
|
if epsilon_fg not in (1.0, 2.0):
|
||||||
|
pytest.skip('Skipping epsilon_fg not in (1, 2) because test is 3D (for speed)')
|
||||||
|
|
||||||
|
epsilon = numpy.full(shape, epsilon_bg, dtype=float)
|
||||||
|
if request.param == 'center':
|
||||||
|
epsilon[:, shape[1]//2, shape[2]//2, shape[3]//2] = epsilon_fg
|
||||||
|
elif request.param == '000':
|
||||||
|
epsilon[:, 0, 0, 0] = epsilon_fg
|
||||||
|
elif request.param == 'random':
|
||||||
|
epsilon[:] = PRNG.uniform(low=min(epsilon_bg, epsilon_fg),
|
||||||
|
high=max(epsilon_bg, epsilon_fg),
|
||||||
|
size=shape)
|
||||||
|
|
||||||
|
yield epsilon
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module', params=[1.0])#, 1.5])
|
||||||
|
def j_mag(request):
|
||||||
|
yield request.param
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module', params=['center', 'random'])
|
||||||
|
def j_distribution(request, shape, j_mag):
|
||||||
|
j = numpy.zeros(shape)
|
||||||
|
if request.param == 'center':
|
||||||
|
j[:, shape[1]//2, shape[2]//2, shape[3]//2] = j_mag
|
||||||
|
elif request.param == '000':
|
||||||
|
j[:, 0, 0, 0] = j_mag
|
||||||
|
elif request.param == 'random':
|
||||||
|
j[:] = PRNG.uniform(low=-j_mag, high=j_mag, size=shape)
|
||||||
|
yield j
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module', params=[1.0, 1.5])
|
||||||
|
def dx(request):
|
||||||
|
yield request.param
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module', params=['uniform'])
|
||||||
|
def dxes(request, shape, dx):
|
||||||
|
if request.param == 'uniform':
|
||||||
|
dxes = [[numpy.full(s, dx) for s in shape[1:]] for _ in range(2)]
|
||||||
|
yield dxes
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='module',
|
||||||
|
params=[(0, 4, 8),
|
||||||
|
#(0,),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def j_steps(request):
|
||||||
|
yield request.param
|
@ -1,21 +1,11 @@
|
|||||||
import numpy
|
|
||||||
import pytest
|
|
||||||
import dataclasses
|
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
import dataclasses
|
||||||
|
import pytest
|
||||||
|
import numpy
|
||||||
from numpy.testing import assert_allclose, assert_array_equal
|
from numpy.testing import assert_allclose, assert_array_equal
|
||||||
|
|
||||||
from meanas import fdtd
|
from .. import fdtd
|
||||||
|
from .utils import assert_close, assert_fields_close
|
||||||
|
|
||||||
prng = numpy.random.RandomState(12345)
|
|
||||||
|
|
||||||
|
|
||||||
def assert_fields_close(a, b, *args, **kwargs):
|
|
||||||
numpy.testing.assert_allclose(a, b, verbose=False, err_msg='Fields did not match:\n{}\n{}'.format(numpy.rollaxis(a, -1),
|
|
||||||
numpy.rollaxis(b, -1)), *args, **kwargs)
|
|
||||||
|
|
||||||
def assert_close(a, b, *args, **kwargs):
|
|
||||||
numpy.testing.assert_allclose(a, b, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def test_initial_fields(sim):
|
def test_initial_fields(sim):
|
||||||
@ -101,40 +91,43 @@ def test_poynting_divergence(sim):
|
|||||||
|
|
||||||
|
|
||||||
def test_poynting_planes(sim):
|
def test_poynting_planes(sim):
|
||||||
mask = (sim.js[0] != 0)
|
mask = (sim.js[0] != 0).any(axis=0)
|
||||||
if mask.sum() > 1:
|
if mask.sum() > 1:
|
||||||
pytest.skip('test_poynting_planes can only test single point sources')
|
pytest.skip('test_poynting_planes can only test single point sources, got {}'.format(mask.sum()))
|
||||||
|
|
||||||
args = {'dxes': sim.dxes,
|
args = {'dxes': sim.dxes,
|
||||||
'epsilon': sim.epsilon}
|
'epsilon': sim.epsilon}
|
||||||
dV = numpy.prod(numpy.meshgrid(*sim.dxes[0], indexing='ij'), axis=0)
|
|
||||||
|
|
||||||
mx = numpy.roll(mask, (-1, -1), axis=(0, 1))
|
mx = numpy.roll(mask, -1, axis=0)
|
||||||
my = numpy.roll(mask, -1, axis=2)
|
my = numpy.roll(mask, -1, axis=1)
|
||||||
mz = numpy.roll(mask, (+1, -1), axis=(0, 3))
|
mz = numpy.roll(mask, -1, axis=2)
|
||||||
px = numpy.roll(mask, -1, axis=0)
|
|
||||||
py = mask.copy()
|
|
||||||
pz = numpy.roll(mask, +1, axis=0)
|
|
||||||
|
|
||||||
u_eprev = None
|
u_eprev = None
|
||||||
for ii in range(1, 8):
|
for ii in range(1, 8):
|
||||||
u_hstep = fdtd.energy_hstep(e0=sim.es[ii-1], h1=sim.hs[ii], e2=sim.es[ii], **args)
|
u_hstep = fdtd.energy_hstep(e0=sim.es[ii-1], h1=sim.hs[ii], e2=sim.es[ii], **args)
|
||||||
u_estep = fdtd.energy_estep(h0=sim.hs[ii], e1=sim.es[ii], h2=sim.hs[ii + 1], **args)
|
u_estep = fdtd.energy_estep(h0=sim.hs[ii], e1=sim.es[ii], h2=sim.hs[ii + 1], **args)
|
||||||
|
delta_j_B = fdtd.delta_energy_j(j0=sim.js[ii], e1=sim.es[ii], dxes=sim.dxes)
|
||||||
|
du_half_h2e = u_estep - u_hstep - delta_j_B
|
||||||
|
|
||||||
s_h2e = -fdtd.poynting(e=sim.es[ii], h=sim.hs[ii], dxes=sim.dxes) * sim.dt
|
s_h2e = -fdtd.poynting(e=sim.es[ii], h=sim.hs[ii], dxes=sim.dxes) * sim.dt
|
||||||
planes = [s_h2e[px].sum(), -s_h2e[mx].sum(),
|
planes = [s_h2e[0, mask].sum(), -s_h2e[0, mx].sum(),
|
||||||
s_h2e[py].sum(), -s_h2e[my].sum(),
|
s_h2e[1, mask].sum(), -s_h2e[1, my].sum(),
|
||||||
s_h2e[pz].sum(), -s_h2e[mz].sum()]
|
s_h2e[2, mask].sum(), -s_h2e[2, mz].sum()]
|
||||||
assert_close(sum(planes), (u_estep - u_hstep).sum())
|
|
||||||
|
assert_close(sum(planes), du_half_h2e[mask])
|
||||||
|
|
||||||
if u_eprev is None:
|
if u_eprev is None:
|
||||||
u_eprev = u_estep
|
u_eprev = u_estep
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
delta_j_A = fdtd.delta_energy_j(j0=sim.js[ii], e1=sim.es[ii-1], dxes=sim.dxes)
|
||||||
|
du_half_e2h = u_hstep - u_eprev - delta_j_A
|
||||||
|
|
||||||
s_e2h = -fdtd.poynting(e=sim.es[ii - 1], h=sim.hs[ii], dxes=sim.dxes) * sim.dt
|
s_e2h = -fdtd.poynting(e=sim.es[ii - 1], h=sim.hs[ii], dxes=sim.dxes) * sim.dt
|
||||||
planes = [s_e2h[px].sum(), -s_e2h[mx].sum(),
|
planes = [s_e2h[0, mask].sum(), -s_e2h[0, mx].sum(),
|
||||||
s_e2h[py].sum(), -s_e2h[my].sum(),
|
s_e2h[1, mask].sum(), -s_e2h[1, my].sum(),
|
||||||
s_e2h[pz].sum(), -s_e2h[mz].sum()]
|
s_e2h[2, mask].sum(), -s_e2h[2, mz].sum()]
|
||||||
assert_close(sum(planes), (u_hstep - u_eprev).sum())
|
assert_close(sum(planes), du_half_e2h[mask])
|
||||||
|
|
||||||
# previous half-step
|
# previous half-step
|
||||||
u_eprev = u_estep
|
u_eprev = u_estep
|
||||||
@ -143,94 +136,14 @@ def test_poynting_planes(sim):
|
|||||||
#####################################
|
#####################################
|
||||||
# Test fixtures
|
# Test fixtures
|
||||||
#####################################
|
#####################################
|
||||||
|
# Also see conftest.py
|
||||||
@pytest.fixture(scope='module',
|
|
||||||
params=[(5, 5, 1),
|
|
||||||
(5, 1, 5),
|
|
||||||
(5, 5, 5),
|
|
||||||
# (7, 7, 7),
|
|
||||||
])
|
|
||||||
def shape(request):
|
|
||||||
yield (3, *request.param)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=[0.3])
|
@pytest.fixture(params=[0.3])
|
||||||
def dt(request):
|
def dt(request):
|
||||||
yield request.param
|
yield request.param
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=[1.0, 1.5])
|
|
||||||
def epsilon_bg(request):
|
|
||||||
yield request.param
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=[1.0, 2.5])
|
|
||||||
def epsilon_fg(request):
|
|
||||||
yield request.param
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=['center', '000', 'random'])
|
|
||||||
def epsilon(request, shape, epsilon_bg, epsilon_fg):
|
|
||||||
is3d = (numpy.array(shape) == 1).sum() == 0
|
|
||||||
if is3d:
|
|
||||||
if request.param == '000':
|
|
||||||
pytest.skip('Skipping 000 epsilon because test is 3D (for speed)')
|
|
||||||
if epsilon_bg != 1:
|
|
||||||
pytest.skip('Skipping epsilon_bg != 1 because test is 3D (for speed)')
|
|
||||||
if epsilon_fg not in (1.0, 2.0):
|
|
||||||
pytest.skip('Skipping epsilon_fg not in (1, 2) because test is 3D (for speed)')
|
|
||||||
|
|
||||||
epsilon = numpy.full(shape, epsilon_bg, dtype=float)
|
|
||||||
if request.param == 'center':
|
|
||||||
epsilon[:, shape[1]//2, shape[2]//2, shape[3]//2] = epsilon_fg
|
|
||||||
elif request.param == '000':
|
|
||||||
epsilon[:, 0, 0, 0] = epsilon_fg
|
|
||||||
elif request.param == 'random':
|
|
||||||
epsilon[:] = prng.uniform(low=min(epsilon_bg, epsilon_fg),
|
|
||||||
high=max(epsilon_bg, epsilon_fg),
|
|
||||||
size=shape)
|
|
||||||
|
|
||||||
yield epsilon
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=[1.0])#, 1.5])
|
|
||||||
def j_mag(request):
|
|
||||||
yield request.param
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=['center', 'random'])
|
|
||||||
def j_distribution(request, shape, j_mag):
|
|
||||||
j = numpy.zeros(shape)
|
|
||||||
if request.param == 'center':
|
|
||||||
j[:, shape[1]//2, shape[2]//2, shape[3]//2] = j_mag
|
|
||||||
elif request.param == '000':
|
|
||||||
j[:, 0, 0, 0] = j_mag
|
|
||||||
elif request.param == 'random':
|
|
||||||
j[:] = prng.uniform(low=-j_mag, high=j_mag, size=shape)
|
|
||||||
yield j
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=[1.0, 1.5])
|
|
||||||
def dx(request):
|
|
||||||
yield request.param
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module', params=['uniform'])
|
|
||||||
def dxes(request, shape, dx):
|
|
||||||
if request.param == 'uniform':
|
|
||||||
dxes = [[numpy.full(s, dx) for s in shape[1:]] for _ in range(2)]
|
|
||||||
yield dxes
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module',
|
|
||||||
params=[(0,),
|
|
||||||
(0, 4, 8),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
def j_steps(request):
|
|
||||||
yield request.param
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass()
|
@dataclasses.dataclass()
|
||||||
class SimResult:
|
class SimResult:
|
||||||
shape: Tuple[int]
|
shape: Tuple[int]
|
||||||
@ -244,7 +157,7 @@ class SimResult:
|
|||||||
js: List[numpy.ndarray] = dataclasses.field(default_factory=list)
|
js: List[numpy.ndarray] = dataclasses.field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@pytest.fixture()
|
||||||
def sim(request, shape, epsilon, dxes, dt, j_distribution, j_steps):
|
def sim(request, shape, epsilon, dxes, dt, j_distribution, j_steps):
|
||||||
is3d = (numpy.array(shape) == 1).sum() == 0
|
is3d = (numpy.array(shape) == 1).sum() == 0
|
||||||
if is3d:
|
if is3d:
|
||||||
@ -281,5 +194,3 @@ def sim(request, shape, epsilon, dxes, dt, j_distribution, j_steps):
|
|||||||
sim.es.append(e)
|
sim.es.append(e)
|
||||||
sim.hs.append(h)
|
sim.hs.append(h)
|
||||||
return sim
|
return sim
|
||||||
|
|
||||||
|
|
||||||
|
11
meanas/test/utils.py
Normal file
11
meanas/test/utils.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import numpy
|
||||||
|
|
||||||
|
|
||||||
|
def assert_fields_close(x, y, *args, **kwargs):
|
||||||
|
numpy.testing.assert_allclose(x, y, verbose=False,
|
||||||
|
err_msg='Fields did not match:\n{}\n{}'.format(numpy.rollaxis(x, -1),
|
||||||
|
numpy.rollaxis(y, -1)), *args, **kwargs)
|
||||||
|
|
||||||
|
def assert_close(x, y, *args, **kwargs):
|
||||||
|
numpy.testing.assert_allclose(x, y, *args, **kwargs)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user