diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7340d091065e0a1de1cf7510914f0021827c6a93..c3ef11475a0abf37254b5eef60130fe3dfbb4097 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,6 +4,23 @@ stages: - Deploy +testsuite-clang18: + image: i10git.cs.fau.de:5005/walberla/buildenvs/clang-18:latest + tags: + - docker + stage: "Test" + needs: [] + variables: + CXX: clang++ + CC: clang + before_script: + - cd user_manual/examples + - cmake -G Ninja -S . -B build + - cd build + - cmake --build . --target SfgTests + script: + - ctest + build-examples: image: i10git.cs.fau.de:5005/walberla/buildenvs/clang-18:latest tags: @@ -14,7 +31,7 @@ build-examples: CXX: clang++ CC: clang script: - - cd user_manual/examples + - cd tests - cmake -G Ninja -S . -B build - cd build - cmake --build . --target Examples diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f6e52227b3c49260f6329d25dfa096a9e3e3dac1..72acde9c5dc7ca88b51038b3798c79810a812883 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,6 +3,7 @@ project( sfg-walberla-testsuite ) set(WALBERLA_BUILD_TESTS OFF CACHE BOOL "") set(WALBERLA_BUILD_BENCHMARKS OFF CACHE BOOL "") +set(WALBERLA_BUILD_SHOWCASES OFF CACHE BOOL "") set(WALBERLA_BUILD_TUTORIALS OFF CACHE BOOL "") include(FetchContent) @@ -20,4 +21,6 @@ add_subdirectory(${CMAKE_SOURCE_DIR}/.. ${CMAKE_BINARY_DIR}/sfg-walberla) # Test Directories include(CTest) +add_custom_target( SfgTests ) + add_subdirectory( FreeSlip ) diff --git a/tests/CMakePresets.json b/tests/CMakePresets.json index 11b6c5797a4a848db2ef82c3e601e403848fb15a..48449c2d856200adfa38b7019aa2bcff44144615 100644 --- a/tests/CMakePresets.json +++ b/tests/CMakePresets.json @@ -11,6 +11,7 @@ "binaryDir": "${sourceDir}/build/${presetName}", "generator": "Ninja", "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", "WALBERLA_BUILD_TESTS": false } } diff --git a/tests/FreeSlip/CMakeLists.txt b/tests/FreeSlip/CMakeLists.txt index 661ef3c7d06ef4512b754d2aa2614cc313f12430..e47cae2e1bef502e62a8b64dd2dea7f9fa396151 100644 --- a/tests/FreeSlip/CMakeLists.txt +++ b/tests/FreeSlip/CMakeLists.txt @@ -2,3 +2,5 @@ add_executable( TestIrregularFreeSlip TestIrregularFreeSlip.cpp ) walberla_generate_sources( TestIrregularFreeSlip SCRIPTS IrregularFreeSlip.py ) target_link_libraries( TestIrregularFreeSlip core blockforest field geometry sfg_walberla ) add_test( NAME TestIrregularFreeSlip COMMAND TestIrregularFreeSlip ) + +add_dependencies( SfgTests TestIrregularFreeSlip ) diff --git a/tests/FreeSlip/IrregularFreeSlip.py b/tests/FreeSlip/IrregularFreeSlip.py index 4a5b5cdcccb7fbc580b69827a8aa315f5b604dfe..3fa69cf2042e054618db15ec1779945b9198214a 100644 --- a/tests/FreeSlip/IrregularFreeSlip.py +++ b/tests/FreeSlip/IrregularFreeSlip.py @@ -1,22 +1,54 @@ +import sympy as sp from pystencilssfg import SourceFileGenerator -from sfg_walberla.boundaries import FreeSlip -from lbmpy import LBStencil, Stencil, LBMConfig, create_lb_method + from pystencils import fields, Field +from lbmpy import LBStencil, Stencil, LBMConfig, LBMOptimisation, create_lb_update_rule +from lbmpy.macroscopic_value_kernels import macroscopic_values_setter + + +from sfg_walberla import Sweep +from sfg_walberla.boundaries import FreeSlip with SourceFileGenerator() as sfg: - sfg.namespace("gen") + sfg.namespace("TestIrregularFreeSlip::gen") stencil = LBStencil(Stencil.D3Q19) d, q = stencil.D, stencil.Q f: Field - f = fields(f"f({q}): double[{d}D]", layout="fzyx") # type: ignore + f_tmp: Field + f, f_tmp, rho, u = fields( + f"f({q}), f_tmp({q}), rho, u({d}): double[{d}D]", layout="fzyx" + ) # type: ignore stencil_name = stencil.name sfg.include(f"stencil/{stencil_name}.h") sfg.code(f"using LbStencil = walberla::stencil::{stencil_name};") - lbm_config = LBMConfig(stencil=stencil) - lb_method = create_lb_method(lbm_config) + lbm_config = LBMConfig( + stencil=stencil, + output={"density": rho, "velocity": u}, + ) + lbm_opt = LBMOptimisation( + symbolic_field=f, + symbolic_temporary_field=f_tmp, + ) + + lb_update = create_lb_update_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt) + assert lb_update is not None + + lb_update_sweep = Sweep("LbStreamCollide", lb_update) + lb_update_sweep.swap_fields(f, f_tmp) + sfg.generate(lb_update_sweep) + + lb_init = macroscopic_values_setter( + lb_update.method, + density=sp.Symbol("density"), + velocity=u.center_vector, + pdfs=f, + ) + lb_init_sweep = Sweep("LbInit", lb_init) + sfg.generate(lb_init_sweep) + + irreg_freeslip = FreeSlip("FreeSlipIrregular", lb_update.method, f, wall_normal=FreeSlip.IRREGULAR) + sfg.generate(irreg_freeslip) - bc = FreeSlip("FreeSlip", lb_method, f, wall_normal=FreeSlip.IRREGULAR) - sfg.generate(bc) diff --git a/tests/FreeSlip/TestIrregularFreeSlip.cpp b/tests/FreeSlip/TestIrregularFreeSlip.cpp index 68e4ae927e91caafa7693f0a30a2b2ed40f5ef64..c08df34308cc4e8c64d02717cfe1c091c0ecb5a4 100644 --- a/tests/FreeSlip/TestIrregularFreeSlip.cpp +++ b/tests/FreeSlip/TestIrregularFreeSlip.cpp @@ -1,9 +1,15 @@ #include "core/all.h" #include "blockforest/all.h" + #include "field/all.h" +#include "field/communication/PackInfo.h" +#include "field/communication/StencilRestrictedPackInfo.h" + #include "geometry/all.h" +#include "vtk/all.h" + #include <array> #include "gen/IrregularFreeSlip.hpp" @@ -13,66 +19,129 @@ namespace TestIrregularFreeSlip using namespace walberla; using PdfField_T = field::GhostLayerField<real_t, gen::LbStencil::Q>; + using ScalarField_T = field::GhostLayerField<real_t, 1>; + using VectorField_T = field::GhostLayerField<real_t, gen::LbStencil::D>; using FlagField_T = FlagField<uint8_t>; - - void run(int argc, char **argv) + using CommScheme = blockforest::communication::UniformBufferedScheme<gen::LbStencil>; + using PdfsPackInfo = field::communication::StencilRestrictedPackInfo<PdfField_T, gen::LbStencil>; + + /** + * Pipe flow with circular cross-section and free-slip walls. + * The pipe flow is initialized with a constant velocity in x-direction. + * As free-slip walls do not impose any friction, velocity should remain constant in time. + */ + void freeSlipPipe(Environment &env) { - Environment env{argc, argv}; - - AABB domainAabb{0., 0., 0., 1., 1., 1.}; std::array<uint_t, 3> blocks{1, 1, 1}; - std::array<uint_t, 3> cpb{32, 32, 32}; + std::array<uint_t, 3> cpb{4, 32, 32}; + std::array<bool, 3> periodic{true, false, false}; auto sbfs = blockforest::createUniformBlockGrid( - domainAabb, blocks[0], blocks[1], blocks[2], - cpb[0], cpb[1], cpb[2]); + cpb[0], cpb[1], cpb[2], + 1.0, + true, + periodic[0], periodic[1], periodic[2] + ); BlockDataID pdfsId = field::addToStorage<PdfField_T>(sbfs, "f", real_c(0.0)); + BlockDataID rhoId = field::addToStorage<ScalarField_T>(sbfs, "rho", real_c(0.0)); + BlockDataID uId = field::addToStorage<VectorField_T>(sbfs, "u", real_c(0.0)); const BlockDataID flagFieldId = field::addFlagFieldToStorage<FlagField_T>(sbfs, "flagField"); const FlagUID fluidFlagUid{"Fluid"}; const FlagUID freeSlipFlagUID{"FreeSlip"}; const CellInterval allCells{{0, 0, 0}, {sbfs->getNumberOfXCellsPerBlock() - 1, sbfs->getNumberOfYCellsPerBlock() - 1, sbfs->getNumberOfZCellsPerBlock() - 1}}; - const Vector3<real_t> sphereCenter{16., 16., 16.}; - const real_t sphereRadius{8.}; + const CellInterval allCellsWithGl{{-1, 0, 0}, {sbfs->getNumberOfXCellsPerBlock(), sbfs->getNumberOfYCellsPerBlock() - 1, sbfs->getNumberOfZCellsPerBlock() - 1}}; + + const real_t pipeRadius{14.0}; + const Vector3<real_t> pipeAnchor{0.0, 16.0, 16.0}; + const real_t maxVelocity{0.02}; for (auto &block : *sbfs) { FlagField_T &flagField = *block.getData<FlagField_T>(flagFieldId); const uint8_t freeSlipFlag{flagField.getOrRegisterFlag(freeSlipFlagUID)}; - PdfField_T &pdfField = *block.getData<PdfField_T>(pdfsId); + VectorField_T &velField = *block.getData<VectorField_T>(uId); - for (Cell c : allCells) + for (Cell c : allCellsWithGl) { Cell globalCell{c}; sbfs->transformBlockLocalToGlobalCell(globalCell, block); Vector3<real_t> cellCenter{sbfs->getCellCenter(globalCell)}; + cellCenter[0] = 0.0; - if ((cellCenter - sphereCenter).sqrLength() < sphereRadius * sphereRadius) + Vector3<real_t> initVelocity; + real_t radialDistance = (cellCenter - pipeAnchor).length(); + if (radialDistance > pipeRadius) { flagField.addFlag(c, freeSlipFlag); - for (uint_t q = 0; q < 19; ++q) - { - pdfField.get(c, q) = NAN; - } + initVelocity = Vector3<real_t>{NAN}; + } + else + { + initVelocity = Vector3<real_t>{maxVelocity, 0., 0.}; } + + velField.get(c, 0) = initVelocity[0]; + velField.get(c, 1) = initVelocity[1]; + velField.get(c, 2) = initVelocity[2]; } } geometry::setNonBoundaryCellsToDomain<FlagField_T>(*sbfs, flagFieldId, fluidFlagUid); - gen::FreeSlip freeSlip{gen::FreeSlipFactory(sbfs, pdfsId).fromFlagField<FlagField_T>(flagFieldId, freeSlipFlagUID, fluidFlagUid)}; + auto flagsOutput = field::createVTKOutput<FlagField_T>(flagFieldId, *sbfs, "flags"); + flagsOutput(); + + gen::LbInit initialize { pdfsId, uId, 1.0 }; - for(auto& block: *sbfs){ - freeSlip( &block ); + for(auto& b : *sbfs){ + initialize(&b); } + + gen::FreeSlipIrregular freeSlip{ + gen::FreeSlipIrregularFactory(sbfs, pdfsId).fromFlagField<FlagField_T>(flagFieldId, freeSlipFlagUID, fluidFlagUid) + }; + + gen::LbStreamCollide streamCollide { pdfsId, rhoId, uId, 1.0 }; + + CommScheme comm{sbfs}; + auto pdfsPackInfo = std::make_shared<PdfsPackInfo>(pdfsId); + comm.addPackInfo(pdfsPackInfo); + + auto velOutput = field::createVTKOutput<VectorField_T>(uId, *sbfs, "vel"); + + for(uint_t i = 0; i < 10; ++i){ + comm(); + for (auto &block : *sbfs) + { + velOutput(); + freeSlip(&block); + streamCollide(&block); + + VectorField_T & velField = *block.getData< VectorField_T >(uId); + FlagField_T & flagField = *block.getData< FlagField_T >(flagFieldId); + uint8_t fluidFlag = flagField.getFlag(fluidFlagUid); + + for(Cell c : allCells){ + if( flagField.isFlagSet(c, fluidFlag) ){ + WALBERLA_CHECK_FLOAT_EQUAL( velField.get(c, 0), maxVelocity ); + WALBERLA_CHECK_FLOAT_EQUAL( velField.get(c, 1), 0. ); + WALBERLA_CHECK_FLOAT_EQUAL( velField.get(c, 2), 0. ); + } + } + } + } + + velOutput(); } } int main(int argc, char **argv) { - TestIrregularFreeSlip::run(argc, argv); + walberla::Environment env{argc, argv}; + TestIrregularFreeSlip::freeSlipPipe(env); } diff --git a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py index 1d6678f3121c38964a0d8b6c314f0cb77c16bcf5..a40d6b4c1349ef03a585c8a734d81e286dbbb3df 100644 --- a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py +++ b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py @@ -7,7 +7,7 @@ from lbmpy.macroscopic_value_kernels import macroscopic_values_setter from sfg_walberla import Sweep -from sfg_walberla.boundaries import FreeSlip, IRREGULAR +from sfg_walberla.boundaries import FreeSlip with SourceFileGenerator() as sfg: sfg.namespace("FreeSlipBubble::gen") @@ -45,6 +45,5 @@ with SourceFileGenerator() as sfg: lb_init_sweep = Sweep("LbInit", lb_init) sfg.generate(lb_init_sweep) - freeslip = FreeSlip("FreeSlip", lb_update.method, f, wall_normal=IRREGULAR) + freeslip = FreeSlip("FreeSlip", lb_update.method, f, wall_normal=FreeSlip.IRREGULAR) sfg.generate(freeslip) -