Commit ef03d2e6 authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Tests for comm slices

parent 28a9823b
Pipeline #27061 failed with stage
in 22 minutes and 28 seconds
from pystencils import Field
from pystencils.slicing import shift_slice, get_slice_before_ghost_layer
from lbmpy.advanced_streaming.utility import get_accessor
from lbmpy.advanced_streaming.utility import get_accessor, numeric_index, numeric_offsets
def cut_slice_in_direction(slices, direction):
assert len(slices) == len(dir)
assert len(slices) == len(direction)
result = []
for s, d in zip(slices, direction):
......@@ -30,7 +31,16 @@ def _get_neighbour_transform(direction, ghost_layers):
return tuple(d * (ghost_layers + 1) for d in direction)
def communication_slices(lb_method, streaming_pattern='pull', after_timestep='both', ghost_layers=1):
def _fix_length_one_slices(slices):
if isinstance(slices, slice):
if slices.stop is None:
return slices
else:
return slice(slices.start, None if abs(slices.start - slices.stop) == 1 else slices.stop)
return tuple(_fix_length_one_slices(s) for s in slices)
def get_communication_slices(stencil, streaming_pattern='pull', after_timestep='both', ghost_layers=1):
"""
Return the source and destination slices for periodicity handling or communication between
blocks. This function returns a dictionary which contains a list of tuples
......@@ -44,26 +54,30 @@ def communication_slices(lb_method, streaming_pattern='pull', after_timestep='bo
:param ghost_layers: Number of ghost layers in each direction.
"""
stencil = lb_method.stencil
write_accesses = get_accessor(streaming_pattern, after_timestep).write()
pdfs = Field.create_generic('pdfs', spatial_dimensions=len(stencil[0]), index_shape=(len(stencil),))
write_accesses = get_accessor(streaming_pattern, after_timestep).write(pdfs, stencil)
all_slices = dict()
for comm_dir in stencil:
slices_for_dir = set()
if all(d == 0 for d in comm_dir):
continue
slices_for_dir = dict()
for streaming_dir in set(extend_dir(comm_dir)) & set(stencil):
d = stencil.index(streaming_dir)
write_offsets = write_accesses[d].offsets
write_index = write_accesses[d].index[0]
write_offsets = numeric_offsets(write_accesses[d])
write_index = numeric_index(write_accesses[d])[0]
tangential_dir = tuple(s - c for s, c in zip(streaming_dir, comm_dir))
origin_slice = get_slice_before_ghost_layer(comm_dir, ghost_layers=ghost_layers, thickness=1)
origin_slice = _fix_length_one_slices(origin_slice)
src_slice = shift_slice(cut_slice_in_direction(origin_slice, tangential_dir), write_offsets)
neighbour_transform = _get_neighbour_transform(comm_dir, ghost_layers)
dst_slice = shift_slice(src_slice, neighbour_transform)
slices_for_dir.add((write_index, src_slice, dst_slice))
slices_for_dir[write_index] = ((src_slice, dst_slice))
all_slices[comm_dir] = slices_for_dir
return all_slices
......
......@@ -6,6 +6,7 @@ from lbmpy.fieldaccess import PdfFieldAccessor, \
EsoTwistEvenTimeStepAccessor, \
EsoTwistOddTimeStepAccessor
import pystencils as ps
streaming_patterns = ['push', 'pull', 'aa', 'esotwist']
timesteps = ['even', 'odd', 'both']
......@@ -39,17 +40,22 @@ def get_accessor(streaming_pattern, timestep) -> PdfFieldAccessor:
return odd_accessors[streaming_pattern]
def inverse_dir_index(stencil, dir):
return stencil.index(tuple(-d for d in stencil[dir]))
def numeric_offsets(field_access: ps.Field.Access):
return tuple(int(o) for o in field_access.offsets)
"""
Allows to access values from a PDF array correctly depending on
the streaming pattern.
"""
def numeric_index(field_access: ps.Field.Access):
return tuple(int(i) for i in field_access.index)
def inverse_dir_index(stencil, dir):
return stencil.index(tuple(-d for d in stencil[dir]))
class AccessPdfValues:
"""Allows to access values from a PDF array correctly depending on
the streaming pattern."""
def __init__(self, pdf_field, stencil, streaming_pattern='pull', timestep='both', accessor=None):
if accessor is None:
accessor = get_accessor(streaming_pattern, timestep)
......
import numpy as np
from lbmpy.stencils import get_stencil
from pystencils.slicing import get_slice_before_ghost_layer, get_ghost_region_slice
from lbmpy.advanced_streaming.communication import get_communication_slices, _fix_length_one_slices
from lbmpy.advanced_streaming.utility import streaming_patterns
import pytest
@pytest.mark.parametrize('stencil', ['D2Q9', 'D3Q19', 'D3Q27'])
@pytest.mark.parametrize('streaming_pattern', streaming_patterns)
@pytest.mark.parametrize('timestep', ['even', 'odd'])
def test_slices_not_empty(stencil, streaming_pattern, timestep):
stencil = get_stencil(stencil)
arr = np.zeros( (4,) * len(stencil[0]) )
slices = get_communication_slices(stencil, streaming_pattern, timestep, 1)
for _, slices_dict in slices.items():
for _, comm_slices in slices_dict.items():
assert all(s != 0 for s in arr[comm_slices[0]].shape)
assert all(s != 0 for s in arr[comm_slices[1]].shape)
@pytest.mark.parametrize('stencil', ['D2Q9', 'D3Q19', 'D3Q27'])
def test_pull_communication_slices(stencil):
stencil = get_stencil(stencil)
slices = get_communication_slices(stencil, 'pull', 'both', 1)
for i, d in enumerate(stencil):
if i == 0:
continue
src, dst = slices[d][i]
inner_slice = _fix_length_one_slices(get_slice_before_ghost_layer(d, ghost_layers=1))
inv_dir = (-e for e in d)
gl_slice = _fix_length_one_slices(get_ghost_region_slice(inv_dir, ghost_layers=1))
assert src == inner_slice
assert dst == gl_slice
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment