diff --git a/cmake/waLBerlaFunctions.cmake b/cmake/waLBerlaFunctions.cmake index 320afbb1de3518c1ccb7a25f5cdb7be3a25dd71e..f0f5296614c5c06849ef6f1ac74d9743f53d4f44 100644 --- a/cmake/waLBerlaFunctions.cmake +++ b/cmake/waLBerlaFunctions.cmake @@ -211,6 +211,7 @@ function ( waLBerla_add_executable ) set( generatedSourceFiles ) set( generatorSourceFiles ) handle_python_codegen(sourceFiles generatedSourceFiles generatorSourceFiles codeGenRequired ${sourceFiles}) + if( NOT WALBERLA_BUILD_WITH_CODEGEN AND codeGenRequired) message(STATUS "Skipping ${ARG_NAME} since pystencils code generation is not enabled") return() diff --git a/cmake/waLBerlaHelperFunctions.cmake b/cmake/waLBerlaHelperFunctions.cmake index f3fdc0fcd8ea10828ebb5d58f98ed7a52d2fd1b9..face2f95f2fdb187cefc274fe314bfc20875b5d0 100644 --- a/cmake/waLBerlaHelperFunctions.cmake +++ b/cmake/waLBerlaHelperFunctions.cmake @@ -19,14 +19,17 @@ endfunction ( add_flag ) ####################################################################################################################### # -# Function to handle source files of type .gen.py and .gen.cuda.py +# Function to handle python code generation files # -# files .gen.py generate a .h and a .cpp file -# files .gen.cuda.py generate a .h and a .cu file -# Takes a list of source files that contain .py files, and returns a list of source files -# where the generated version are added and the .py files are removed. -# Additionally creates a custom build rule for the code generation +# parameters: +# sourceFilesOut: variable where source files without python files are written to +# generatedSourceFilesOut: variable where generated source files (with custom command) are written to +# generatorsOut: only the python files that have been passed +# codeGenRequired: true if at least one python file was part of the sources # +# The list of generated files is determined via the pystencils_walberla package mechanism. +# The python script, when called with -l, should return a semicolon-separated list of generated files +# if this list changes, CMake has to be run manually again. ####################################################################################################################### function( handle_python_codegen sourceFilesOut generatedSourceFilesOut generatorsOut codeGenRequiredOut ) set(result ) @@ -34,25 +37,27 @@ function( handle_python_codegen sourceFilesOut generatedSourceFilesOut generator set(generatorsResult ) set(codeGenRequired NO) foreach( sourceFile ${ARGN} ) - if( ${sourceFile} MATCHES ".*\\.gen\\.py$" ) - get_filename_component(sourceFileName ${sourceFile} NAME) - if( ${sourceFileName} MATCHES ".*\\.cuda\\.gen\\.py$" ) - string(REPLACE ".cuda.gen.py" ".h" genHeaderFile ${sourceFileName}) - string(REPLACE ".cuda.gen.py" ".cu" genSourceFile ${sourceFileName}) - else() - string(REPLACE ".gen.py" ".h" genHeaderFile ${sourceFileName}) - string(REPLACE ".gen.py" ".cpp" genSourceFile ${sourceFileName}) - endif() - list(APPEND generatedResult ${CMAKE_CURRENT_BINARY_DIR}/${genSourceFile} - ${CMAKE_CURRENT_BINARY_DIR}/${genHeaderFile}) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${genSourceFile} - ${CMAKE_CURRENT_BINARY_DIR}/${genHeaderFile} - DEPENDS ${sourceFile} - COMMAND ${PYTHON_EXECUTABLE} ${sourceFile} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) - list(APPEND generatorsResult ${sourceFile} ) + if( ${sourceFile} MATCHES ".*\\.py$" ) set(codeGenRequired YES) + if( WALBERLA_BUILD_WITH_CODEGEN) + execute_process(COMMAND ${PYTHON_EXECUTABLE} ${sourceFile} -l + OUTPUT_VARIABLE generatedSourceFiles) + string(REGEX REPLACE "\n$" "" generatedSourceFiles "${generatedSourceFiles}") + + set(generatedWithAbsolutePath ) + foreach( filename ${generatedSourceFiles} ) + list(APPEND generatedWithAbsolutePath ${CMAKE_CURRENT_BINARY_DIR}/${filename}) + endforeach() + + list(APPEND generatedResult ${generatedWithAbsolutePath} ) + list(APPEND generatorsResult ${sourceFile} ) + + add_custom_command(OUTPUT ${generatedWithAbsolutePath} + DEPENDS ${sourceFile} + COMMAND ${PYTHON_EXECUTABLE} ${sourceFile} -g + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) + endif() else() list(APPEND result ${sourceFile}) endif() diff --git a/python/waLBerla/tools/jobscripts/__init__.py b/python/waLBerla/tools/jobscripts/__init__.py index 0a006cd3289ddd6b99f47ef21a8ecf948a2fd581..cafc3408aa0d926410aaef882e86ce1c359b34ea 100644 --- a/python/waLBerla/tools/jobscripts/__init__.py +++ b/python/waLBerla/tools/jobscripts/__init__.py @@ -8,6 +8,8 @@ from waLBerla.tools.jobscripts.hornet import createJobscript as _cr_hor from waLBerla.tools.jobscripts.supermuc import createJobscript as _cr_supermuc from waLBerla.tools.jobscripts.supermuc_phase2 import createJobscript as _cr_supermuc2 from waLBerla.tools.jobscripts.juqueen import createJobscript as _cr_juqueen +from waLBerla.tools.jobscripts.pizdaint_hybrid import createJobscript as _cr_pizdainth + def createJobscript(*args, **kwargs): """ @@ -43,6 +45,6 @@ def createJobscript(*args, **kwargs): if kwargs['machine'].lower() == 'supermuc_phase2': return _cr_supermuc2 ( *args, **kwargs ) if kwargs['machine'].lower() == 'juqueen' : return _cr_juqueen ( *args, **kwargs ) if kwargs['machine'].lower() == 'hornet' : return _cr_hornet ( *args, **kwargs ) - - raise ValueError( "Unknown Machine: supported machines <supermuc,supermuc_phase2,juqueen,hornet>" ) + if kwargs['machine'].lower() == 'pizdaint_hybrid': return _cr_pizdainth ( *args, **kwargs ) + raise ValueError( "Unknown Machine: supported machines <supermuc,supermuc_phase2,juqueen,hornet,pizdaint_hybrid>" ) \ No newline at end of file diff --git a/tests/cuda/CMakeLists.txt b/tests/cuda/CMakeLists.txt index 364b8bbea1b3980955955b22d3795ffc4048a2f9..7cde4254bbfbe376d04d666d23fdfb81b73f11eb 100644 --- a/tests/cuda/CMakeLists.txt +++ b/tests/cuda/CMakeLists.txt @@ -17,8 +17,7 @@ waLBerla_compile_test( FILES FieldIndexing3DTest.cpp FieldIndexing3DTest.cu ) waLBerla_execute_test( NAME FieldIndexing3DTest ) waLBerla_compile_test( FILES codegen/CodegenJacobiGPU.cpp - codegen/JacobiKernel2D.cuda.gen.py - codegen/JacobiKernel3D.cuda.gen.py + codegen/CudaJacobiKernel.py DEPENDS blockforest timeloop gui ) waLBerla_execute_test( NAME CodegenJacobiGPU ) diff --git a/tests/cuda/codegen/CodegenJacobiGPU.cpp b/tests/cuda/codegen/CodegenJacobiGPU.cpp index f81ecf1a6c2a2c91481b5203b3ecad99489865b8..a8ebd370e44f6304ec2f0f6c17c8028b65ff10e1 100644 --- a/tests/cuda/codegen/CodegenJacobiGPU.cpp +++ b/tests/cuda/codegen/CodegenJacobiGPU.cpp @@ -18,8 +18,8 @@ // //====================================================================================================================== -#include "JacobiKernel2D.h" -#include "JacobiKernel3D.h" +#include "CudaJacobiKernel2D.h" +#include "CudaJacobiKernel3D.h" #include "cuda/HostFieldAllocator.h" #include "blockforest/Initialization.h" @@ -110,7 +110,7 @@ void testJacobi2D() // Registering the sweep timeloop.add() << BeforeFunction( commScheme, "Communication" ) - << Sweep( pystencils::JacobiKernel2D(gpuField, 1.0), "Jacobi Kernel" ); + << Sweep( pystencils::CudaJacobiKernel2D(gpuField, 1.0), "Jacobi Kernel" ); cuda::fieldCpy<GPUField, ScalarField>( blocks, gpuField, cpuFieldID ); @@ -165,7 +165,7 @@ void testJacobi3D() // Registering the sweep timeloop.add() << BeforeFunction( commScheme, "Communication" ) - << Sweep( pystencils::JacobiKernel3D(gpuField, 1.0), "Jacobi Kernel" ); + << Sweep( pystencils::CudaJacobiKernel3D(gpuField, 1.0), "Jacobi Kernel" ); cuda::fieldCpy<GPUField, ScalarField>( blocks, gpuField, cpuFieldID ); diff --git a/tests/cuda/codegen/CudaJacobiKernel.py b/tests/cuda/codegen/CudaJacobiKernel.py new file mode 100644 index 0000000000000000000000000000000000000000..d30da2edcb663a351634490c93d503742e34e418 --- /dev/null +++ b/tests/cuda/codegen/CudaJacobiKernel.py @@ -0,0 +1,17 @@ +from pystencils_walberla.sweep import Sweep +from pystencils_walberla.cmake_integration import codegen + +def jacobi2D(sweep): + src = sweep.field("f1") + dst = sweep.temporaryField(src) + + dst[0, 0] @= (src[1, 0] + src[-1, 0] + src[0, 1] + src[0, -1]) / (4 * S.h ** 2) + +def jacobi3D(sweep): + src = sweep.field("f1") + dst = sweep.temporaryField(src) + + dst[0,0,0] @= (src[1,0,0] + src[-1,0,0] + src[0,1,0] + src[0, -1, 0] + src[0, 0, 1] + src[0, 0 , -1] ) / (6 * S.h**2) + +Sweep.generate('CudaJacobiKernel2D', jacobi2D, dim=2, target='gpu') +Sweep.generate('CudaJacobiKernel3D', jacobi3D, dim=3, target='gpu') \ No newline at end of file diff --git a/tests/cuda/codegen/JacobiKernel2D.cuda.gen.py b/tests/cuda/codegen/JacobiKernel2D.cuda.gen.py deleted file mode 100644 index ca6fca69cd5702bb2ec856b312f4e52890f1ec64..0000000000000000000000000000000000000000 --- a/tests/cuda/codegen/JacobiKernel2D.cuda.gen.py +++ /dev/null @@ -1,12 +0,0 @@ -from pystencils_walberla import Sweep - -k = Sweep(dim=2) - -src = k.field("f1") -dst = k.temporaryField(src) -h = k.constant("h") - -rhs = (src[1,0] + src[-1,0] + src[0,1] + src[0, -1] ) / (4 * h**2) -k.addEq(dst[0,0], rhs) - -k.generate() diff --git a/tests/cuda/codegen/JacobiKernel3D.cuda.gen.py b/tests/cuda/codegen/JacobiKernel3D.cuda.gen.py deleted file mode 100644 index 32ac6d17eff7cd85a103c38383e000f678ca04d9..0000000000000000000000000000000000000000 --- a/tests/cuda/codegen/JacobiKernel3D.cuda.gen.py +++ /dev/null @@ -1,12 +0,0 @@ -from pystencils_walberla import Sweep - -k = Sweep(dim=3) - -src = k.field("f1") -dst = k.temporaryField(src) -h = k.constant("h") - -rhs = (src[1,0,0] + src[-1,0,0] + src[0,1,0] + src[0, -1, 0] + src[0, 0, 1] + src[0, 0 , -1] ) / (6 * h**2) -k.addEq(dst[0,0,0], rhs) - -k.generate() diff --git a/tests/field/CMakeLists.txt b/tests/field/CMakeLists.txt index d7534a81375d2e85498a6c8fae5b51c0c5b0a68d..47a1549e231c0265c4bd5f55602a5082ed63bf87 100644 --- a/tests/field/CMakeLists.txt +++ b/tests/field/CMakeLists.txt @@ -59,7 +59,7 @@ endif( WALBERLA_BUILD_WITH_MPI ) # CodeGen Tests -waLBerla_compile_test( FILES codegen/CodegenJacobiCPU.cpp codegen/JacobiKernel2D.gen.py codegen/JacobiKernel3D.gen.py +waLBerla_compile_test( FILES codegen/CodegenJacobiCPU.cpp codegen/JacobiKernel.py DEPENDS gui timeloop ) waLBerla_execute_test( NAME CodegenJacobiCPU ) diff --git a/tests/field/codegen/JacobiKernel.py b/tests/field/codegen/JacobiKernel.py new file mode 100644 index 0000000000000000000000000000000000000000..bcdc4c72e5f3999fb66ccc98bc827fbeb9991eac --- /dev/null +++ b/tests/field/codegen/JacobiKernel.py @@ -0,0 +1,16 @@ +from pystencils_walberla.sweep import Sweep + +def jacobi2D(sweep): + src = sweep.field("f1") + dst = sweep.temporaryField(src) + + dst[0, 0] @= (src[1, 0] + src[-1, 0] + src[0, 1] + src[0, -1]) / (4 * S.h ** 2) + +def jacobi3D(sweep): + src = sweep.field("f1") + dst = sweep.temporaryField(src) + + dst[0,0,0] @= (src[1,0,0] + src[-1,0,0] + src[0,1,0] + src[0, -1, 0] + src[0, 0, 1] + src[0, 0 , -1] ) / (6 * S.h**2) + +Sweep.generate('JacobiKernel2D', jacobi2D, dim=2) +Sweep.generate('JacobiKernel3D', jacobi3D, dim=3) \ No newline at end of file diff --git a/tests/field/codegen/JacobiKernel2D.gen.py b/tests/field/codegen/JacobiKernel2D.gen.py deleted file mode 100644 index ca6fca69cd5702bb2ec856b312f4e52890f1ec64..0000000000000000000000000000000000000000 --- a/tests/field/codegen/JacobiKernel2D.gen.py +++ /dev/null @@ -1,12 +0,0 @@ -from pystencils_walberla import Sweep - -k = Sweep(dim=2) - -src = k.field("f1") -dst = k.temporaryField(src) -h = k.constant("h") - -rhs = (src[1,0] + src[-1,0] + src[0,1] + src[0, -1] ) / (4 * h**2) -k.addEq(dst[0,0], rhs) - -k.generate() diff --git a/tests/field/codegen/JacobiKernel3D.gen.py b/tests/field/codegen/JacobiKernel3D.gen.py deleted file mode 100644 index 32ac6d17eff7cd85a103c38383e000f678ca04d9..0000000000000000000000000000000000000000 --- a/tests/field/codegen/JacobiKernel3D.gen.py +++ /dev/null @@ -1,12 +0,0 @@ -from pystencils_walberla import Sweep - -k = Sweep(dim=3) - -src = k.field("f1") -dst = k.temporaryField(src) -h = k.constant("h") - -rhs = (src[1,0,0] + src[-1,0,0] + src[0,1,0] + src[0, -1, 0] + src[0, 0, 1] + src[0, 0 , -1] ) / (6 * h**2) -k.addEq(dst[0,0,0], rhs) - -k.generate() diff --git a/tests/lbm/codegen/SrtWithForceField.cpp b/tests/lbm/codegen/SrtWithForceField.cpp index c93dde10f184bd9e5b8d6d7fce05b5c66020e030..57e8674bf64f64d896ed151e839fd4c95883c33b 100644 --- a/tests/lbm/codegen/SrtWithForceField.cpp +++ b/tests/lbm/codegen/SrtWithForceField.cpp @@ -26,9 +26,16 @@ #include "field/all.h" #include "geometry/all.h" #include "gui/all.h" -#include "lbm/all.h" #include "timeloop/all.h" +#include "lbm/field/PdfField.h" +#include "lbm/field/AddToStorage.h" +#include "lbm/communication/PdfFieldPackInfo.h" +#include "lbm/gui/Connection.h" +#include "lbm/vtk/VTKOutput.h" + +#include "MyUBB.h" +#include "MyNoSlip.h" using namespace walberla; @@ -60,8 +67,6 @@ int main( int argc, char ** argv ) const double remainingTimeLoggerFrequency = parameters.getParameter< double >( "remainingTimeLoggerFrequency", 3.0 ); // in seconds - // create force field - // create fields BlockDataID forceFieldId = field::addToStorage<ForceField_T>(blocks, "Force", real_t(0.0) ); @@ -72,18 +77,17 @@ int main( int argc, char ** argv ) // create and initialize boundary handling const FlagUID fluidFlagUID( "Fluid" ); + auto boundariesConfig = walberlaEnv.config()->getOneBlock( "Boundaries" ); - typedef lbm::DefaultBoundaryHandlingFactory< LatticeModel_T, FlagField_T > BHFactory; + lbm::MyUBB ubb(blocks, pdfFieldId); + lbm::MyNoSlip noSlip(blocks, pdfFieldId); - BlockDataID boundaryHandlingId = BHFactory::addBoundaryHandlingToStorage( blocks, "boundary handling", flagFieldId, pdfFieldId, fluidFlagUID, - boundariesConfig.getParameter< Vector3<real_t> >( "velocity0", Vector3<real_t>() ), - boundariesConfig.getParameter< Vector3<real_t> >( "velocity1", Vector3<real_t>() ), - boundariesConfig.getParameter< real_t > ( "pressure0", real_c( 1.0 ) ), - boundariesConfig.getParameter< real_t > ( "pressure1", real_c( 1.0 ) ) ); + geometry::initBoundaryHandling<FlagField_T>(*blocks, flagFieldId, boundariesConfig); + geometry::setNonBoundaryCellsToDomain<FlagField_T>(*blocks, flagFieldId, fluidFlagUID); - geometry::initBoundaryHandling<BHFactory::BoundaryHandling>( *blocks, boundaryHandlingId, boundariesConfig ); - geometry::setNonBoundaryCellsToDomain<BHFactory::BoundaryHandling> ( *blocks, boundaryHandlingId ); + ubb.fillFromFlagField<FlagField_T>( blocks, flagFieldId, FlagUID("UBB"), fluidFlagUID ); + noSlip.fillFromFlagField<FlagField_T>( blocks, flagFieldId, FlagUID("NoSlip"), fluidFlagUID ); // create time loop SweepTimeloop timeloop( blocks->getBlockStorage(), timesteps ); @@ -94,7 +98,8 @@ int main( int argc, char ** argv ) // add LBM sweep and communication to time loop timeloop.add() << BeforeFunction( communication, "communication" ) - << Sweep( BHFactory::BoundaryHandling::getBlockSweep( boundaryHandlingId ), "boundary handling" ); + << Sweep( noSlip, "noSlip boundary" ); + timeloop.add() << Sweep( ubb, "ubb boundary" ); timeloop.add() << Sweep( LatticeModel_T::Sweep( pdfFieldId ), "LB stream & collide" ); // LBM stability check diff --git a/tests/lbm/codegen/SrtWithForceFieldModel.gen.py b/tests/lbm/codegen/SrtWithForceFieldModel.gen.py index d847c51c5d07f9751209d323d02958d71b395a91..2ecb139fbbba9d4562a6781441f2d929f9404086 100644 --- a/tests/lbm/codegen/SrtWithForceFieldModel.gen.py +++ b/tests/lbm/codegen/SrtWithForceFieldModel.gen.py @@ -1,6 +1,11 @@ import sympy as sp +from lbmpy.boundaries import NoSlip, UBB from lbmpy_walberla import Field, generateLatticeModelFiles, RefinementScaling +from lbmpy.creationfunctions import createLatticeBoltzmannMethod +from lbmpy_walberla.boundary import createBoundaryClass +from pystencils_walberla.cmake_integration import codegen +# ------------- Lattice Model ------------------------------ forceField = Field.createGeneric('force', spatialDimensions=3, indexDimensions=1, layout='fzyx') force = [forceField(0), forceField(1), forceField(2)] @@ -10,6 +15,21 @@ scaling = RefinementScaling() scaling.addStandardRelaxationRateScaling(omega) scaling.addForceScaling(forceField) -generateLatticeModelFiles(method='srt', stencil='D3Q19', forceModel='guo', force=force, +generateLatticeModelFiles(className='SrtWithForceFieldModel', + method='srt', stencil='D3Q19', forceModel='guo', force=force, relaxationRates=[omega], refinementScaling=scaling) + +def genBoundary(): + boundary = UBB([0.05, 0, 0], dim=3, name="MyUBB") + method = createLatticeBoltzmannMethod(stencil='D3Q19', method='srt') + return createBoundaryClass(boundary, method) + +def genNoSlip(): + boundary = NoSlip(name='MyNoSlip') + method = createLatticeBoltzmannMethod(stencil='D3Q19', method='srt') + return createBoundaryClass(boundary, method) + +codegen.register(['MyUBB.h', 'MyUBB.cpp'], genBoundary) +codegen.register(['MyNoSlip.h', 'MyNoSlip.cpp',], genNoSlip) +