Commit 577f7797 authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Refactoring + First steps toward merging boundary implementations

parent ac69e4f1
Pipeline #27450 passed with stage
in 29 minutes and 41 seconds
from .boundaryindexing import AdvancedStreamingBoundaryIndexing
from .indexing import BetweenTimestepsIndexing
from .boundaryconditions import FlexibleBoundary, FlexibleNoSlip
from .boundaryhandling import FlexibleLBMBoundaryHandling, \
create_advanced_streaming_boundary_kernel
from .communication import get_communication_slices, PeriodicityHandling
from .utility import Timestep, get_accessor
__all__ = ['AdvancedStreamingBoundaryIndexing', 'FlexibleBoundary',
__all__ = ['BetweenTimestepsIndexing', 'FlexibleBoundary',
'FlexibleNoSlip', 'create_advanced_streaming_boundary_kernel',
'FlexibleLBMBoundaryHandling',
'get_communication_slices', 'PeriodicityHandling',
......
from lbmpy.advanced_streaming.boundaryindexing import AdvancedStreamingBoundaryIndexing
from lbmpy.advanced_streaming.utility import Timestep
import numpy as np
from lbmpy.advanced_streaming.indexing import BetweenTimestepsIndexing
from lbmpy.advanced_streaming.utility import is_inplace, Timestep, AccessPdfValues
from pystencils import Field, Assignment, create_indexed_kernel
from pystencils.boundaries import BoundaryHandling
from pystencils.boundaries.createindexlist import numpy_data_type_for_boundary_object
......@@ -16,13 +17,11 @@ class FlexibleLBMBoundaryHandling(BoundaryHandling):
name="boundary_handling", flag_interface=None, target='cpu', openmp=True):
self._lb_method = lb_method
self._streaming_pattern = streaming_pattern
self._two_fields_kernel = streaming_pattern in ['pull', 'push']
self._inplace = is_inplace(streaming_pattern)
self._prev_timestep = None
super(FlexibleLBMBoundaryHandling, self).__init__(data_handling, pdf_field_name, lb_method.stencil,
name, flag_interface, target, openmp)
# TODO: Force On Boundary
# ------------------------- Overridden methods of pystencils.BoundaryHandling -------------------------
@property
......@@ -38,10 +37,10 @@ class FlexibleLBMBoundaryHandling(BoundaryHandling):
raise NotImplementedError("Adding to fixed loop is not supported by FlexibleLBMBoundaryHandling")
def _add_boundary(self, boundary_obj, flag=None):
if self._two_fields_kernel:
return super(FlexibleLBMBoundaryHandling, self)._add_boundary(boundary_obj, flag)
else:
if self._inplace:
return self._add_flexible_boundary(boundary_obj, flag)
else:
return super(FlexibleLBMBoundaryHandling, self)._add_boundary(boundary_obj, flag)
def _add_flexible_boundary(self, boundary_obj, flag=None):
if boundary_obj not in self._boundary_object_to_boundary_info:
......@@ -53,7 +52,7 @@ class FlexibleLBMBoundaryHandling(BoundaryHandling):
self._data_handling.fields[self._field_name], sym_index_field, boundary_obj, Timestep.ODD).compile()]
if flag is None:
flag = self.flag_interface.reserve_next_flag()
boundary_info = self.FlexibleBoundaryInfo(self, boundary_obj, flag, kernels)
boundary_info = self.InplaceStreamingBoundaryInfo(self, boundary_obj, flag, kernels)
self._boundary_object_to_boundary_info[boundary_obj] = boundary_info
return self._boundary_object_to_boundary_info[boundary_obj].flag
......@@ -63,14 +62,14 @@ class FlexibleLBMBoundaryHandling(BoundaryHandling):
prev_timestep=prev_timestep, streaming_pattern=self._streaming_pattern,
target=self._target, openmp=self._openmp)
class FlexibleBoundaryInfo(object):
class InplaceStreamingBoundaryInfo(object):
@property
def kernel(self):
prev_timestep = self._boundary_handling.prev_timestep
if prev_timestep is None:
raise Exception(
"The flexible boundary kernel property was accessed while "
"The boundary kernel property was accessed while "
+ "there was no boundary handling in progress.")
return self._kernels[prev_timestep]
......@@ -79,6 +78,41 @@ class FlexibleLBMBoundaryHandling(BoundaryHandling):
self.boundary_object = boundary_obj
self.flag = flag
self._kernels = kernels
# end class InplaceStreamingBoundaryInfo
# ------------------------------ Force On Boundary ------------------------------------------------------------
def force_on_boundary(self, boundary_obj, prev_timestep=Timestep.BOTH):
from lbmpy.advanced_streaming import FlexibleNoSlip
if isinstance(boundary_obj, FlexibleNoSlip):
return self._force_on_no_slip(boundary_obj, prev_timestep)
else:
self.__call__()
return self._force_on_boundary(boundary_obj, prev_timestep)
def _force_on_no_slip(self, boundary_obj, prev_timestep):
dh = self._data_handling
ff_ghost_layers = dh.ghost_layers_of_field(self.flag_interface.flag_field_name)
method = self._lb_method
stencil = np.array(method.stencil)
result = np.zeros(self.dim)
for b in dh.iterate(ghost_layers=ff_ghost_layers):
obj_to_ind_list = b[self._index_array_name].boundary_object_to_index_list
pdf_array = b[self._field_name]
if boundary_obj in obj_to_ind_list:
ind_arr = obj_to_ind_list[boundary_obj]
acc = AccessPdfValues(dh.fields[self._field_name], self._lb_method.stencil,
streaming_pattern=self._streaming_pattern, timestep=prev_timestep,
streaming_dir='out')
values = 2 * acc.collect_from_index_list(pdf_array, ind_arr)
forces = stencil[ind_arr['dir']] * values[:, np.newaxis]
result += forces.sum(axis=0)
return dh.reduce_float_sequence(list(result), 'sum')
def _force_on_boundary(self, boundary_obj, prev_timestep):
raise NotImplementedError()
# end class FlexibleLBMBoundaryHandling
......@@ -88,7 +122,7 @@ def create_advanced_streaming_boundary_kernel(pdf_field, index_field, lb_method,
target='cpu', openmp=True):
index_dtype = index_field.dtype.numpy_dtype.fields['dir'][0]
offsets_dtype = index_field.dtype.numpy_dtype.fields['x'][0]
indexing = AdvancedStreamingBoundaryIndexing(
indexing = BetweenTimestepsIndexing(
pdf_field, lb_method.stencil, prev_timestep, streaming_pattern, index_dtype, offsets_dtype)
f_out, f_in = indexing.proxy_fields
......
......@@ -161,7 +161,7 @@ class PeriodicityHandling:
to be about four times faster.
"""
if not isinstance(data_handling, SerialDataHandling):
raise ValueError('Only single node data handling is supported!')
raise ValueError('Only serial data handling is supported!')
assert target in ['cpu', 'gpu', 'opencl']
......
......@@ -10,11 +10,11 @@ from lbmpy.advanced_streaming.utility import get_accessor, inverse_dir_index, is
from itertools import product
class AdvancedStreamingBoundaryIndexing:
class BetweenTimestepsIndexing:
# =======================================
# Symbols for usage in boundaries
# =======================================
# ==============================================
# Symbols for usage in kernel definitions
# ==============================================
@property
def proxy_fields(self):
......@@ -154,7 +154,7 @@ class AdvancedStreamingBoundaryIndexing:
return trivials
def create_code_node(self):
return AdvancedStreamingBoundaryIndexing.TranslationArraysNode(self)
return BetweenTimestepsIndexing.TranslationArraysNode(self)
class TranslationArraysNode(CustomCodeNode):
......@@ -176,16 +176,16 @@ class AdvancedStreamingBoundaryIndexing:
acc_offsets = ", ".join([str(o) for o in offsets[d]])
code += self._array_pattern(indexing._offsets_dtype, arrsymb.name, acc_offsets)
super(AdvancedStreamingBoundaryIndexing.TranslationArraysNode, self).__init__(
super(BetweenTimestepsIndexing.TranslationArraysNode, self).__init__(
code, symbols_read=set(), symbols_defined=symbols_defined)
def _array_pattern(self, dtype, name, content):
return f"const {str(dtype)} {name} [] = {{ {content} }}; \n"
def __str__(self):
return "Boundary Access Translation Arrays"
return "Variable PDF Access Translation Arrays"
def __repr__(self):
return "Boundary Access Translation Arrays"
return "Variable PDF Access Translation Arrays"
# end class AdvancedStreamingIndexing
......@@ -6,6 +6,7 @@ from lbmpy.fieldaccess import PdfFieldAccessor, \
EsoTwistEvenTimeStepAccessor, \
EsoTwistOddTimeStepAccessor
import numpy as np
import pystencils as ps
from enum import IntEnum
......@@ -79,20 +80,33 @@ 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=Timestep.BOTH, accessor=None):
def __init__(self, pdf_field, stencil,
streaming_pattern='pull', timestep=Timestep.BOTH, streaming_dir='out',
accessor=None):
if streaming_dir not in ['in', 'out']:
raise ValueError('Invalid streaming direction.', streaming_dir)
if accessor is None:
accessor = get_accessor(streaming_pattern, timestep)
self.read_accs = accessor.read(pdf_field, stencil)
self.write_accs = accessor.write(pdf_field, stencil)
self.accs = accessor.read(pdf_field, stencil) \
if streaming_dir == 'in' \
else accessor.write(pdf_field, stencil)
def write_pdf(self, pdf_arr, pos, d, value):
offsets = self.write_accs[d].offsets
offsets = numeric_offsets(self.accs[d])
pos = tuple(p + o for p, o in zip(pos, offsets))
i = self.write_accs[d].index[0]
i = numeric_index(self.accs[d])[0]
pdf_arr[pos + (i,)] = value
def read_pdf(self, pdf_arr, pos, d):
offsets = self.read_accs[d].offsets
offsets = numeric_offsets(self.accs[d])
pos = tuple(p + o for p, o in zip(pos, offsets))
i = self.read_accs[d].index[0]
i = numeric_index(self.accs[d])[0]
return pdf_arr[pos + (i,)]
def collect_from_index_list(self, pdf_arr, index_list):
def to_coordinate_tuple(idx):
return tuple(idx[v] for v in ('x', 'y', 'z')[:len(idx) - 1])
gen = [self.read_pdf(pdf_arr, to_coordinate_tuple(idx), idx['dir']) for idx in index_list]
return np.array(gen)
......@@ -29,8 +29,8 @@ def test_advanced_streaming_noslip_single_cell(stencil, streaming_pattern, prev_
dim = len(stencil[0])
pdf_field = ps.fields(f'pdfs({q}): [{dim}D]')
prev_pdf_access = AccessPdfValues(pdf_field, stencil, streaming_pattern, prev_timestep)
next_pdf_access = AccessPdfValues(pdf_field, stencil, streaming_pattern, prev_timestep.next())
prev_pdf_access = AccessPdfValues(pdf_field, stencil, streaming_pattern, prev_timestep, 'out')
next_pdf_access = AccessPdfValues(pdf_field, stencil, streaming_pattern, prev_timestep.next(), 'in')
pdfs = np.zeros((3,) * dim + (q,))
pos = (1,) * dim
......
......@@ -22,13 +22,15 @@ targets = ['cpu']
try:
import pycuda.autoinit
targets += ['gpu']
except ImportError:
except Exception:
pass
try:
import pystencils.opencl.autoinit
from pystencils.opencl.opencljit import get_global_cl_queue
if get_global_cl_queue() is not None:
targets += ['opencl']
except ImportError:
except Exception:
pass
......@@ -38,7 +40,6 @@ except ImportError:
def test_fully_periodic_flow(target, stencil, streaming_pattern):
if target == 'opencl':
from pystencils.opencl.opencljit import get_global_cl_queue
opencl_queue = get_global_cl_queue()
else:
opencl_queue = None
......
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