Commit 1a13269e authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Implemented FlexibleLBMBoundaryHandling

parent 40bd6745
Pipeline #26909 passed with stage
in 21 minutes and 46 seconds
from .boundaryindexing import AdvancedStreamingBoundaryIndexing
from .boundaryconditions import FlexibleBoundary, FlexibleNoSlip
from .boundaryhandling import create_flexible_lbm_boundary_kernel
from .boundaryhandling import create_advanced_streaming_boundary_kernel
__all__ = ['AdvancedStreamingBoundaryIndexing', 'FlexibleBoundary',
'FlexibleNoSlip', 'create_flexible_lbm_boundary_kernel']
'FlexibleNoSlip', 'create_advanced_streaming_boundary_kernel']
......@@ -48,9 +48,7 @@ class FlexibleBoundary:
@property
def additional_code_nodes(self):
"""Return a list of code nodes that need to be prepended to the boundary equations
in the generated code. Those can be instances of subclasses of pystencils.astnodes.Node, or
pystencils assignments."""
"""Return a list of code nodes that will be added in the generated code before the index field loop."""
return []
@property
......
from lbmpy.advanced_streaming import AdvancedStreamingBoundaryIndexing
from pystencils import Assignment, create_indexed_kernel
from pystencils import Field, Assignment, create_indexed_kernel
from pystencils.boundaries import BoundaryHandling
from pystencils.boundaries.createindexlist import numpy_data_type_for_boundary_object
def create_flexible_lbm_boundary_kernel(pdf_field, index_field, lb_method, boundary_functor,
between_timesteps='both', kernel_type='pull',
target='cpu', openmp=True):
class FlexibleLBMBoundaryHandling(BoundaryHandling):
"""
Enables boundary handling for LBM simulations with advanced streaming patterns.
For the in-place patterns AA and EsoTwist, two kernels are generated for a boundary
object and the right one selected depending on the time step.
"""
def __init__(self, lb_method, data_handling, pdf_field_name, kernel_type='pull',
name="boundary_handling", flag_interface=None, target='cpu', openmp=True):
self._lb_method = lb_method
self._kernel_type = kernel_type
self._two_fields_kernel = kernel_type in ['pull', 'push']
self._between_timesteps = 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
def between_timesteps(self):
return self._between_timesteps
def __call__(self, between_timesteps='both', **kwargs):
if between_timesteps not in ['both', 'odd_to_even', 'even_to_odd']:
raise ValueError("Invalid value of between_timesteps argument:", between_timesteps)
self._between_timesteps = between_timesteps
super(FlexibleLBMBoundaryHandling, self).__call__(**kwargs)
self._between_timesteps = None
def add_fixed_steps(self, fixed_loop, **kwargs):
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:
return self._add_flexible_boundary(boundary_obj, flag)
def _add_flexible_boundary(self, boundary_obj, flag=None):
if boundary_obj not in self._boundary_object_to_boundary_info:
sym_index_field = Field.create_generic('indexField', spatial_dimensions=1,
dtype=numpy_data_type_for_boundary_object(boundary_obj, self.dim))
even_to_odd_kernel = self._create_boundary_kernel(self._data_handling.fields[self._field_name],
sym_index_field, boundary_obj, 'even_to_odd').compile()
odd_to_even_kernel = self._create_boundary_kernel(self._data_handling.fields[self._field_name],
sym_index_field, boundary_obj, 'odd_to_even').compile()
if flag is None:
flag = self.flag_interface.reserve_next_flag()
boundary_info = self.FlexibleBoundaryInfo(self, boundary_obj, flag, even_to_odd_kernel, odd_to_even_kernel)
self._boundary_object_to_boundary_info[boundary_obj] = boundary_info
return self._boundary_object_to_boundary_info[boundary_obj].flag
def _create_boundary_kernel(self, symbolic_field, symbolic_index_field, boundary_obj, between_timesteps='both'):
return create_advanced_streaming_boundary_kernel(
symbolic_field, symbolic_index_field, self._lb_method, boundary_obj,
between_timesteps=between_timesteps, kernel_type=self._kernel_type,
target=self._target, openmp=self._openmp)
class FlexibleBoundaryInfo(object):
@property
def kernel(self):
between_timesteps = self._boundary_handling.between_timesteps
if between_timesteps is None:
raise Exception(
"The flexible boundary kernel property was accessed while "
+ "there was no boundary handling in progress.")
if between_timesteps == 'both':
raise ValueError("No boundary kernel can be selected for both kinds of time steps!")
assert between_timesteps in ['odd_to_even', 'even_to_odd']
if between_timesteps == 'even_to_odd':
return self._even_to_odd_kernel
else:
return self._odd_to_even_kernel
def __init__(self, boundary_handling, boundary_obj, flag, even_to_odd_kernel, odd_to_even_kernel):
self._boundary_handling = boundary_handling
self.boundary_object = boundary_obj
self.flag = flag
self._odd_to_even_kernel = odd_to_even_kernel
self._even_to_odd_kernel = even_to_odd_kernel
# end class FlexibleLBMBoundaryHandling
def create_advanced_streaming_boundary_kernel(pdf_field, index_field, lb_method, boundary_functor,
between_timesteps='both', kernel_type='pull',
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(
......@@ -17,11 +107,15 @@ def create_flexible_lbm_boundary_kernel(pdf_field, index_field, lb_method, bound
boundary_assignments = boundary_functor(f_out, f_in, dir_symbol, inv_dir, lb_method, index_field)
boundary_assignments = indexing.substitute_proxies(boundary_assignments)
elements = []
# elements = [indexing.code_node]
# elements += boundary_functor.additional_code_nodes
elements += [Assignment(dir_symbol, index_field[0]('dir'))]
# Code Elements inside the loop
elements = [Assignment(dir_symbol, index_field[0]('dir'))]
elements += boundary_assignments.all_assignments
kernel = create_indexed_kernel(elements, [index_field], target=target, cpu_openmp=openmp)
kernel.body.insert_front(indexing.code_node)
# Code Elements ahead of the loop
index_arrs_node = indexing.create_code_node()
for node in boundary_functor.additional_code_nodes[::-1]:
kernel.body.insert_front(node)
kernel.body.insert_front(index_arrs_node)
return kernel
......@@ -46,7 +46,7 @@ class AdvancedStreamingBoundaryIndexing:
between_timesteps)
if between_timesteps == 'both' and kernel_type in ['aa', 'esotwist']:
raise ValueError('Cannot create an offset info for both kinds of timesteps for kernel type ' + kernel_type)
raise ValueError('Cannot create index arrays for both kinds of timesteps for kernel type ' + kernel_type)
odd_to_even = (between_timesteps == 'odd_to_even')
......@@ -191,8 +191,7 @@ class AdvancedStreamingBoundaryIndexing:
trivials.add((f_dir, inv))
return trivials
@property
def code_node(self):
def create_code_node(self):
return AdvancedStreamingBoundaryIndexing.TranslationArraysNode(self)
class TranslationArraysNode(CustomCodeNode):
......
......@@ -8,7 +8,7 @@ from lbmpy.fieldaccess import StreamPullTwoFieldsAccessor, \
EsoTwistEvenTimeStepAccessor, \
EsoTwistOddTimeStepAccessor
from lbmpy.advanced_streaming import FlexibleNoSlip, create_flexible_lbm_boundary_kernel
from lbmpy.advanced_streaming import FlexibleNoSlip, create_advanced_streaming_boundary_kernel
from lbmpy.creationfunctions import create_lb_method
from lbmpy.stencils import get_stencil
......@@ -112,7 +112,7 @@ def test_flexible_noslip_single_cell(stencil, timestep_type, kernel_type):
shape=(TypedSymbol("indexVectorSize", create_type(np.int64)), 1), strides=(1, 1))
index_vector = np.array([ pos + (d,) for d in range(q) ], dtype=index_struct_dtype)
flex_ast = create_flexible_lbm_boundary_kernel(pdf_field,
flex_ast = create_advanced_streaming_boundary_kernel(pdf_field,
index_field, lb_method, flex_noslip,
between_timesteps=timestep_type,
kernel_type=kernel_type)
......
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