diff --git a/apps/showcases/CMakeLists.txt b/apps/showcases/CMakeLists.txt index f601fdd24ebb1454ae518db8405be992f9f0be57..c877683244060ac562f7162c7679285f62395b3a 100644 --- a/apps/showcases/CMakeLists.txt +++ b/apps/showcases/CMakeLists.txt @@ -11,6 +11,7 @@ if ( WALBERLA_BUILD_WITH_CODEGEN) add_subdirectory( Antidunes ) add_subdirectory( FlowAroundSphere ) + add_subdirectory( PorousMediaGPU ) if (WALBERLA_BUILD_WITH_PYTHON) add_subdirectory( PhaseFieldAllenCahn ) diff --git a/apps/showcases/PorousMediaGPU/CMakeLists.txt b/apps/showcases/PorousMediaGPU/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fdea6fdfa2482c26261aa781b1b0ac6bb79eb7b9 --- /dev/null +++ b/apps/showcases/PorousMediaGPU/CMakeLists.txt @@ -0,0 +1,28 @@ +waLBerla_link_files_to_builddir( *.py ) +waLBerla_link_files_to_builddir( *.prm ) +waLBerla_link_files_to_builddir( *.png ) +waLBerla_link_files_to_builddir( *.obj ) +waLBerla_link_files_to_builddir( *.stl ) +waLBerla_link_files_to_builddir( *.mtl ) + +waLBerla_generate_target_from_python(NAME PorousMediaGPUCodeGen + FILE PorousMediaGPU.py + OUT_FILES PorousMediaGPUSweepCollection.h PorousMediaGPUSweepCollection.${CODEGEN_FILE_SUFFIX} + PorousMediaGPUStorageSpecification.h PorousMediaGPUStorageSpecification.${CODEGEN_FILE_SUFFIX} + NoSlip.h NoSlip.${CODEGEN_FILE_SUFFIX} + UBB.h UBB.${CODEGEN_FILE_SUFFIX} + Outflow.h Outflow.${CODEGEN_FILE_SUFFIX} + PorousMediaGPUBoundaryCollection.h + PorousMediaGPUInfoHeader.h + PorousMediaGPUStaticDefines.h) + +if (WALBERLA_BUILD_WITH_CUDA OR WALBERLA_BUILD_WITH_HIP) + waLBerla_add_executable ( NAME PorousMediaGPU + FILES PorousMediaGPU.cpp Types.h InitializerFunctions.cpp + DEPENDS blockforest boundary core field gpu lbm_generated stencil timeloop vtk PorousMediaGPUCodeGen ) +else() + waLBerla_add_executable ( NAME PorousMediaGPU + FILES PorousMediaGPU.cpp Types.h InitializerFunctions.cpp + DEPENDS blockforest boundary core field lbm_generated stencil timeloop vtk PorousMediaGPUCodeGen ) + +endif(WALBERLA_BUILD_WITH_CUDA OR WALBERLA_BUILD_WITH_HIP) diff --git a/apps/showcases/PorousMediaGPU/InitializerFunctions.cpp b/apps/showcases/PorousMediaGPU/InitializerFunctions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3a921e31f04f52062ec3b153b730675a5ee1e49 --- /dev/null +++ b/apps/showcases/PorousMediaGPU/InitializerFunctions.cpp @@ -0,0 +1,51 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InitializerFunctions.cpp +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== +#include "core/logging/Initialization.h" +#include "core/math/Constants.h" + +#include "field/FlagField.h" +#include "field/communication/PackInfo.h" +#include "field/vtk/VTKWriter.h" + + +namespace walberla +{ +using PhaseField_T = GhostLayerField< real_t, 1 >; +using FlagField_T = FlagField< uint8_t >; + + + +void init_TPMS(const shared_ptr< StructuredBlockStorage >& blocks, const BlockDataID flagFieldID, + const FlagUID boundaryFlagUID, + const real_t kx, const real_t ky, const real_t kz) +{ + const real_t strut = real_c(0.0); + + for (auto& block : *blocks) + { + const auto flagField = block.template getData< FlagField_T >(flagFieldID); + const auto boundaryFlag = flagField->getOrRegisterFlag(boundaryFlagUID); + WALBERLA_FOR_ALL_CELLS_INCLUDING_GHOST_LAYER_XYZ(flagField, Cell globalCell; + blocks->transformBlockLocalToGlobalCell(globalCell, block, Cell(x, y, z)); + const real_t dist = cos(kx * x) * sin(ky * y) + cos(ky * y) * sin(kz * z) + cos(kz * z) * sin(kx * x); + if (dist >= strut) addFlag(flagField->get(x, y, z), boundaryFlag);) + } +} +} // namespace walberla diff --git a/apps/showcases/PorousMediaGPU/InitializerFunctions.h b/apps/showcases/PorousMediaGPU/InitializerFunctions.h new file mode 100644 index 0000000000000000000000000000000000000000..2dcdaf3aecbb7d04f16adc33a9895dacbc43f438 --- /dev/null +++ b/apps/showcases/PorousMediaGPU/InitializerFunctions.h @@ -0,0 +1,31 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InitializerFunctions.h +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#include "core/logging/Initialization.h" +#include "field/FlagField.h" + +#pragma once + +namespace walberla +{ +void init_TPMS(const shared_ptr< StructuredBlockStorage >& blocks, BlockDataID flagFieldID, + FlagUID boundaryFlagUID, real_t kx, real_t ky, real_t kz); + +} // namespace walberla diff --git a/apps/showcases/PorousMediaGPU/PorousMediaGPU.cpp b/apps/showcases/PorousMediaGPU/PorousMediaGPU.cpp new file mode 100644 index 0000000000000000000000000000000000000000..185a899703c3688e91106d1a7fc487c05289e27a --- /dev/null +++ b/apps/showcases/PorousMediaGPU/PorousMediaGPU.cpp @@ -0,0 +1,259 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file PorousMediaGPU.cpp +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#include "blockforest/Initialization.h" +#include "blockforest/StructuredBlockForest.h" +#include "blockforest/communication/UniformBufferedScheme.h" + +#include "core/Abort.h" +#include "core/DataTypes.h" +#include "core/SharedFunctor.h" +#include "core/debug/CheckFunctions.h" +#include "core/logging/Logging.h" +#include "core/math/Vector3.h" +#include "core/Environment.h" +#include "core/mpi/MPIManager.h" +#include "core/MemoryUsage.h" +#include "core/mpi/Reduce.h" +#include "core/timing/RemainingTimeLogger.h" +#include "core/timing/TimingPool.h" + +#include "field/AddToStorage.h" +#include "field/CellCounter.h" +#include "field/FlagField.h" +#include "field/StabilityChecker.h" +#include "field/adaptors/AdaptorCreators.h" +#include "field/iterators/FieldIterator.h" +#include "field/vtk/VTKWriter.h" +#include "field/vtk/FlagFieldCellFilter.h" + +#include "geometry/InitBoundaryHandling.h" + +#if defined(WALBERLA_BUILD_WITH_GPU_SUPPORT) +# include "gpu/AddGPUFieldToStorage.h" +# include "gpu/DeviceSelectMPI.h" +# include "gpu/ErrorChecking.h" +# include "gpu/FieldCopy.h" +# include "gpu/HostFieldAllocator.h" +# include "gpu/ParallelStreams.h" +# include "gpu/communication/UniformGPUScheme.h" +#endif + +#include "lbm_generated/communication/UniformGeneratedPdfPackInfo.h" +#include "lbm_generated/evaluation/PerformanceEvaluation.h" +#include "lbm_generated/field/AddToStorage.h" +#include "lbm_generated/field/PdfField.h" + +#if defined(WALBERLA_BUILD_WITH_GPU_SUPPORT) +# include "lbm_generated/gpu/AddToStorage.h" +# include "lbm_generated/gpu/GPUPdfField.h" +# include "lbm_generated/gpu/UniformGeneratedGPUPdfPackInfo.h" +#endif + +#include "timeloop/SweepTimeloop.h" +#include "vtk/VTKOutput.h" + +#include <cstdlib> +#include <iostream> +#include <memory> + +#include "InitializerFunctions.h" +#include "Types.h" + +#include "PorousMediaGPUStaticDefines.h" + +using namespace walberla; +using macroFieldType = VelocityField_T::value_type; + +using BoundaryCollection_T = lbm::PorousMediaGPUBoundaryCollection< FlagField_T >; +using SweepCollection_T = lbm::PorousMediaGPUSweepCollection; + +#if defined(WALBERLA_BUILD_WITH_GPU_SUPPORT) +using GPUPdfField_T = lbm_generated::GPUPdfField< StorageSpecification_T >; +using gpu::communication::UniformGPUScheme; + +using lbm_generated::UniformGeneratedGPUPdfPackInfo; +#else +using PdfField_T = lbm_generated::PdfField< StorageSpecification_T >; +using blockforest::communication::UniformBufferedScheme; + +using lbm_generated::UniformGeneratedPdfPackInfo; +#endif + +int main(int argc, char** argv) +{ + Environment env( argc, argv ); + mpi::MPIManager::instance()->useWorldComm(); +#if defined(WALBERLA_BUILD_WITH_GPU_SUPPORT) + gpu::selectDeviceBasedOnMpiRank(); +#endif + + auto config = env.config(); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// SETUP AND CONFIGURATION /// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + auto blocks = blockforest::createUniformBlockGridFromConfig(config); + auto parameters = config->getOneBlock("Parameters"); + const uint_t timesteps = parameters.getParameter< uint_t >("timesteps", uint_c(50)); + const bool gpuEnabledMPI = parameters.getParameter< bool >("gpuEnabledMPI", false); + + const real_t reynoldsNumber = parameters.getParameter< real_t >("reynoldsNumber"); + const real_t referenceVelocity = parameters.getParameter< real_t >("referenceVelocity"); + const real_t inflowVelocity = parameters.getParameter< real_t >("latticeVelocity"); + + const real_t speedOfSound = real_c(real_c(1.0) / std::sqrt( real_c(3.0) )); + const real_t machNumber = inflowVelocity / speedOfSound; + // TODO define RE + const real_t viscosity = real_c((inflowVelocity * 1.0) / reynoldsNumber); + const real_t omega = real_c(real_c(1.0) / (real_c(3.0) * viscosity + real_c(0.5))); + + IDs ids; + + // Creating fields + const StorageSpecification_T StorageSpec = StorageSpecification_T(); + ids.pdfField = lbm_generated::addPdfFieldToStorage(blocks, "pdfs", StorageSpec, uint_c(1), field::fzyx); + + auto allocator = make_shared< gpu::HostFieldAllocator<macroFieldType> >(); // use pinned memory allocator for faster CPU-GPU memory transfers + ids.velocityField = field::addToStorage< VelocityField_T >(blocks, "vel", macroFieldType(0.0), field::fzyx, uint_c(1), allocator); + ids.densityField = field::addToStorage< ScalarField_T >(blocks, "density", macroFieldType(1.0), field::fzyx, uint_c(1), allocator); + ids.flagField = field::addFlagFieldToStorage< FlagField_T >(blocks, "Boundary Flag Field"); + + ids.pdfFieldGPU = lbm_generated::addGPUPdfFieldToStorage< PdfField_T >(blocks, ids.pdfField, StorageSpec, "pdfs on GPU", true); + ids.velocityFieldGPU = gpu::addGPUFieldToStorage< VelocityField_T >(blocks, ids.velocityField, "velocity on GPU", true); + ids.densityFieldGPU = gpu::addGPUFieldToStorage< ScalarField_T >(blocks, ids.densityField, "velocity on GPU", true); + + const Cell innerOuterSplit = Cell(parameters.getParameter< Vector3<cell_idx_t> >("innerOuterSplit", Vector3<cell_idx_t>(1, 1, 1))); + SweepCollection_T sweepCollection(blocks, ids.pdfFieldGPU, ids.densityFieldGPU, ids.velocityFieldGPU, omega, innerOuterSplit); + + for (auto& block : *blocks) + { + sweepCollection.initialise(&block); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// LB SWEEPS AND BOUNDARY HANDLING /// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // Boundaries + const FlagUID fluidFlagUID("Fluid"); + const FlagUID wallFlagUID("NoSlip"); + + auto boundariesConfig = config->getBlock("Boundaries"); + if (boundariesConfig) + { + WALBERLA_LOG_INFO_ON_ROOT("Setting boundary conditions") + geometry::initBoundaryHandling< FlagField_T >(*blocks, ids.flagField, boundariesConfig); + const real_t test = 6; + init_TPMS(blocks, ids.flagField, wallFlagUID, test, test, test); + geometry::setNonBoundaryCellsToDomain< FlagField_T >(*blocks, ids.flagField, fluidFlagUID); + } + geometry::setNonBoundaryCellsToDomain< FlagField_T >(*blocks, ids.flagField, fluidFlagUID); + BoundaryCollection_T boundaryCollection(blocks, ids.flagField, ids.pdfFieldGPU, fluidFlagUID, inflowVelocity); + // BoundaryCollection_T boundaryCollection(blocks, ids.flagField, ids.pdfFieldGPU, fluidFlagUID, inflowVelocity, ids.pdfField); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// COMMUNICATION SCHEME /// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + UniformGPUScheme< Stencil_T > communication(blocks, gpuEnabledMPI); + auto packInfo = std::make_shared<lbm_generated::UniformGeneratedGPUPdfPackInfo< GPUPdfField_T >>(ids.pdfFieldGPU); + communication.addPackInfo(packInfo); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// TIME STEP DEFINITIONS /// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const int streamLowPriority = 0; + auto defaultStream = gpu::StreamRAII::newPriorityStream(streamLowPriority); + + SweepTimeloop timeLoop(blocks->getBlockStorage(), timesteps); + timeLoop.add() << BeforeFunction(communication.getCommunicateFunctor(), "communication") + << Sweep(boundaryCollection.getSweep(BoundaryCollection_T::ALL, defaultStream), "Boundary Conditions"); + timeLoop.add() << Sweep(sweepCollection.streamCollide(SweepCollection_T::ALL, defaultStream), "LBM StreamCollide"); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// VTK Output /// + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // VTK + auto vtkParameters = config->getOneBlock("VTKWriter"); + const uint_t vtkWriteFrequency = vtkParameters.getParameter< uint_t >("vtkWriteFrequency", 0); + if (vtkWriteFrequency > 0) + { + auto vtkOutput = vtk::createVTKOutput_BlockData(*blocks, "vtk", vtkWriteFrequency, 0, false, "vtk_out", + "simulation_step", false, true, true, false, 0); + auto velWriter = make_shared< field::VTKWriter< VelocityField_T, float32 > >(ids.velocityField, "vel"); + vtkOutput->addCellDataWriter(velWriter); + + vtkOutput->addBeforeFunction([&]() { + for (auto& block : *blocks) + sweepCollection.calculateMacroscopicParameters(&block); + gpu::fieldCpy< VelocityField_T, gpu::GPUField< VelocityField_T::value_type > >(blocks, ids.velocityField, ids.velocityFieldGPU); + }); + + if (vtkParameters.getParameter< bool >("flag")) + { + auto flagWriter = make_shared< field::VTKWriter< FlagField_T > >(ids.flagField, "flag"); + vtkOutput->addCellDataWriter(flagWriter); + } + + timeLoop.addFuncAfterTimeStep(vtk::writeFiles(vtkOutput), "VTK Output"); + } + + WALBERLA_MPI_BARRIER() +#if defined(WALBERLA_BUILD_WITH_GPU_SUPPORT) + WALBERLA_GPU_CHECK(gpuDeviceSynchronize()) + WALBERLA_GPU_CHECK(gpuPeekAtLastError()) +#endif + + const lbm_generated::PerformanceEvaluation< FlagField_T > performance(blocks, ids.flagField, fluidFlagUID); + field::CellCounter< FlagField_T > fluidCells(blocks, ids.flagField, fluidFlagUID); + fluidCells(); + + WALBERLA_LOG_INFO_ON_ROOT("Starting Simulation") + WcTimingPool timeloopTiming; + WcTimer simTimer; + + WALBERLA_MPI_BARRIER() +#if defined(WALBERLA_BUILD_WITH_GPU_SUPPORT) + WALBERLA_GPU_CHECK(gpuDeviceSynchronize()) + WALBERLA_GPU_CHECK(gpuPeekAtLastError()) +#endif + + simTimer.start(); + timeLoop.run(timeloopTiming); +#if defined(WALBERLA_BUILD_WITH_GPU_SUPPORT) + WALBERLA_GPU_CHECK(gpuDeviceSynchronize()) + WALBERLA_GPU_CHECK(gpuPeekAtLastError()) +#endif + WALBERLA_MPI_BARRIER() + simTimer.end(); + WALBERLA_LOG_INFO_ON_ROOT("Simulation finished") + double time = double_c(simTimer.max()); + WALBERLA_MPI_SECTION() { walberla::mpi::reduceInplace(time, walberla::mpi::MAX); } + performance.logResultOnRoot(timesteps, time); + + const auto reducedTimeloopTiming = timeloopTiming.getReduced(); + WALBERLA_LOG_RESULT_ON_ROOT("Time loop timing:\n" << *reducedTimeloopTiming) + + printResidentMemoryStatistics(); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/apps/showcases/PorousMediaGPU/PorousMediaGPU.prm b/apps/showcases/PorousMediaGPU/PorousMediaGPU.prm new file mode 100644 index 0000000000000000000000000000000000000000..392caccc003db502c539e90728dfde7271db4164 --- /dev/null +++ b/apps/showcases/PorousMediaGPU/PorousMediaGPU.prm @@ -0,0 +1,72 @@ +Parameters +{ + reynoldsNumber 2500; + + referenceVelocity 1.0; + latticeVelocity 0.05; + initialiseWithInletVelocity true; + + timesteps 2; + + processMemoryLimit 512; // MiB + innerOuterSplit <1, 1, 1>; + + // GPU related Parameters, only used if GPU is enabled + gpuEnabledMPI false; +} + +//! [domainSetup] +DomainSetup +{ + cellsPerBlock < 256, 64, 64 >; + blocks < 1, 1, 1 >; + periodic < false, true, true >; +} +//! [domainSetup] + +Boundaries +{ + Border { direction W; walldistance -1; flag UBB; } + Border { direction E; walldistance -1; flag Outflow; } +} + + +StabilityChecker +{ + checkFrequency 0; + streamOutput false; + vtkOutput true; +} + +VTKWriter +{ + vtkWriteFrequency 1; + vtkGhostLayers 0; + velocity true; + density true; + flag true; + omega false; + writeOnlySlice true; + sliceThickness 1; + writeXZSlice false; + amrFileFormat true; + oneFilePerProcess false; + samplingResolution -1; + initialWriteCallsToSkip 0; +} + +Logging +{ + logLevel info; // info progress detail tracing + writeSetupForestAndReturn true; // When only one process is used the decomposition is writen and the program terminates + readSetupFromFile false; + remainingTimeLoggerFrequency 60; // in seconds +} + +Evaluation +{ + evaluationCheckFrequency 500; + rampUpTime 0; + logToStream true; + logToFile true; +} \ No newline at end of file diff --git a/apps/showcases/PorousMediaGPU/PorousMediaGPU.py b/apps/showcases/PorousMediaGPU/PorousMediaGPU.py new file mode 100644 index 0000000000000000000000000000000000000000..f01f9f5386cb8c67ec5493501485a845f8ccb671 --- /dev/null +++ b/apps/showcases/PorousMediaGPU/PorousMediaGPU.py @@ -0,0 +1,106 @@ +import sympy as sp +from pystencils import Target + +from pystencils.field import fields +from pystencils.simp import insert_aliases, insert_constants + +from lbmpy import LBStencil, LBMConfig, LBMOptimisation +from lbmpy.boundaries.boundaryconditions import ExtrapolationOutflow, UBB, NoSlip, FixedDensity +from lbmpy.creationfunctions import create_lb_collision_rule +from lbmpy.enums import Method, Stencil + +from pystencils_walberla import CodeGeneration, generate_info_header +from lbmpy_walberla import generate_lbm_package, lbm_boundary_generator + +info_header = """ +#pragma once +#include <map> +std::map<std::string, std::string> infoMap{{{{"stencil", "{stencil}"}}, + {{"streamingPattern", "{streaming_pattern}"}}, + {{"collisionOperator", "{collision_operator}"}}}}; +""" + +omega = sp.symbols("omega") +inlet_velocity = sp.symbols("u_x") +max_threads = 256 + +with CodeGeneration() as ctx: + target = Target.GPU if ctx.gpu else Target.CPU + sweep_params = {'block_size': (128, 1, 1)} if ctx.gpu else {} + + # The application is meant to be compiled with double precision. For single precision, the pdf_dtype can be switched + # to float32. In this way the calculations are still performed in double precision while the application can profit + # from enhanced performance due to the lower precision of the PDF field + dtype = 'float64' if ctx.double_accuracy else 'float32' + pdf_dtype = 'float64' + + stencil = LBStencil(Stencil.D3Q19) + q = stencil.Q + dim = stencil.D + + streaming_pattern = 'pull' + + pdfs = fields(f"pdfs({stencil.Q}): {pdf_dtype}[3D]", layout='fzyx') + velocity_field, density_field = fields(f"velocity({dim}), density(1) : {dtype}[{dim}D]", layout='fzyx') + + macroscopic_fields = {'density': density_field, 'velocity': velocity_field} + + # method_enum = Method.CUMULANT + method_enum = Method.SRT + lbm_config = LBMConfig( + method=method_enum, + stencil=stencil, + relaxation_rate=omega, + compressible=True, + # subgrid_scale_model=SubgridScaleModel.QR, + fourth_order_correction=0.01 if method_enum == Method.CUMULANT and stencil.Q == 27 else False, + field_name='pdfs', + streaming_pattern=streaming_pattern, + ) + + lbm_opt = LBMOptimisation(cse_global=False, cse_pdfs=False, field_layout="fzyx", + symbolic_field=pdfs) + + collision_rule = create_lb_collision_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt) + if lbm_config.method == Method.CUMULANT: + collision_rule = insert_constants(collision_rule) + collision_rule = insert_aliases(collision_rule) + lb_method = collision_rule.method + + no_slip = lbm_boundary_generator(class_name='NoSlip', flag_uid='NoSlip', + boundary_object=NoSlip(), field_data_type=pdf_dtype) + + ubb = lbm_boundary_generator(class_name='UBB', flag_uid='UBB', + boundary_object=UBB((inlet_velocity, 0.0, 0.0), density=1.0, data_type=dtype), + field_data_type=pdf_dtype) + + # outflow_boundary = ExtrapolationOutflow(stencil[4], lb_method, data_type=pdf_dtype) + # outflow = lbm_boundary_generator(class_name='Outflow', flag_uid='Outflow', + # boundary_object=outflow_boundary, + # field_data_type=pdf_dtype) + + outflow = lbm_boundary_generator(class_name='Outflow', flag_uid='Outflow', + boundary_object=FixedDensity(1.0), + field_data_type=pdf_dtype) + + generate_lbm_package(ctx, name="PorousMediaGPU", collision_rule=collision_rule, + lbm_config=lbm_config, lbm_optimisation=lbm_opt, + nonuniform=False, boundaries=[no_slip, ubb, outflow], + macroscopic_fields=macroscopic_fields, gpu_indexing_params=sweep_params, + target=target, data_type=dtype, pdfs_data_type=pdf_dtype, + max_threads=max_threads) + + field_typedefs = {'VelocityField_T': velocity_field, + 'ScalarField_T': density_field} + + # Info header containing correct template definitions for stencil and field + generate_info_header(ctx, 'PorousMediaGPUInfoHeader', + field_typedefs=field_typedefs) + + infoHeaderParams = { + 'stencil': stencil.name.lower(), + 'streaming_pattern': streaming_pattern, + 'collision_operator': lbm_config.method.name.lower(), + } + + ctx.write_file("PorousMediaGPUStaticDefines.h", info_header.format(**infoHeaderParams)) \ No newline at end of file diff --git a/apps/showcases/PorousMediaGPU/Types.h b/apps/showcases/PorousMediaGPU/Types.h new file mode 100644 index 0000000000000000000000000000000000000000..1e8335fdc18dec28a6f3bb7293fc565ca2ea917b --- /dev/null +++ b/apps/showcases/PorousMediaGPU/Types.h @@ -0,0 +1,45 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla is free software: you can +// redistribute it and/or modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// waLBerla is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Types.h +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== +# pragma once + +#include "domain_decomposition/BlockDataID.h" +#include "lbm_generated/field/PdfField.h" +#include "PorousMediaGPUInfoHeader.h" + +using namespace walberla; + +using StorageSpecification_T = lbm::PorousMediaGPUStorageSpecification; +using Stencil_T = StorageSpecification_T::Stencil; +using CommunicationStencil_T = StorageSpecification_T::CommunicationStencil; + +using PdfField_T = lbm_generated::PdfField< StorageSpecification_T >; +using FlagField_T = FlagField< uint8_t >; + +struct IDs +{ + BlockDataID pdfField; + BlockDataID velocityField; + BlockDataID densityField; + BlockDataID flagField; + + BlockDataID pdfFieldGPU; + BlockDataID velocityFieldGPU; + BlockDataID densityFieldGPU; +}; \ No newline at end of file