diff --git a/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.cpp b/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.cpp index bcb87d151db8a169f86757acdaf9d68486fe560e..b4275d395532f9e90a985ccec1986be1b44d7154 100644 --- a/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.cpp +++ b/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.cpp @@ -155,7 +155,7 @@ int main( int argc, char **argv ) auto remainingTimeLoggerFrequency = parameters.getParameter< double >( "remainingTimeLoggerFrequency", -1.0 ); // in seconds if (remainingTimeLoggerFrequency > 0) { - auto logger = timing::RemainingTimeLogger( timeLoop.getNrOfTimeSteps() * outerIterations, remainingTimeLoggerFrequency ); + auto logger = timing::RemainingTimeLogger( timeLoop.getNrOfTimeSteps() * uint_c( outerIterations ), remainingTimeLoggerFrequency ); timeLoop.addFuncAfterTimeStep( logger, "remaining time logger" ); } diff --git a/python/lbmpy_walberla/templates/LatticeModel.tmpl.cpp b/python/lbmpy_walberla/templates/LatticeModel.tmpl.cpp index 2b2065cc7600e4d230d7d21f801e8e1044bb7701..b10bc3948026ad1b46b0dfd0db8eba1c86ecdfef 100644 --- a/python/lbmpy_walberla/templates/LatticeModel.tmpl.cpp +++ b/python/lbmpy_walberla/templates/LatticeModel.tmpl.cpp @@ -66,7 +66,7 @@ void {{class_name}}::Sweep::streamCollide( IBlock * block, const uint_t numberOf {{stream_collide_kernel|generate_block_data_to_field_extraction(parameters=['pdfs', 'pdfs_tmp'])|indent(4)}} auto & lm = dynamic_cast< lbm::PdfField<{{class_name}}> * > (pdfs)->latticeModel(); - WALBERLA_ASSERT_EQUAL( *(lm.blockId), block->getId() ); + WALBERLA_ASSERT_EQUAL( *(lm.blockId_), block->getId() ); {{stream_collide_kernel|generate_refs_for_kernel_parameters(prefix='lm.', parameters_to_ignore=['pdfs', 'pdfs_tmp'])|indent(4) }} {{stream_collide_kernel|generate_call('cell_idx_c(numberOfGhostLayersToInclude)')|indent(4)}} @@ -78,7 +78,7 @@ void {{class_name}}::Sweep::collide( IBlock * block, const uint_t numberOfGhostL {{collide_kernel|generate_block_data_to_field_extraction(parameters=['pdfs'])|indent(4)}} auto & lm = dynamic_cast< lbm::PdfField<{{class_name}}> * > (pdfs)->latticeModel(); - WALBERLA_ASSERT_EQUAL( *(lm.blockId), block->getId() ); + WALBERLA_ASSERT_EQUAL( *(lm.blockId_), block->getId() ); {{collide_kernel|generate_refs_for_kernel_parameters(prefix='lm.', parameters_to_ignore=['pdfs', 'pdfs_tmp'])|indent(4) }} {{collide_kernel|generate_call('cell_idx_c(numberOfGhostLayersToInclude)')|indent(4)}} diff --git a/python/lbmpy_walberla/templates/LatticeModel.tmpl.h b/python/lbmpy_walberla/templates/LatticeModel.tmpl.h index be160e99e89d596f86511a97db314e35aeaaca18..df188fa32081427ae5ea4a05e81f7fe5b63ea1d4 100644 --- a/python/lbmpy_walberla/templates/LatticeModel.tmpl.h +++ b/python/lbmpy_walberla/templates/LatticeModel.tmpl.h @@ -134,17 +134,17 @@ public: private: void configureBlock(IBlock * block, StructuredBlockStorage * storage) { - {{stream_collide_kernel|generate_block_data_to_field_extraction(lmIgnores+lmOffsets, no_declarations=True)|indent(8)}} + {{stream_collide_kernel|generate_block_data_to_field_extraction(lmIgnores+lmOffsets, no_declarations=True, update_member=True)|indent(8)}} {% if need_block_offsets[0] -%} - block_offset_0 = uint32_c(storage->getBlockCellBB(*block).xMin()); + block_offset_0_ = uint32_c(storage->getBlockCellBB(*block).xMin()); {% endif -%} {%- if need_block_offsets[1] -%} - block_offset_1 = uint32_c(storage->getBlockCellBB(*block).yMin()); + block_offset_1_ = uint32_c(storage->getBlockCellBB(*block).yMin()); {% endif -%} {%- if need_block_offsets[2] -%} - block_offset_2 = uint32_c(storage->getBlockCellBB(*block).zMin()); + block_offset_2_ = uint32_c(storage->getBlockCellBB(*block).zMin()); {% endif %} - blockId = &block->getId(); + blockId_ = &block->getId(); {% if refinement_scaling_info -%} const uint_t targetLevel = block->getBlockStorage().getLevel(*block); @@ -182,7 +182,7 @@ private: // Updated by configureBlock: {{stream_collide_kernel|generate_block_data_to_field_extraction(lmIgnores, declarations_only=True)|indent(4)}} - const IBlockID * blockId; + const IBlockID * blockId_; uint_t currentLevel; // Backend classes can access private members: diff --git a/python/lbmpy_walberla/walberla_lbm_generation.py b/python/lbmpy_walberla/walberla_lbm_generation.py index 05e98a96fe31c1fd001c400f696b4e7c143a762c..7e32867b05b1d8b9bd15b4da09b5c4d20d3cb3cd 100644 --- a/python/lbmpy_walberla/walberla_lbm_generation.py +++ b/python/lbmpy_walberla/walberla_lbm_generation.py @@ -68,6 +68,15 @@ def __lattice_model(generation_context, class_name, lb_method, stream_collide_as if refinement_scaling: refinement_scaling_info = [ (e0,e1,expression_to_code(e2, '', dtype=dtype)) for e0,e1,e2 in refinement_scaling.scaling_info ] + # append '_' to entries since they are used as members + for i in range(len(refinement_scaling_info)): + updated_entry = (refinement_scaling_info[i][0], + refinement_scaling_info[i][1].replace(refinement_scaling_info[i][1], + refinement_scaling_info[i][1] + '_'), + refinement_scaling_info[i][2].replace(refinement_scaling_info[i][1], + refinement_scaling_info[i][1] + '_'), + ) + refinement_scaling_info[i] = updated_entry else: refinement_scaling_info = None @@ -147,8 +156,6 @@ def generate_lattice_model(generation_context, class_name, collision_rule, refin refinement_scaling) - - class RefinementScaling: level_scale_factor = sp.Symbol("level_scale_factor") @@ -217,18 +224,27 @@ def stencil_switch_statement(stencil, values): def field_and_symbol_substitute(expr, variable_prefix="lm.", variables_without_prefix=[]): variables_without_prefix = [v.name if isinstance(v, sp.Symbol) else v for v in variables_without_prefix] substitutions = {} + # check for member access + if variable_prefix.endswith('.'): + postfix = '_' + else: + postfix = '' for sym in expr.atoms(sp.Symbol): if isinstance(sym, Field.Access): fa = sym prefix = "" if fa.field.name in variables_without_prefix else variable_prefix + if prefix.endswith('.'): + postfix2 = '_' + else: + postfix2 = '' if fa.field.index_dimensions == 0: - substitutions[fa] = sp.Symbol("%s%s->get(x,y,z)" % (prefix, fa.field.name)) + substitutions[fa] = sp.Symbol("%s%s->get(x,y,z)" % (prefix, fa.field.name + postfix2)) else: assert fa.field.index_dimensions == 1, "walberla supports only 0 or 1 index dimensions" - substitutions[fa] = sp.Symbol("%s%s->get(x,y,z,%s)" % (prefix, fa.field.name, fa.index[0])) + substitutions[fa] = sp.Symbol("%s%s->get(x,y,z,%s)" % (prefix, fa.field.name + postfix2, fa.index[0])) else: if sym.name not in variables_without_prefix: - substitutions[sym] = sp.Symbol(variable_prefix + sym.name) + substitutions[sym] = sp.Symbol(variable_prefix + sym.name + postfix) return expr.subs(substitutions) @@ -244,10 +260,19 @@ def expression_to_code(expr, variable_prefix="lm.", variables_without_prefix=[], """ return cpp_printer.doprint(type_expr(field_and_symbol_substitute(expr, variable_prefix, variables_without_prefix),dtype=dtype)) + def type_expr(eq, dtype): - eq=type_all_numbers(eq,dtype=dtype) + def recurse(expr): + for i in range(len(expr.args)): + if expr.args[i] == sp.Rational or expr.args[i] == sp.Float: + expr.args[i] = type_all_numbers(expr.args[i], dtype=dtype) + else: + recurse(expr.args[i]) + + recurse(eq) return eq.subs({s: TypedSymbol(s.name, dtype) for s in eq.atoms(sp.Symbol)}) + def equations_to_code(equations, variable_prefix="lm.", variables_without_prefix=[], dtype="double"): if isinstance(equations, AssignmentCollection): diff --git a/python/pystencils_walberla/jinja_filters.py b/python/pystencils_walberla/jinja_filters.py index 174b9dfecbaf6bd0c1df4d391eca5cb1a5e7c7c3..eb209237bfdf54a64bee209c8d1a50e9d122e06f 100644 --- a/python/pystencils_walberla/jinja_filters.py +++ b/python/pystencils_walberla/jinja_filters.py @@ -1,5 +1,6 @@ import jinja2 import sympy as sp +import re from pystencils import TypedSymbol from pystencils.backends.cbackend import generate_c @@ -90,7 +91,7 @@ def generate_definition(kernel_info, target='cpu'): def field_extraction_code(field, is_temporary, declaration_only=False, - no_declaration=False, is_gpu=False): + no_declaration=False, is_gpu=False, update_member=False): """Returns code string for getting a field pointer. This can happen in two ways: either the field is extracted from a walberla block, or a temporary field to swap is @@ -102,9 +103,10 @@ def field_extraction_code(field, is_temporary, declaration_only=False, declaration_only: only create declaration instead of the full code no_declaration: create the extraction code, and assume that declarations are elsewhere is_gpu: if the field is a GhostLayerField or a GpuField + update_member: specify if function is used inside a constructor; add _ to members """ - # Determine size of f coordinate which is a template parameter +# Determine size of f coordinate which is a template parameter f_size = get_field_fsize(field) field_name = field.name dtype = get_base_type(field.dtype) @@ -114,15 +116,18 @@ def field_extraction_code(field, is_temporary, declaration_only=False, dtype = get_base_type(field.dtype) field_type = make_field_type(dtype, f_size, is_gpu) if declaration_only: - return "%s * %s;" % (field_type, field_name) + return "%s * %s_;" % (field_type, field_name) else: prefix = "" if no_declaration else "auto " - return "%s%s = block->uncheckedFastGetData< %s >(%sID);" % (prefix, field_name, field_type, field_name) + if update_member: + return "%s%s_ = block->uncheckedFastGetData< %s >(%sID);" % (prefix, field_name, field_type, field_name) + else: + return "%s%s = block->uncheckedFastGetData< %s >(%sID);" % (prefix, field_name, field_type, field_name) else: assert field_name.endswith('_tmp') original_field_name = field_name[:-len('_tmp')] if declaration_only: - return "%s * %s;" % (field_type, field_name) + return "%s * %s_;" % (field_type, field_name) else: declaration = "{type} * {tmp_field_name};".format(type=field_type, tmp_field_name=field_name) tmp_field_str = temporary_fieldTemplate.format(original_field_name=original_field_name, @@ -132,7 +137,7 @@ def field_extraction_code(field, is_temporary, declaration_only=False, @jinja2.contextfilter def generate_block_data_to_field_extraction(ctx, kernel_info, parameters_to_ignore=(), parameters=None, - declarations_only=False, no_declarations=False): + declarations_only=False, no_declarations=False, update_member=False): """Generates code that extracts all required fields of a kernel from a walberla block storage.""" if parameters is not None: assert parameters_to_ignore == () @@ -154,8 +159,12 @@ def generate_block_data_to_field_extraction(ctx, kernel_info, parameters_to_igno 'no_declaration': no_declarations, 'is_gpu': ctx['target'] == 'gpu', } - result = "\n".join(field_extraction_code(field=field, is_temporary=False, **args) for field in normal_fields) + "\n" - result += "\n".join(field_extraction_code(field=field, is_temporary=True, **args) for field in temporary_fields) + result = "\n".join( + field_extraction_code(field=field, is_temporary=False, update_member=update_member, **args) for field in + normal_fields) + "\n" + result += "\n".join( + field_extraction_code(field=field, is_temporary=True, update_member=update_member, **args) for field in + temporary_fields) return result @@ -163,7 +172,7 @@ def generate_refs_for_kernel_parameters(kernel_info, prefix, parameters_to_ignor symbols = {p.field_name for p in kernel_info.parameters if p.is_field_pointer} symbols.update(p.symbol.name for p in kernel_info.parameters if not p.is_field_parameter) symbols.difference_update(parameters_to_ignore) - return "\n".join("auto & %s = %s%s;" % (s, prefix, s) for s in symbols) + return "\n".join("auto & %s = %s%s_;" % (s, prefix, s) for s in symbols) @jinja2.contextfilter @@ -256,6 +265,7 @@ def generate_call(ctx, kernel_info, ghost_layers_to_include=0, cell_interval=Non kernel_call_lines.append("const %s %s = %s;" % (type_str, param.symbol.name, shape)) call_parameters = ", ".join([p.symbol.name for p in ast_params]) + if not is_cpu: if not spatial_shape_symbols: spatial_shape_symbols = [p.symbol for p in ast_params if p.is_field_shape] @@ -295,7 +305,7 @@ def generate_constructor_initializer_list(kernel_info, parameters_to_ignore=None if param.is_field_pointer and param.field_name not in parameters_to_ignore: parameter_initializer_list.append("%sID(%sID_)" % (param.field_name, param.field_name)) elif not param.is_field_parameter and param.symbol.name not in parameters_to_ignore: - parameter_initializer_list.append("%s(%s_)" % (param.symbol.name, param.symbol.name)) + parameter_initializer_list.append("%s_(%s)" % (param.symbol.name, param.symbol.name)) return ", ".join(parameter_initializer_list) @@ -314,8 +324,8 @@ def generate_constructor_parameters(kernel_info, parameters_to_ignore=None): if param.is_field_pointer and param.field_name not in parameters_to_ignore: parameter_list.append("BlockDataID %sID_" % (param.field_name, )) elif not param.is_field_parameter and param.symbol.name not in parameters_to_ignore: - parameter_list.append("%s %s_" % (param.symbol.dtype, param.symbol.name,)) - varying_parameters = ["%s %s_" % e for e in varying_parameters] + parameter_list.append("%s %s" % (param.symbol.dtype, param.symbol.name,)) + varying_parameters = ["%s %s" % e for e in varying_parameters] return ", ".join(parameter_list + varying_parameters) @@ -335,7 +345,7 @@ def generate_members(ctx, kernel_info, parameters_to_ignore=(), only_fields=Fals if param.is_field_pointer and param.field_name not in params_to_skip: result.append("BlockDataID %sID;" % (param.field_name, )) elif not param.is_field_parameter and param.symbol.name not in params_to_skip: - result.append("%s %s;" % (param.symbol.dtype, param.symbol.name,)) + result.append("%s %s_;" % (param.symbol.dtype, param.symbol.name,)) for field_name in kernel_info.temporary_fields: f = fields[field_name] @@ -348,7 +358,7 @@ def generate_members(ctx, kernel_info, parameters_to_ignore=(), only_fields=Fals result.append(temporary_fieldMemberTemplate.format(type=field_type, original_field_name=original_field_name)) if hasattr(kernel_info, 'varying_parameters'): - result.extend(["%s %s;" % e for e in kernel_info.varying_parameters]) + result.extend(["%s %s_;" % e for e in kernel_info.varying_parameters]) return "\n".join(result) diff --git a/python/pystencils_walberla/templates/Sweep.tmpl.cpp b/python/pystencils_walberla/templates/Sweep.tmpl.cpp index 8628e40a99beec142dc087831630c6cf189a78ff..ae15b45953455966605ad783ecbf5d2434a6b552 100644 --- a/python/pystencils_walberla/templates/Sweep.tmpl.cpp +++ b/python/pystencils_walberla/templates/Sweep.tmpl.cpp @@ -58,6 +58,7 @@ namespace {{namespace}} { void {{class_name}}::operator()( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream{% endif %} ) { {{kernel|generate_block_data_to_field_extraction|indent(4)}} + {{kernel|generate_refs_for_kernel_parameters(prefix='this->', parameters_to_ignore=['velocity', 'src', 'src_tmp', 'pdfs', 'pdfs_tmp'])|indent(4) }} {{kernel|generate_call(stream='stream')|indent(4)}} {{kernel|generate_swaps|indent(4)}} } @@ -77,6 +78,7 @@ void {{class_name}}::runOnCellInterval( const shared_ptr<StructuredBlockStorage> return; {{kernel|generate_block_data_to_field_extraction|indent(4)}} + {{kernel|generate_refs_for_kernel_parameters(prefix='this->', parameters_to_ignore=['velocity', 'src', 'src_tmp', 'pdfs', 'pdfs_tmp'])|indent(4) }} {{kernel|generate_call(stream='stream', cell_interval='ci')|indent(4)}} {{kernel|generate_swaps|indent(4)}} } diff --git a/tests/lbm/codegen/FluctuatingMRT.cpp b/tests/lbm/codegen/FluctuatingMRT.cpp index 24e5168feaf6bc8dc1a606f0cafad05a3b4329a2..27021afaa407725d8a7d3a7f20eaf5643b15a155 100644 --- a/tests/lbm/codegen/FluctuatingMRT.cpp +++ b/tests/lbm/codegen/FluctuatingMRT.cpp @@ -85,7 +85,7 @@ int main( int argc, char ** argv ) communication.addPackInfo( make_shared< lbm::PdfFieldPackInfo< LatticeModel_T > >( pdfFieldId ) ); // add LBM sweep and communication to time loop - timeloop.add() << BeforeFunction( [&](){ latticeModel.time_step = uint32_c(timeloop.getCurrentTimeStep()); }, "set RNG counter" ) + timeloop.add() << BeforeFunction( [&](){ latticeModel.time_step_ = uint32_c(timeloop.getCurrentTimeStep()); }, "set RNG counter" ) << BeforeFunction( communication, "communication" ) << Sweep( LatticeModel_T::Sweep( pdfFieldId ), "LB stream & collide" );