diff --git a/src/pystencils_autodiff/CMakeLists.tmpl.txt b/src/pystencils_autodiff/CMakeLists.tmpl.txt deleted file mode 100644 index 67e939afe9c75fcd4f7e34cf78d90e03e200bc22..0000000000000000000000000000000000000000 --- a/src/pystencils_autodiff/CMakeLists.tmpl.txt +++ /dev/null @@ -1,12 +0,0 @@ -waLBerla_link_files_to_builddir( *.prm ) -waLBerla_add_executable ( NAME {{ cmake_target_name }} - FILES {%- for f in files_to_compile %} - {{ f }} - {%- endfor %} - DEPENDS {{depends | join(' ')}}) - -{% if 'walberla_openvdb' in depends -%} -if (WALBERLA_BUILD_WITH_OPENVDB) -target_link_libraries( {{ cmake_target_name }} tbb boundary openvdb Half IexMath Iex IlmThread Imath) -endif(WALBERLA_BUILD_WITH_OPENVDB) -{%- endif %} diff --git a/src/pystencils_autodiff/framework_integration/texture_astnodes.py b/src/pystencils_autodiff/framework_integration/texture_astnodes.py index c82fe23a0981a70c75054aad4211ac82043d5708..21e43f24510bf22ac0b9f03227ede1e17b566bc2 100644 --- a/src/pystencils_autodiff/framework_integration/texture_astnodes.py +++ b/src/pystencils_autodiff/framework_integration/texture_astnodes.py @@ -107,7 +107,8 @@ class NativeTextureBinding(pystencils.backends.cbackend.CustomCodeNode): float maxMipmapLevelClamp; }; """ # noqa - CODE_TEMPLATE_LINEAR = jinja2.Template("""cudaResourceDesc {{resource_desc}}{}; + CODE_TEMPLATE_LINEAR = jinja2.Template(""" +cudaResourceDesc {{resource_desc}}{}; {{resource_desc}}.resType = cudaResourceTypeLinear; {{resource_desc}}.res.linear.devPtr = {{device_ptr}}; {{resource_desc}}.res.linear.desc.f = {{cuda_channel_format}}; @@ -124,6 +125,7 @@ auto {{texture_object}}Destroyer = std::unique_ptr(nullptr, [&](){ """) CODE_TEMPLATE_PITCHED2D = jinja2.Template(""" !!! TODO!!! """) CODE_TEMPLATE_CUDA_ARRAY = jinja2.Template(""" +# pragma GCC diagnostic ignored "-Wconversion" auto channel_desc_{{texture_name}} = {{channel_desc}}; {{ create_array }} {{ copy_array }} @@ -139,7 +141,8 @@ std::shared_ptr<void> {{array}}Destroyer(nullptr, [&](...){ cudaFreeArray({{array}}); cudaUnbindTexture({{texture_namespace}}{{texture_name}}); }); - """) +# pragma GCC diagnostic pop +""") def __init__(self, texture, device_data_ptr, use_texture_objects=True, texture_namespace=''): self._texture = texture diff --git a/src/pystencils_autodiff/graph_datahandling.py b/src/pystencils_autodiff/graph_datahandling.py index 7051943bc44df79131c133277fd36fbf6dadafd7..b0c6283f6dabce8d64ee19e3bdf1cb160624035c 100644 --- a/src/pystencils_autodiff/graph_datahandling.py +++ b/src/pystencils_autodiff/graph_datahandling.py @@ -176,7 +176,8 @@ class GraphDataHandling(pystencils.datahandling.SerialDataHandling): cpu=True, gpu=None, alignment=False, - field_type=FieldType.GENERIC): + field_type=FieldType.GENERIC, + shape=None): if layout is None: layout = self.default_layout @@ -197,13 +198,22 @@ class GraphDataHandling(pystencils.datahandling.SerialDataHandling): if len(values_per_cell) == 1 and values_per_cell[0] == 1: values_per_cell = () - rtn = self._fields[name] = pystencils.Field.create_generic(name, - self.dim, - dtype, - index_dimensions=len(values_per_cell), - layout=layout, - index_shape=values_per_cell, - field_type=field_type) + if shape: + rtn = self._fields[name] = pystencils.Field.create_fixed_size(name, + shape, + index_dimensions=len(values_per_cell), + layout=layout, + dtype=dtype, + field_type=field_type) + else: + rtn = self._fields[name] = pystencils.Field.create_generic(name, + self.dim, + dtype, + index_dimensions=len(values_per_cell), + layout=layout, + index_shape=values_per_cell, + field_type=field_type) + rtn.latex_name = latex_name if cpu: diff --git a/src/pystencils_autodiff/simulation.py b/src/pystencils_autodiff/simulation.py deleted file mode 100644 index 9b176ef29364b47c9698457df0c1b5a0a84af654..0000000000000000000000000000000000000000 --- a/src/pystencils_autodiff/simulation.py +++ /dev/null @@ -1,270 +0,0 @@ -# -# Copyright © 2020 Stephan Seitz <stephan.seitz@fau.de> -# -# Distributed under terms of the GPLv3 license. - -""" - -""" - -import itertools -from typing import Dict - -from stringcase import camelcase, pascalcase - -import lbmpy_walberla -import pystencils -import pystencils_walberla.codegen -from pystencils.astnodes import Block, EmptyLine -from pystencils.cpu.cpujit import get_headers -from pystencils_autodiff.walberla import ( - AllocateAllFields, CMakeLists, Communication, DefineKernelObjects, DefinitionsHeader, - FieldCopy, InitBoundaryHandling, LbCommunicationSetup, ResolveUndefinedSymbols, SwapFields, - SweepCreation, SweepOverAllBlocks, TimeLoopNode, UniformBlockforestFromConfig, WalberlaMain, - WalberlaModule, WriteVdb) - -WALBERLA_MODULES = ["blockforest", - "boundary", - "communication", - "core", - "cuda", - "domain_decomposition", - "executiontree", - "fft", - "field", - "gather", - "geometry", - "gui", - "lbm", - "mesa_pd", - "mesh", - "pde", - "pe", - "pe_coupling", - "postprocessing", - "python_coupling", - "simd", - "sqlite", - "stencil", - "timeloop", - "vtk", - "walberla_openvdb"] - - -class Simulation(): - def _get_sweep_class_name(prefix='Kernel'): - ctr = 0 - while True: - yield f'{prefix}{ctr}' - ctr += 1 - - def __init__(self, - graph_data_handling, - codegen_context, - boundary_handling: pystencils.boundaries.BoundaryHandling = None, - lb_rule=None, - refinement_scaling=None, - boundary_handling_target='gpu', - cmake_target_name='autogen_app', - write_out_stuff=True): - self._data_handling = graph_data_handling - self._lb_rule = lb_rule - self._refinement_scaling = refinement_scaling - self._block_forest = UniformBlockforestFromConfig() - self.parameter_config_block = 'parameters' - self._codegen_context = codegen_context - self._boundary_handling = boundary_handling - self._lb_model_name = 'GeneratedLatticeModel' - self._flag_field_dtype = 'uint32_t' - self._kernel_class_generator = Simulation._get_sweep_class_name() - self._with_gui = False - self._with_gui_default = False - self._boundary_kernels = {} - self._boundary_handling_target = boundary_handling_target - self._data_handling.merge_swaps_with_kernel_calls() - self._packinfo_class = 'PackInfo' - self.cmake_target_name = cmake_target_name - self._write_out_stuff = write_out_stuff - self._fluid_uid = None - self._debug = None - - def _create_helper_files(self) -> Dict[str, str]: - - if self._lb_rule: - pystencils_walberla.codegen.generate_pack_info_for_field( - self._codegen_context, - 'PackInfo', - pystencils.Field.create_generic(self._data_handling.fields['ldc_pdf'].name, - self._data_handling.fields['ldc_pdf'].spatial_dimensions, - self._data_handling.fields['ldc_pdf'].dtype.numpy_dtype, - self._data_handling.fields['ldc_pdf'].index_dimensions, - index_shape=self._data_handling.fields['ldc_pdf'].index_shape,), - target=self._boundary_handling_target) - lbmpy_walberla.generate_lattice_model(self._codegen_context, self._lb_model_name, - self._lb_rule, - refinement_scaling=self._refinement_scaling) - if self._boundary_handling: - for bc in self.boundary_conditions: - self._boundary_kernels.update({bc.name: lbmpy_walberla.generate_boundary( - self._codegen_context, - pascalcase(bc.name), - bc, - self._lb_rule.method, - target=self._boundary_handling_target)}, - ) - self._bh_cycler = itertools.cycle(self._boundary_kernels.keys()) - - def _create_module(self): - if self._lb_rule: - lb_shape = (len(self._lb_rule.method.stencil),) - else: - lb_shape = (-1,) - - self._field_allocations = field_allocations = AllocateAllFields(self._block_forest.blocks, - self._data_handling, - lb_shape, - self._lb_model_name) - - if self._boundary_handling: - flag_field_id = field_allocations._cpu_allocations[ - self._boundary_handling.flag_interface.flag_field_name].symbol - - if self._lb_rule: - pdf_field_id = field_allocations._gpu_allocations.get( - 'ldc_pdf', field_allocations._cpu_allocations['ldc_pdf']).symbol - else: - pdf_field_id = None - - call_nodes = filter(lambda x: x, [self._graph_to_sweep(c) for c in self._data_handling.call_queue]) - - init_boundary_handling = (InitBoundaryHandling(self._block_forest.blocks, - flag_field_id, - pdf_field_id, - self.boundary_conditions, - self._boundary_kernels, - self._field_allocations) - if self._boundary_handling - else EmptyLine()) - if hasattr(init_boundary_handling, 'fluid'): - self._fluid_uid = init_boundary_handling.fluid - - module = WalberlaModule(WalberlaMain(Block([ - self._block_forest, - ResolveUndefinedSymbols( - Block([ - field_allocations, - init_boundary_handling, - LbCommunicationSetup(self._lb_model_name, - pdf_field_id, - self._packinfo_class, - self._boundary_handling_target) - if self._lb_rule else EmptyLine(), - DefineKernelObjects( - Block([*call_nodes]) - ) - ]), self.parameter_config_block - ) - ]))) - - if self._debug: - from pystencils_autodiff.framework_integration.printer import DebugFrameworkPrinter - module.printer = DebugFrameworkPrinter() - self._codegen_context.write_file("main.cpp", str(module)) - return module - - def _create_defintions_header(self): - self._codegen_context.write_file("UserDefinitions.h", - str(DefinitionsHeader(self._lb_model_name if self._lb_rule else None, - self._flag_field_dtype))) - - def _create_cmake_file(self, extra_dependencis=[]): - walberla_dependencies = [] - import re - regex = re.compile(r'^["<](\w*)/.*[>$"]') - headers = get_headers(self._module) - for h in headers: - match = regex.match(h) - if match: - module = match[1] - if module in WALBERLA_MODULES: - walberla_dependencies.append(module) - - dependencies = walberla_dependencies + extra_dependencis - - try: - self._codegen_context.write_file("CMakeLists.txt", - str(CMakeLists(self.cmake_target_name, - [f for f in self._codegen_context.files_written() - if f.endswith('.cpp') or f.endswith('.cu')], - depends=dependencies))) - except AttributeError: - self._codegen_context.write_file("CMakeLists.txt", - str(CMakeLists(self.cmake_target_name, - [f for f in self._codegen_context.files.keys() - if f.endswith('.cpp') or f.endswith('.cu')], - depends=dependencies))) - - def write_files(self): - self._create_helper_files() - self._module = self._create_module() - self._create_defintions_header() - self._create_cmake_file() # has to be called last - - @property - def boundary_conditions(self): - return self._boundary_handling._boundary_object_to_boundary_info.keys() - - def _graph_to_sweep(self, c): - from pystencils_autodiff.graph_datahandling import ( - KernelCall, TimeloopRun, DataTransferKind, DataTransfer, FieldOutput) - - if isinstance(c, KernelCall): - - if 'indexField' in [f.name for f in c.kernel.ast.fields_accessed]: - bh = next(self._bh_cycler) - return f'sweep(blocks, {camelcase(bh)});' - - sweep_class_name = next(self._kernel_class_generator) - fields_accessed = [f.name for f in c.kernel.ast.fields_accessed] - c.tmp_field_swaps = list(filter( - lambda x: x[0].name in fields_accessed and x[1].name in fields_accessed, c.tmp_field_swaps)) - pystencils_walberla.codegen.generate_sweep( - self._codegen_context, sweep_class_name, c.kernel.ast, field_swaps=c.tmp_field_swaps) - rtn = SweepOverAllBlocks(SweepCreation(sweep_class_name, - self._field_allocations, - c.kernel.ast, - parameters_to_ignore=[s[1].name for s in c.tmp_field_swaps]), - self._block_forest.blocks) - - elif isinstance(c, TimeloopRun): - sweeps = [self._graph_to_sweep(s) for s in c.timeloop._single_step_asts] - rtn = TimeLoopNode(0, c.time_steps, sweeps) - - elif isinstance(c, DataTransfer): - if c.kind == DataTransferKind.HOST_SWAP: - src = self._field_allocations._cpu_allocations[c.field.name].symbol - dst = self._field_allocations._cpu_allocations[c.destination.name].symbol - rtn = SwapFields(src, dst) - elif c.kind == DataTransferKind.DEVICE_SWAP: - src = self._field_allocations._gpu_allocations[c.field.name].symbol - dst = self._field_allocations._gpu_allocations[c.destination.name].symbol - rtn = SwapFields(src, dst) - elif c.kind == DataTransferKind.HOST_TO_DEVICE: - src = self._field_allocations._cpu_allocations[c.field.name].symbol - dst = self._field_allocations._gpu_allocations[c.field.name].symbol - rtn = FieldCopy(self._block_forest.blocks, src, c.field, False, dst, c.field, True) - elif c.kind == DataTransferKind.DEVICE_TO_HOST: - src = self._field_allocations._gpu_allocations[c.field.name].symbol - dst = self._field_allocations._cpu_allocations[c.field.name].symbol - rtn = FieldCopy(self._block_forest.blocks, src, c.field, True, dst, c.field, False) - elif c.kind in (DataTransferKind.DEVICE_COMMUNICATION, DataTransferKind.HOST_COMMUNICATION): - rtn = Communication(self._boundary_handling_target == 'gpu') - else: - rtn = None - elif isinstance(c, FieldOutput): - rtn = WriteVdb(self._block_forest, c.output_path, c.fields, c.flag_field, self._fluid_uid) - else: - rtn = None - - return rtn - return rtn diff --git a/src/pystencils_autodiff/walberla.py b/src/pystencils_autodiff/walberla.py deleted file mode 100644 index 914a65296dfdac9108cbd930a4630503e2fcde07..0000000000000000000000000000000000000000 --- a/src/pystencils_autodiff/walberla.py +++ /dev/null @@ -1,1025 +0,0 @@ -# -# Copyright © 2020 Stephan Seitz <stephan.seitz@fau.de> -# -# Distributed under terms of the GPLv3 license. - -""" - -""" - - -from abc import ABC -from os.path import dirname, join - -import jinja2 -import numpy as np -import sympy as sp -from stringcase import camelcase, pascalcase -from sympy.core.cache import cacheit - -import pystencils -from pystencils.astnodes import SympyAssignment -from pystencils.data_types import TypedSymbol, create_type -from pystencils_autodiff._file_io import read_template_from_file -from pystencils_autodiff.framework_integration.astnodes import JinjaCppFile - - -def _make_field_type(field, on_gpu): - from pystencils_walberla.jinja_filters import make_field_type, get_field_fsize - f_size = get_field_fsize(field) - - return make_field_type(pystencils.data_types.get_base_type(field.dtype), f_size, on_gpu) - - -class BlockDataID(TypedSymbol): - """ - Local cell interval in global index coordinates - """ - def __new__(cls, *args, **kwds): - obj = BlockDataID.__xnew_cached_(cls, *args, **kwds) - return obj - - def __new_stage2__(cls, field, on_gpu, *args, **kwargs): - name = field.name + ('_data_gpu' if on_gpu else '_data') - obj = super(BlockDataID, cls).__xnew__(cls, - name, - 'BlockDataID', - *args, - **kwargs) - obj.field = field - obj.on_gpu = on_gpu - return obj - - __xnew__ = staticmethod(__new_stage2__) - __xnew_cached_ = staticmethod(cacheit(__new_stage2__)) - - def _hashable_content(self): - return super()._hashable_content(), self.on_gpu - - def __getnewargs__(self): - return self.name, self.on_gpu - - @property - def walberla_field_type(self): - return _make_field_type(self.field, self.on_gpu) - - -class FieldType(JinjaCppFile): - - TEMPLATE = jinja2.Template("{{ field_type }}") - - def __init__(self, field: pystencils.Field, on_gpu: bool): - - field_type = _make_field_type(field, on_gpu) - - ast_dict = {'on_gpu': on_gpu, - 'field_type': field_type - } - JinjaCppFile.__init__(self, ast_dict) - - @property - def headers(self): - if self.ast_dict.on_gpu: - return ['"field/GhostLayerField.h"'] - else: - return ['"cuda/GPUField.h"'] - - -class WalberlaModule(JinjaCppFile): - TEMPLATE = read_template_from_file(join(dirname(__file__), 'walberla_main.tmpl.cpp')) - - def __init__(self, main): - ast_dict = {'main': main} - JinjaCppFile.__init__(self, ast_dict) - - -class CMakeLists(JinjaCppFile): - TEMPLATE = read_template_from_file(join(dirname(__file__), 'CMakeLists.tmpl.txt')) - - def __init__(self, cmake_target_name, files_to_compile, depends): - ast_dict = {'files_to_compile': files_to_compile, # we try to avoid evil globbing - 'cmake_target_name': cmake_target_name, - 'depends': depends} - JinjaCppFile.__init__(self, ast_dict) - - -class WalberlaMain(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" -int main( int argc, char ** argv ) -{ - using namespace walberla; - using namespace walberla_user; - using namespace walberla::pystencils; - - Environment {{ walberl_env }}( argc, argv ); - - {{ body | indent(3) }} - - return EXIT_SUCCESS; -} - """) - - headers = ['"core/Environment.h"', - '<cstdlib>', - '"UserDefinitions.h"'] - - def __init__(self, body, walberl_env="walberlaEnv"): - - ast_dict = { - 'body': body, - 'walberl_env': TypedSymbol(walberl_env, "Environment") - } - - super().__init__(ast_dict) - - @property - def symbols_defined(self): - return {self.ast_dict.walberl_env} - - -class BlockForestCreation(JinjaCppFile): - TEMPLATE = jinja2.Template("""auto {{ blocks }} = walberla_user::createBlockForest(walberlaEnv);""") - def __init__(self, block_forest_name): - - ast_dict = { - 'blocks': TypedSymbol(block_forest_name, "auto") - } - - super().__init__(ast_dict) - - @property - def symbols_defined(self): - return {self.ast_dict.blocks} - - -class UniformBlockforestFromConfig(BlockForestCreation): - TEMPLATE = jinja2.Template( - """auto {{ blocks }} = blockforest::createUniformBlockGridFromConfig( walberlaEnv.config() );""") - headers = ['"blockforest/Initialization.h"'] - - def __init__(self): - super().__init__('blocks') - - @property - def config_required(self): - return {"DomainSetup": {"blocks": [1, 1, 1], "cellsPerBlock": [100, 100, 100]}} - - @property - def blocks(self): - return self.ast_dict.blocks - - -class DefinitionsHeader(JinjaCppFile): - TEMPLATE = read_template_from_file(join(dirname(__file__), 'walberla_user_defintions.tmpl.hpp')) - - def __init__(self, lb_model_name, flag_field_type): - self.headers = ['<cstdint>', '"field/FlagField.h"'] - if lb_model_name: - self.headers.append(f'"{lb_model_name}.h"') - super().__init__({'lb_model_name': lb_model_name, 'flag_field_type': flag_field_type}) - - -class Using(JinjaCppFile): - TEMPLATE = jinja2.Template("using {{ new_type }} = {{ definition }};\n") - - def __init__(self, new_type, definition): - ast_dict = { - 'new_type': new_type, - 'definition': definition, - } - super().__init__(ast_dict) - - @property - def symbols_defined(self): - return {self.ast_dict.new_type} - - -class GetParameter(JinjaCppFile): - - TEMPLATE = jinja2.Template( - 'walberlaEnv.config()->getOneBlock("{{ block }}").getParameter<{{ key.dtype }}>("{{ key }}"{% if default %}, static_cast<{{ key.dtype }}>({{ default }}){% endif %})' # noqa - ) - - def __init__(self, block: str, key, default_value=None): - ast_dict = { - 'key': key, - 'block': block, - 'default': default_value - } - super().__init__(ast_dict) - - @property - def config_required(self): - return {self.ast_dict.block: {self.ast_dict.symbol: self.ast_dict.default_value}} - - def __sympy__(self): - return TypedSymbol(self.ast_dict.key.name + "Config", str(self.ast_dict.key.dtype)) - - def __getattr__(self, name): - return getattr(self.__sympy__(), name) - - -class FieldAllocation(JinjaCppFile): - """ - .. code:: cpp - - BlockDataID addToStorage(const shared_ptr < BlockStorage_T > & blocks, - const std:: string & identifier, - const typename GhostLayerField_T:: value_type & initValue = typename GhostLayerField_T: : value_type(), - const Layout layout=zyxf, - const uint_t nrOfGhostLayers=uint_t(1), - const bool alwaysInitialize=false, - const std:: function < void (GhostLayerField_T * field, IBlock * const block ) > & initFunction = - std: : function < void (GhostLayerField_T * field, IBlock * const block ) > (), - const Set < SUID > & requiredSelectors = Set < SUID > : : emptySet(), - const Set < SUID > & incompatibleSelectors = Set < SUID > : : emptySet() ) - - """ # noqa - - TEMPLATE = jinja2.Template(""" -{%- if on_gpu -%} -BlockDataID {{ field_name }}_data_gpu = cuda::addGPUFieldToStorage<{{ field_type }}>({{ block_forest }}, - "{{ field_name }}", - {{ f_size }}, - {{ layout }}, - {{ num_ghost_layers }}, - {{ usePitchedMem }} ); -{%- else -%} -BlockDataID {{ field_name }}_data = field::addToStorage<{{ field_type }}>( {{ block_forest }}, - "{{ field_name }}" - {%- if init_value -%} , {{ init_value }}{% endif %} - {%- if layout -%} , {{ layout }}{% endif %} - {%- if num_ghost_layers -%}, {{ num_ghost_layers }} {% endif %} - {%- if always_initialize -%}, {{ always_initialize }} {% endif %}); -{%- endif %} -""") # noqa - - def __init__(self, block_forest, field, on_gpu=False, usePitchedMem=True, num_ghost_layers=1, ): - self._symbol = BlockDataID(field, on_gpu) - ast_dict = { - 'block_forest': block_forest, - 'field_name': field.name, - # f'GhostLayerField< {field.dtype}, {field.index_shape[0] if field.index_shape else 1} >' - 'field_type': FieldType(field, on_gpu), - 'on_gpu': on_gpu, - 'f_size': field.index_shape[0] if field.index_shape else 1, - 'init_value': f'{field.dtype}{{}}', - 'num_ghost_layers': num_ghost_layers, - 'layout': 'field::zyxf', - 'usePitchedMem': 'true' if usePitchedMem else 'false', - } - super().__init__(ast_dict) - - @property - def symbol(self): - return self._symbol - - @property - def symbols_defined(self): - return {self.symbol} - - @property - def headers(self): - return (['"cuda/AddGPUFieldToStorage.h"', '"field/GhostLayerField.h"'] - if self.ast_dict.on_gpu - else ['"field/AddToStorage.h"']) - - -class FlagFieldAllocation(FieldAllocation): - """We need this special class to pass waLBerla's runtime type checks""" - TEMPLATE = jinja2.Template("""BlockDataID {{ field_name }}_data = field::addFlagFieldToStorage<FlagField_T>({{ block_forest }}, - "{{ field_name }}"); -""") # noqa - - -class WalberlaVector(JinjaCppFile): - TEMPLATE = jinja2.Template("""math::Vector{{ndim}}<{{dtype}}>({{offset | join(', ')}})""") - - def __init__(self, offset, dtype='real_t'): - ast_dict = { - 'offset': offset, - 'dtype': dtype, - 'ndim': len(offset), - } - super().__init__(ast_dict) - - def __sympy__(self): - return sp.Matrix(self.ast_dict.offset) - - -class FlagUidDefinition(JinjaCppFile): - TEMPLATE = jinja2.Template('const FlagUID {{ name }}FlagUID("{{ name }}");') - - def __init__(self, name): - self._symbol = TypedSymbol(name + 'FlagUID', 'FlagUID') - ast_dict = { - 'name': name, - } - super().__init__(ast_dict) - - headers = ['"field/FlagUID.h"'] - - @property - def symbol(self): - return self._symbol - - @property - def symbols_defined(self): - return {self.symbol} - - -class BoundaryHandling(ABC): - pass - - -class BoundaryHandlingFromConfig(JinjaCppFile): - - TEMPLATE = jinja2.Template("""auto {{ boundaries_config }} = walberlaEnv.config()->getOneBlock( "Boundaries" ); -geometry::initBoundaryHandling<FlagField_T>(*{{ block_forest }}, {{ flag_field_id }}, {{ boundaries_config }}); -geometry::setNonBoundaryCellsToDomain<FlagField_T>(*{{ block_forest }}, {{ flag_field_id }}, {{ fluid_uid }});""") - - def __init__(self, block_forest, flag_field_id, fluid_uid): - self._symbol = boundaries_config = TypedSymbol('boundariesConfig', 'auto') - ast_dict = { - 'flag_field_id': flag_field_id, - 'block_forest': block_forest, - 'fluid_uid': fluid_uid, - 'boundaries_config': boundaries_config, - } - super().__init__(ast_dict) - - @property - def symbol(self): - return self._symbol - - @property - def symbols_defined(self): - return {self.symbol} - - -class FillFromFlagField(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" - {{ boundary_condition }}.fillFromFlagField<{{ flag_field_type }}>( {{ block_forest }}, {{ flag_field_id }}, FlagUID("{{ boundary_name }}"), {{ flag_field_id }}); - """) # noqa - - def __init__(self, flag_field_id, fluid_uid): - self._symbol = boundaries_config = TypedSymbol('boundariesConfig', 'auto') - ast_dict = { - 'flag_field_id': flag_field_id, - 'fluid_uid': fluid_uid, - 'boundaries_config': boundaries_config, - } - super().__init__(ast_dict) - - @property - def symbol(self): - return self._symbol - - @property - def symbols_defined(self): - return {self.symbol} - - -class LbCommunicationSetup(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" -{{CommonicationScheme}}<lbm::{{ lb_model_type }}::CommunicationStencil> {{ communication }}( blocks ); -{{ communication }}.addPackInfo( make_shared< {{ packinfo_class }} >( {{ pdf_id }} ) ); - """) # noqa - - def __init__(self, lb_model_type, pdf_id, packinfo_class, gpu): - self._symbol = TypedSymbol('communication', 'auto') - self.gpu = gpu - - ast_dict = { - 'lb_model_type': lb_model_type, - 'pdf_id': pdf_id, - 'communication': self._symbol, - 'packinfo_class': packinfo_class, - 'CommonicationScheme': ('cuda::communication::UniformGPUScheme' - if gpu else 'blockforest::communication::UniformBufferedScheme') - } - super().__init__(ast_dict) - - @property - def symbol(self): - return self._symbol - - @property - def symbols_defined(self): - return {self.symbol} - - @property - def headers(self): - if self.gpu: - return ['"cuda/communication/UniformGPUScheme.h"', '"lbm/communication/PdfFieldPackInfo.h"', '"PackInfo.h"'] - else: - return ['"blockforest/communication/UniformBufferedScheme.h"', - '"lbm/communication/PdfFieldPackInfo.h"', - '"PackInfo.h"'] - - -class BeforeFunction(JinjaCppFile): - - TEMPLATE = jinja2.Template("""BeforeFunction( {{ f }}, "{{ f }}" )""") # noqa - - def __init__(self, function): - ast_dict = { - 'f': function, - } - super().__init__(ast_dict) - - -class AfterFunction(JinjaCppFile): - - TEMPLATE = jinja2.Template("""AfterFunction( {{ f }}, "{{ f }}" )""") # noqa - - def __init__(self, function): - ast_dict = { - 'f': function, - } - super().__init__(ast_dict) - - -class Sweep(JinjaCppFile): - - TEMPLATE = jinja2.Template("""Sweep( {{ f }}, "{{ f }}" )""") # noqa - - def __init__(self, function): - ast_dict = { - 'f': function, - } - super().__init__(ast_dict) - - -class TimeLoop(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" -{{ timeloop_definition }} - -{% for f in before_functions -%} -{{timeloop_name}}.add() << {{ f }}; -{% endfor %} -{% for s in sweeps -%} -{{timeloop_name}}.add() << {{ s }}; -{% endfor %} -{% for f in after_functions -%} -{{timeloop_name}}.add() << {{ f }}; -{% endfor %} - """) # noqa - - def __init__(self, block_forest, before_functions, sweeps, after_functions, timesteps, timeloop_name='timeloop'): - self._symbol = TypedSymbol(timeloop_name, 'SweepTimeloop') - ast_dict = { - 'timeloop_definition': CppObjectConstruction(self._symbol, - [f'{block_forest}->getBlockStorage()', - timesteps]), - 'before_functions': [BeforeFunction(f) for f in before_functions], - 'sweeps': [Sweep(f) for f in sweeps], - 'after_functions': [AfterFunction(f) for f in after_functions], - 'timeloop_name': timeloop_name - } - super().__init__(ast_dict) - - @property - def symbol(self): - return self._symbol - - @property - def symbols_defined(self): - return {self.symbol} - - headers = ['"timeloop/all.h"'] - - -class ForLoop(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" -for( {{loop_symbol.dtype}} {{loop_symbol}} = {{loop_start}}; {{loop_symbol}} < {{loop_end}}; {{loop_symbol}} += {{loop_increment}} ) { - {%- for c in children %} - {{ c | indent(3) -}} - {% endfor %} -} -""") # noqa - - def __init__(self, - loop_start, - loop_end, - children, - loop_symbol=TypedSymbol('t_', create_type('int64')), - loop_increment=1): - ast_dict = { - 'loop_symbol': loop_symbol, - 'loop_start': loop_start, - 'loop_end': loop_end, - 'children': children, - 'loop_increment': loop_increment - } - super().__init__(ast_dict) - - @property - def loop_symbol(self): - return self.ast_dict.loop_symbol - - @property - def symbols_defined(self): - return {self.loop_symbol} - - -class U_Rho_Adaptor(JinjaCppFile): - """Docstring for U_Rho_Adaptor. """ - - TEMPLATE = jinja2.Template(""" -field::addFieldAdaptor<lbm::Adaptor<lbm::{{ lb_model_type }}>::Density> ( {{ block_forest }}, {{ pdf_id }}, "{{ density_name }}" ); -field::addFieldAdaptor<lbm::Adaptor<lbm::{{ lb_model_type }}>::VelocityVector>( {{ block_forest }}, {{ pdf_id }}, "{{ velocity_name }}" ); - """) # noqa - - def __init__(self, block_forest, lb_model_type, pdf_id): - self.density_name = "DensityAdaptor" - self.velocity_name = "VelocityAdaptor" - ast_dict = { - 'lb_model_type': lb_model_type, - 'pdf_id': pdf_id, - 'block_forest': block_forest, - 'density_name': self.density_name, - 'velocity_name': self.velocity_name, - } - super().__init__(ast_dict) - - headers = ['"timeloop/all.h"'] - - -class RunTimeLoop(JinjaCppFile): - TEMPLATE = jinja2.Template("""{%- if with_gui == 'true' %} -if( parameters.getParameter<bool>( "useGui", {{ use_gui_default }}) ) -{ - GUI gui ( {{ timeloop }}, {{ block_forest }}, argc, argv ); - lbm::connectToGui<LatticeModel_T> ( gui ); - gui.run(); -} -else { - {{ timeloop }}.run(); -} -{%- else %} -timeloop.run(); -{%- endif %}""") # noqa - - def __init__(self, block_forest, timeloop, with_gui=False, use_gui_default='false'): - self.density_name = "DensityAdaptor" - self.velocity_name = "VelocityAdaptor" - ast_dict = { - 'block_forest': block_forest, - 'timeloop': timeloop.symbol, - 'with_gui': with_gui, - 'use_gui_default': use_gui_default, - } - super().__init__(ast_dict) - - @property - def headers(self): - if self.ast_dict.with_gui: - return [ - "gui/all.h", - "lbm/gui/Connection.h" - ] - else: - return [] - - -class CppObjectConstruction(JinjaCppFile, pystencils.astnodes.SympyAssignment): - - TEMPLATE = jinja2.Template("""{{ symbol.dtype }} {{ symbol }}({{ args | join(', ') }});""") # noqa - - def __init__(self, symbol, args): - JinjaCppFile.__init__(self, {}) - self.ast_dict.update({ - 'symbol': symbol, - 'args': args, - }) - pystencils.astnodes.SympyAssignment.__init__(self, symbol, 1) - - @property - def symbol(self): - return self.lhs - - def __sympy__(self): - return self.symbol - - @property - def symbols_defined(self): - return {self.symbol} - - -class ResolveUndefinedSymbols(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" -{% for p in parameters %} -{{ p }} -{% endfor %} -{{ block }} -""") # noqa - - def __init__(self, block, config_block): - self.block = block - JinjaCppFile.__init__(self, {}) - self.ast_dict.update({ - 'block': block, - 'config_block': config_block, - 'parameters': self.parameter_definitions - }) - - @property - def symbols_defined(self): - return self.block.undefined_symbols - - def __repr__(self): - self.ast_dict.parameters = self.parameter_definitions - return super().__repr__() - - def __str__(self): - self.ast_dict.parameters = self.parameter_definitions - return super().__str__() - - @property - def parameter_definitions(self): - parameter_definitions = [SympyAssignment(s, GetParameter(self.ast_dict.config_block, s)) - for s in self.block.undefined_symbols] - return parameter_definitions - - @property - def config_required(self): - return {self.ast_dict.config_block, {s.name: None for s in self.symbols_defined}} - - -class FieldCopyFunctor(JinjaCppFile): - - TEMPLATE = jinja2.Template("""cuda::fieldCpyFunctor<{{from_type}}, {{ to_type }} >({{from_id}}, {{to_id}})""") # noqa - - def __init__(self, from_id, from_type, to_id, to_type): - ast_dict = {'from_id': from_id, - 'from_type': from_type, - 'to_id': to_id, - 'to_type': to_type - } - super().__init__(ast_dict) - - headers = ['"cuda/FieldCopy.h"'] - - -class DefineKernelObjects(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" -// Kernels -{% for k in kernels -%} -{{ k }} -{% endfor %} -// Execution -{{ block }} -""") # noqa - - def __init__(self, block): - self.sweeps = block.atoms(SweepOverAllBlocks) - self.kernels = sorted({k.ast_dict.functor if isinstance(k.ast_dict.functor, SympyAssignment) - else SympyAssignment(k.ast_dict.functor.symbol, k.ast_dict.functor, - is_const=False, use_auto=True) - for k in self.sweeps}, key=str) - ast_dict = {'block': block, - 'kernels': self.kernels, - } - JinjaCppFile.__init__(self, ast_dict) - - -def _allocate_field(block_forest, field, on_gpu): - # TODO: hack! - if np.issubdtype(field.dtype.numpy_dtype, np.integer) and 'flag' in field.name.lower(): - assert on_gpu is False - return FlagFieldAllocation(block_forest, field) - else: - return FieldAllocation(block_forest, field, on_gpu=on_gpu) - - -class AllocateAllFields(JinjaCppFile): - - TEMPLATE = jinja2.Template(""" -// CPU Arrays -{% for c in cpu_arrays %} -{{- c }} -{% endfor %} -{%- if gpu_arrays -%} -// GPU Arrays -{% for g in gpu_arrays %} -{{- g }} -{% endfor %} -{%- endif %} -{{ block }} -""") # noqa - - def __init__(self, block_forest, data_handling, lb_index_shape=(-1,), lb_model_name=None): - self.data_handling = data_handling - self.block_forest = block_forest - self.lb_index_shape = lb_index_shape - self.lb_model_name = lb_model_name - JinjaCppFile.__init__(self, {}) - self._update() - - def __repr__(self): - self._update() - return super().__repr__() - - def __str__(self): - self._update() - return super().__str__() - - def _update(self): - self.ast_dict.update({ - 'cpu_arrays': self._cpu_allocations.values(), - 'gpu_arrays': self._gpu_allocations.values() - }) - - @property - def _cpu_allocations(self): - return {s: _allocate_field(self.block_forest, self.data_handling.fields[s], on_gpu=False) - for s in self.data_handling.cpu_arrays.keys()} - # if not (self.data_handling.fields[s].index_shape == self.lb_index_shape)} - - @property - def _gpu_allocations(self): - return {s: _allocate_field(self.block_forest, self.data_handling.fields[s], on_gpu=True) - for s in self.data_handling.gpu_arrays.keys()} - # if not (self.data_handling.fields[s].index_shape == self.lb_index_shape)} - - -class InitBoundaryHandling(JinjaCppFile): - TEMPLATE = jinja2.Template(""" -// This is my fluid 🏊. It's special... 🤔 but for the computer just a 0 -{{ fluid_uid_definition }} - -// Initialize geometry 🎲 -{{ geometry_initialization }} - -// Here are the generated boundaries. They are not so special... 👎 -{%- for b in generated_boundaries %} -{{ b }} -{% endfor %} -""") # noqa - - def __init__(self, - block_forest, - flag_field_id, - pdf_field_id, - boundary_conditions, - boundary_kernel: dict, - field_allocations): - self.fluid = FlagUidDefinition("fluid") - ast_dict = {'fluid_uid_definition': self.fluid, - 'geometry_initialization': BoundaryHandlingFromConfig(block_forest, - flag_field_id, - self.fluid.symbol), - 'generated_boundaries': [GeneratedBoundaryInitialization(block_forest, - b, - pdf_field_id, - flag_field_id, - self.fluid.symbol, - boundary_kernel[b.name], - field_allocations) - for b in boundary_conditions] - } - super().__init__(ast_dict) - - headers = ['"cuda/FieldCopy.h"', '"geometry/InitBoundaryHandling.h"'] - @property - def undefined_symbols(self): - rtn = super().undefined_symbols - for b in self.ast_dict.generated_boundaries: - rtn = rtn | b.undefined_symbols - return rtn - - -class GeneratedBoundaryInitialization(JinjaCppFile): - TEMPLATE = jinja2.Template("""lbm::{{ boundary_condition }} {{ identifier }}( {{ block_forest }}, {{ parameter_ids | join(', ') }} ); -{{ identifier }}.fillFromFlagField<FlagField_T>( {{ block_forest }}, {{ flag_field_id }}, FlagUID("{{ boundary_condition }}"), {{ fluid_uid }} ); -""") # noqa - - def __init__(self, - block_forest, - boundary_condition, - pdf_field_id, - flag_field_id, - fluid_uid, - kernel, - field_allocations): - def resolve_parameter(p): - if kernel.target == 'cpu': - dict = field_allocations._cpu_allocations - else: - dict = field_allocations._gpu_allocations - - return dict.get(p.symbol.name.replace('_data_', ''), p).symbol - parameters = kernel.get_parameters() - parameter_ids = [resolve_parameter(p) - for p in parameters - if (p.is_field_pointer or not p.is_field_parameter) and - p.symbol.name not in ('_data_indexVector', '_data_pdfs', 'indexVectorSize',)] - - self.fluid = FlagUidDefinition("fluid") - ast_dict = {'block_forest': block_forest, - 'boundary_condition': pascalcase(boundary_condition.name), - 'identifier': camelcase(boundary_condition.name), - 'pdf_field_id': pdf_field_id, - 'fluid_uid': fluid_uid, - 'flag_field_id': flag_field_id, - 'parameter_ids': [pdf_field_id] + parameter_ids, - } - super().__init__(ast_dict) - - @property - def headers(self): - return [f'"{pascalcase(self.ast_dict.boundary_condition)}.h"'] - - @property - def symbols_defined(self): - # Could also be defined - # TypedSymbol(self.ast_dict.identifier, 'FlagUID'), - return {TypedSymbol(self.ast_dict.identifier, f'lbm::{self.ast_dict.boundary_condition}')} - - @property - def undefined_symbols(self): - return super().undefined_symbols | set(self.ast_dict.parameter_ids) - - -class SweepCreation(JinjaCppFile): - TEMPLATE = jinja2.Template("""{{ sweep_class_name }}( {{ parameter_ids | join(', ') }} )""") # noqa - - def __init__(self, - sweep_class_name: str, - field_allocation: AllocateAllFields, - ast, - parameters_to_ignore=[]): - - import pystencils_walberla.jinja_filters - parameters_to_ignore += pystencils_walberla.jinja_filters.SPECIAL_SYMBOL_NAMES - - def resolve_parameter(p): - if ast.target == 'cpu': - dict = field_allocation._cpu_allocations - else: - dict = field_allocation._gpu_allocations - - return dict.get(p.symbol.name.replace('_data_', ''), p).symbol - - parameters = ast.get_parameters() - parameter_ids = [resolve_parameter(p) - for p in parameters - if (p.is_field_pointer and p.symbol.field_name not in parameters_to_ignore) - or not p.is_field_parameter and p.symbol.name not in parameters_to_ignore] - - ast_dict = {'sweep_class_name': sweep_class_name, - 'parameter_ids': parameter_ids, - } - super().__init__(ast_dict) - self.symbol = TypedSymbol(self.ast_dict.sweep_class_name.lower(), self.ast_dict.sweep_class_name) - - @property - def headers(self): - return [f'"{self.ast_dict.sweep_class_name}.h"'] - - @property - def undefined_symbols(self): - return set(self.ast_dict.parameter_ids) - - free_symbols = undefined_symbols - - @property - def symbols_defined(self): - return {self.symbol} - - def __sympy__(self): - return self.symbol - - -class SweepOverAllBlocks(JinjaCppFile): - # TEMPLATE = jinja2.Template("""std::for_each({{block_forest}}->begin(), {{block_forest}}->end(), {{functor}});""") # noqa - TEMPLATE = jinja2.Template("""sweep({{block_forest}}, {{sweep_class_name | lower() }});""") - - def __init__(self, functor: SweepCreation, block_forest): - ast_dict = {'functor': functor, - 'sweep_class_name': functor.ast_dict.sweep_class_name, - 'block_forest': block_forest} - super().__init__(ast_dict) - - @property - def undefined_symbols(self): - return {self.ast_dict.functor.symbol} - - @property - def required_global_declarations(self): - return ["""template < class BlockStorage_T, class Functor_T > -static inline auto sweep(walberla::shared_ptr<BlockStorage_T> blocks, Functor_T functor) -> void { - for ( auto& block : *blocks ) { - functor(&block); - } -} -"""] - - -class FieldCopy(JinjaCppFile): - TEMPLATE = jinja2.Template("""cuda::fieldCpy< {{src_type }}, {{dst_type }} > ({{block_forest }}, {{src_id }}, {{dst_id }}); """) # noqa - - def __init__(self, block_forest, src_id, dst_id,): - ast_dict = {'src_id': src_id, - 'dst_id': dst_id, - 'src_type': src_id.walberla_field_type, - 'dst_type': dst_id.walberla_field_type, - 'block_forest': block_forest} - super().__init__(ast_dict) - - headers = ['"cuda/FieldCopy.h"'] - - -class SwapFields(JinjaCppFile): - """ - .. warn:: - - Prefer temporary fields in sweeps over this class! Two full fields have higher memory usage. - - """ - TEMPLATE = jinja2.Template("""std::swap({{field_id0}}, {{field_id1}});""") - - def __init__(self, field_id0, field_id1): - ast_dict = {'field_id0': field_id0, - 'field_id1': field_id1} - super().__init__(ast_dict) - - headers = ["<algorithm>"] - - -class Communication(JinjaCppFile): - """ - .. warn:: - - Prefer temporary fields in sweeps over this class! Two full fields have higher memory usage. - - """ - TEMPLATE = jinja2.Template("""communication();""") - - def __init__(self, gpu): - ast_dict = {'gpu': gpu} - super().__init__(ast_dict) - - headers = ["<algorithm>"] - - -class VdbWriter(CppObjectConstruction): - def __init__(self, block_forest): - symbol = TypedSymbol('vdb', 'walberla_openvdb::OpenVdbFieldWriter') - super().__init__(symbol, [block_forest.blocks]) - - headers = ['"walberla_openvdb/OpenVdbFieldWriter.h"'] - - @property - def dtype(self): - return self.symbol.dtype - - @property - def free_symbols(self): - return {} - - -class WriteVdb(SweepOverAllBlocks): - TEMPLATE = jinja2.Template( - """{{vdb_writer}}.beginFile("{{output_path}}"{% if time %}, optional<float>({{time}}){% endif %}); -{% for f in fields %} -{%- if flag_field_id -%} -{{ vdb_writer }}.addFieldFiltered<{{ f.walberla_field_type }}, VdbGrid_T<float>, FlagField_T>( {{f}}, "{{f}}", {{ flag_field_id }}, {{ fluid_uid }}); -{%- else -%} -{{ vdb_writer }}.addField<{{ f.walberla_field_type }}, VdbGrid_T<float>>( {{f}}, "{{f}}"); -{%- endif -%} -{% endfor %} -{{vdb_writer}}.writeFile();""") # noqa - - def __init__(self, block_forest, output_path, fields_to_write, flag_field_id, fluid_uid, time=None): - functor = VdbWriter(block_forest) - ast_dict = {'fields': [BlockDataID(f, on_gpu=False) for f in fields_to_write], - 'output_path': output_path, - 'vdb_writer': functor.symbol, - 'flag_field_id': flag_field_id, - 'fluid_uid': fluid_uid, - 'functor': functor, - 'block_forest': block_forest, - 'time': time} - JinjaCppFile.__init__(self, ast_dict) - - required_global_declarations = ["""template < typename T > -using VdbGrid_T = openvdb::Grid < typename openvdb::tree::Tree4 < T, 5, 4, 3 >::Type >;"""] - - @property - def undefined_symbols(self): - return {self.ast_dict.vdb_writer} - - -class TimeLoopNode(ForLoop): - @property - def time(self): - return self.loop_symbol diff --git a/src/pystencils_autodiff/walberla_main.tmpl.cpp b/src/pystencils_autodiff/walberla_main.tmpl.cpp deleted file mode 100644 index 83968b619b3c20fcb40e794c4cc0d54c709f4b89..0000000000000000000000000000000000000000 --- a/src/pystencils_autodiff/walberla_main.tmpl.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Automatically generated waLBerla main - * - */ - -{% for header in headers -%} -#include {{ header }} -{% endfor %} -{% for global in globals -%} -{{ global }} -{% endfor %} - -{{ main }} diff --git a/src/pystencils_autodiff/walberla_user_defintions.tmpl.hpp b/src/pystencils_autodiff/walberla_user_defintions.tmpl.hpp deleted file mode 100644 index 278e8fef9f1d5ce2fdc0361dafe15737c8cd1361..0000000000000000000000000000000000000000 --- a/src/pystencils_autodiff/walberla_user_defintions.tmpl.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * walberla_user_defintions.tmpl.hpp - * Copyright (C) 2020 Stephan Seitz <stephan.seitz@fau.de> - * - * Distributed under terms of the GPLv3 license. - */ - -#pragma once - - -{% for header in headers -%} -#include {{ header }} -{% endfor %} - -namespace walberla_user { -using namespace walberla; -{% if with_lbm %} -using LatticeModel_T = lbm::{{ lb_model_name }}; -using Stencil_T = LatticeModel_T::Stencil; -using CommunicationStencil_T = LatticeModel_T::CommunicationStencil; -{% endif %} -using flag_t = {{ flag_field_type }}; -using FlagField_T = FlagField<flag_t>; - -} // namespace walberla_user diff --git a/tests/test_walberla.py b/tests/test_walberla.py deleted file mode 100644 index 74e19b759fb02f92b6d6c70799eecb514ec1d11b..0000000000000000000000000000000000000000 --- a/tests/test_walberla.py +++ /dev/null @@ -1,188 +0,0 @@ -# -# Copyright © 2020 Stephan Seitz <stephan.seitz@fau.de> -# -# Distributed under terms of the GPLv3 license. - -""" - -""" -import os -import sys -from os.path import dirname, expanduser, join - -import numpy as np -import sympy as sp - -import pystencils -from pystencils.astnodes import Block, EmptyLine, SympyAssignment -from pystencils.data_types import TypedSymbol, create_type -from pystencils_autodiff._file_io import write_file -from pystencils_autodiff.graph_datahandling import GraphDataHandling -from pystencils_autodiff.simulation import Simulation -from pystencils_autodiff.walberla import ( - DefinitionsHeader, FieldAllocation, FlagFieldAllocation, GetParameter, ResolveUndefinedSymbols, - UniformBlockforestFromConfig, WalberlaMain, WalberlaModule) -from pystencils_walberla.cmake_integration import ManualCodeGenerationContext - - -def test_walberla(): - x, y = pystencils.fields('x, y: float32[3d]') - flags = pystencils.fields('flag_field: float32[3d]') - - foo_symbol = TypedSymbol('foo', np.bool) - number_symbol = TypedSymbol('number', np.float32) - crazy_plus_one = TypedSymbol('crazy', np.float32) - - block_forest = UniformBlockforestFromConfig() - - block = Block([ - block_forest, - SympyAssignment(foo_symbol, GetParameter('parameters', foo_symbol)), - SympyAssignment(number_symbol, GetParameter('parameters', number_symbol, 1.2)), - SympyAssignment(crazy_plus_one, number_symbol + 1), - EmptyLine(), - FieldAllocation(block_forest.blocks, x, on_gpu=False), - FlagFieldAllocation(block_forest.blocks, flags) - ]) - - module = WalberlaModule(WalberlaMain(block)) - code = str(module) - print(code) - - write_file('/localhome/seitz_local/projects/walberla/apps/autogen/main.cpp', code) - - definitions = DefinitionsHeader(module, 'uint8_t') - write_file('/localhome/seitz_local/projects/walberla/apps/autogen/UserDefinitions.h', str(definitions)) - - -def test_wald_wiesen_simulation(): - with ManualCodeGenerationContext() as ctx: - dh = GraphDataHandling((30, 30), - periodicity=False, - default_ghost_layers=1, - default_target='cpu') - dh.add_arrays('x, y') - dh.add_arrays('w, z', gpu=True) - - sim = Simulation(dh, ctx) - print(sim._create_module()) - - -def test_wald_wiesen_lbm(): - import pytest - pytest.importorskip('lbmpy') - from lbmpy.creationfunctions import create_lb_collision_rule - sys.path.append(dirname(__file__)) - with ManualCodeGenerationContext() as ctx: - from test_graph_datahandling import ldc_setup - opt_params = {'target': 'gpu'} - import sympy as sp - lid_velocity = sp.symbols('lid_velocity') - lbm_step = ldc_setup(domain_size=(30, 30), optimization=opt_params, - fixed_loop_sizes=False, lid_velocity=lid_velocity) - - del lbm_step.data_handling.gpu_arrays.ldc_pdf_tmp - - sim = Simulation(lbm_step.data_handling, - ctx, - lbm_step.boundary_handling, - create_lb_collision_rule(lbm_step.method, optimization=opt_params), - cmake_target_name='autogen') - sim.write_files() - - dir = '/localhome/seitz_local/projects/walberla/apps/autogen/' - os.makedirs(dir, exist_ok=True) - for k, v in ctx.files.items(): - with open(join(dir, k), 'w') as file: - file.write(v) - - -def test_projection(): - volume = pystencils.fields('volume: float32[3d]') - projections = pystencils.fields('projection: float32[2d]') - spacing, foo = sp.symbols('spacing, foo') - - from pystencils_walberla.special_symbols import aabb_min_vector, dx_vector, global_coord - import pystencils_reco.projection - - from sympy.matrices.dense import matrix_multiply_elementwise - volume.coordinate_transform = lambda x: aabb_min_vector + matrix_multiply_elementwise(x, dx_vector) - projections.set_coordinate_origin_to_field_center() - projections.coordinate_transform *= spacing - - from pystencils.interpolation_astnodes import TextureDeclaration - TextureDeclaration.headers = [] - projection_matrix = pystencils_reco.matrix_symbols('T', pystencils.data_types.create_type('float32'), 3, 4) - from pystencils.kernelparameters import FieldPointerSymbol, FieldStrideSymbol - - assignments = pystencils_reco.projection.forward_projection(volume, projections, projection_matrix) - assignments.main_assignments.append(pystencils.Assignment(foo, FieldPointerSymbol( - volume.name, volume.dtype, const=True) + FieldStrideSymbol(volume.name, 0) + FieldStrideSymbol(volume.name, 1))) - assignments.subs({a: b for a, b in zip(pystencils.x_vector(3), global_coord)}) - assignments.kwargs = {} - print(assignments) - kernel = assignments.compile('gpu') - pystencils.show_code(kernel) - - with ManualCodeGenerationContext() as ctx: - - dh = GraphDataHandling((300, 300, 300)) - volume, projections = dh.add_arrays('volume, projection', gpu=True) - - dh.run_kernel(kernel, simulate_only=True) - - sim = Simulation(dh, ctx, cmake_target_name='projection') - sim._debug = False - sim.write_files() - - dir = '/localhome/seitz_local/projects/walberla/apps/projection/' - os.makedirs(dir, exist_ok=True) - for k, v in ctx.files.items(): - with open(join(dir, k), 'w') as file: - file.write(v) - - -def test_global_idx(): - with ManualCodeGenerationContext() as ctx: - from pystencils_walberla.special_symbols import aabb_min_vector, global_coord - - dh = GraphDataHandling((20, 30, 40)) - my_array = dh.add_array('my_array') - - ast = pystencils.create_kernel([pystencils.Assignment( - my_array.center, sum(aabb_min_vector))]).compile() - dh.run_kernel(ast, simulate_only=True) - dh.save_fields('my_array', expanduser('~/foo')) - ast = pystencils.create_kernel([pystencils.Assignment( - my_array.center, sum(global_coord))]).compile() - dh.run_kernel(ast, simulate_only=True) - dh.save_fields('my_array', expanduser('~/foo2')) - # ast = pystencils.create_kernel([pystencils.Assignment(my_array.center, sum(current_global_idx))]).compile() - # dh.run_kernel(ast, simulate_only=True) - - sim = Simulation(dh, ctx, cmake_target_name='foo') - sim._debug = False - sim.write_files() - - dir = '/localhome/seitz_local/projects/walberla/apps/foo/' - os.makedirs(dir, exist_ok=True) - for k, v in ctx.files.items(): - with open(join(dir, k), 'w') as file: - file.write(v) - - -def test_resolve_parameters(): - sym = TypedSymbol('s', create_type('double')) - sym2 = TypedSymbol('t', create_type('double')) - - block_forest = UniformBlockforestFromConfig() - - module = WalberlaModule(WalberlaMain(Block([ - block_forest, - ResolveUndefinedSymbols( - Block([ - SympyAssignment(sym, 1 + sym2), - ]), 'parameters') - ]))) - - print(module)