diff --git a/src/sfg_walberla/api.py b/src/sfg_walberla/api.py index 2c8caeef9bb6715af061e5d508a79cfdeddd4566..1b24fc41e07c564fe6cde1e26cbba5ca9f6a2d8f 100644 --- a/src/sfg_walberla/api.py +++ b/src/sfg_walberla/api.py @@ -65,6 +65,14 @@ class AABB(AugExpr): return Vector3(real_t).bind("{}.max()", self) +class CellInterval(AugExpr): + def __init__(self, ref: bool = False): + dtype = PsCustomType("walberla::CellInterval") + if ref: + dtype = Ref(dtype) + super().__init__(dtype) + + class BlockDataID(AugExpr): def __init__(self): super().__init__(PsCustomType("walberla::BlockDataID")) @@ -157,11 +165,11 @@ class GenericWalberlaField(SrcField): element_type: PsType, field_type: PsCustomType, ptr: bool = False, - ref: bool = False + ref: bool = False, ): if ptr and ref: raise ValueError("At most one of `ptr` and `ref` may be true.") - + self._element_type = element_type self._field_type = field_type @@ -181,17 +189,20 @@ class GenericWalberlaField(SrcField): return AugExpr.format("{}->", self) else: return AugExpr.format("{}.", self) - + @property def field_type(self) -> PsCustomType: return self._field_type def get_extraction(self) -> IFieldExtraction: return GhostLayerFieldExtraction(self, None) - + + def with_cell_interval(self, ci: CellInterval | None): + return GhostLayerFieldExtraction(self, ci) + def cloneUninitialized(self) -> AugExpr: return AugExpr.format("{}cloneUninitialized()", self._a) - + def swapDataPointers(self, other: AugExpr) -> AugExpr: return AugExpr.format("{}swapDataPointers({});", self._a, other) @@ -220,12 +231,8 @@ class GhostLayerFieldPtr(GenericWalberlaField): f"walberla::field::GhostLayerField< {elmt_type_str}, {fsize} >" ) - super().__init__( - element_type, - field_type, - ptr=True - ) - + super().__init__(element_type, field_type, ptr=True) + @property def required_includes(self) -> set[SfgHeaderInclude]: return {SfgHeaderInclude("field/GhostLayerField.h")} @@ -251,16 +258,10 @@ class GpuFieldPtr(GenericWalberlaField): ): element_type = create_type(element_type) elmt_type_str = element_type.c_string() - field_type = PsCustomType( - f"walberla::gpu::GpuField< {elmt_type_str} >" - ) + field_type = PsCustomType(f"walberla::gpu::GpuField< {elmt_type_str} >") + + super().__init__(element_type, field_type, ptr=True) - super().__init__( - element_type, - field_type, - ptr=True - ) - @property def required_includes(self) -> set[SfgHeaderInclude]: return {SfgHeaderInclude("gpu/GpuField.h")} diff --git a/src/sfg_walberla/boundaries/__init__.py b/src/sfg_walberla/boundaries/__init__.py index eb22b15e8dacf9a3cb7b873349a3a4ff45ff05ab..9a732bf3f6131d110ec614b49d0996bbcf5919f5 100644 --- a/src/sfg_walberla/boundaries/__init__.py +++ b/src/sfg_walberla/boundaries/__init__.py @@ -1,5 +1,3 @@ from .hbb import SimpleHbbBoundary -__all__ = [ - "SimpleHbbBoundary" -] \ No newline at end of file +__all__ = ["SimpleHbbBoundary"] diff --git a/src/sfg_walberla/boundaries/hbb.py b/src/sfg_walberla/boundaries/hbb.py index 8114b3495cb12d4db88c896b650f9cfc9b415193..2a79cb70a0f6d4ed6d6f3fe8e38d87726a225132 100644 --- a/src/sfg_walberla/boundaries/hbb.py +++ b/src/sfg_walberla/boundaries/hbb.py @@ -199,7 +199,7 @@ def _create_lb_boundary_kernel( ): """Almost-copy of `lbmpy.boundaryhandling.create_lattice_boltzmann_boundary_kernel`, extended with waLBerla-specific function expansion.""" - + from lbmpy.advanced_streaming.indexing import BetweenTimestepsIndexing indexing = BetweenTimestepsIndexing( diff --git a/src/sfg_walberla/sweep.py b/src/sfg_walberla/sweep.py index fd9bc9c4eb80bcd0904f325b834454c1cd049a80..eb84dbb00e6ba440912b81b007d9c5ec00645698 100644 --- a/src/sfg_walberla/sweep.py +++ b/src/sfg_walberla/sweep.py @@ -40,6 +40,7 @@ from .api import ( BlockDataID, Vector2, Vector3, + CellInterval, ) @@ -211,10 +212,14 @@ class BlockforestParameters: for param in params: for coord in range(3): if param.name == domain.aabb_min[coord].name: - self._extractions[param] = self.blockforest().getDomain().min()[coord] + self._extractions[param] = ( + self.blockforest().getDomain().min()[coord] + ) break elif param.name == domain.aabb_max[coord].name: - self._extractions[param] = self.blockforest().getDomain().max()[coord] + self._extractions[param] = ( + self.blockforest().getDomain().max()[coord] + ) break elif param.name == block.aabb_min[coord].name: self._extractions[param] = self._block.getAABB().min()[coord] @@ -332,12 +337,11 @@ class CudaInvocation: self._gpu_func = gpu_func self._block_size = Vector3(uint_t).var("gpuBlockSize") - + def render(self, sfg: SfgComposer): pass - def combine_vectors(scalars: set[SfgVar]) -> dict[SrcVector, tuple[SfgVar, ...]]: """Attempt to combine vector component symbols into vectors. @@ -493,50 +497,53 @@ class Sweep(CustomGenerator): for s in sorted(parameters, key=lambda p: p.name): props.add_property(s, setter=True, getter=True) + def render_runmethod(ci: CellInterval | None = None): + return [ + # Get IDs from class + *(sfg.init(fi.data_id)(props.get(fi.data_id)) for fi in block_fields), + # Extract regular fields from block + *( + sfg.init(fi.glfield_ptr)( + block.getData(fi.glfield_ptr.field_type, fi.data_id) + ) + for fi in block_fields + ), + # Get shadow fields from cache + *( + sfg.init(shadow_info.glfield_ptr)( + shadows_cache.get_shadow(orig_name) + ) + for orig_name, shadow_info in swaps.items() + ), + # Map GhostLayerFields to pystencils fields + *( + sfg.map_field(fi.field, fi.glfield_ptr.with_cell_interval(ci)) + for fi in all_fields.values() + ), + # Get parameters from class + *(sfg.init(param)(props.get(param)) for param in parameters), + # Extract scalars from vectors + *( + sfg.map_vector(components, vector) + for vector, components in vector_groups.items() + ), + # Extract geometry information + *(blockforest_params.render_extractions(sfg)), + sfg.call(khandle), + # Perform field swaps + *( + shadows_cache.perform_swap(orig_name, shadow_info) + for orig_name, shadow_info in swaps.items() + ), + ] + sfg.klass(self._name)( *props.render(sfg), sfg.public( - sfg.method("operator()")( - # Get IDs from class - *( - sfg.init(fi.data_id)(props.get(fi.data_id)) - for fi in block_fields - ), - # Extract regular fields from block - *( - sfg.init(fi.glfield_ptr)( - block.getData(fi.glfield_ptr.field_type, fi.data_id) - ) - for fi in block_fields - ), - # Get shadow fields from cache - *( - sfg.init(shadow_info.glfield_ptr)( - shadows_cache.get_shadow(orig_name) - ) - for orig_name, shadow_info in swaps.items() - ), - # Map GhostLayerFields to pystencils fields - *( - sfg.map_field(fi.field, fi.glfield_ptr) - for fi in all_fields.values() - ), - # Get parameters from class - *(sfg.init(param)(props.get(param)) for param in parameters), - # Extract scalars from vectors - *( - sfg.map_vector(components, vector) - for vector, components in vector_groups.items() - ), - # Extract geometry information - *(blockforest_params.render_extractions(sfg)), - sfg.call(khandle), - # Perform field swaps - *( - shadows_cache.perform_swap(orig_name, shadow_info) - for orig_name, shadow_info in swaps.items() - ), - ) + sfg.method("operator()")(*render_runmethod()), + sfg.method("runOnCellInterval")( + *render_runmethod(CellInterval(ref=True).var("ci")) + ), ), *shadows_cache.render(sfg), )