diff --git a/lib/walberla/experimental/sweep/DomainSlices.hpp b/lib/walberla/experimental/sweep/DomainSlices.hpp index 450316dd1c6e7bc883a61f130d46b2d1c981bd4f..0492cb53bdc2baddae1f8b4f8468eea4b95bfc02 100644 --- a/lib/walberla/experimental/sweep/DomainSlices.hpp +++ b/lib/walberla/experimental/sweep/DomainSlices.hpp @@ -78,4 +78,4 @@ class BorderSweep } }; -} // namespace walberla::experimental::sweep \ No newline at end of file +} // namespace walberla::experimental::sweep diff --git a/src/walberla/codegen/boundaries/linkwise.py b/src/walberla/codegen/boundaries/linkwise.py index 04a6491ba0712f4f17b55d386757f89cf83e4070..777e6b0a883f7000e891285d88b2cb7cc9281b31 100644 --- a/src/walberla/codegen/boundaries/linkwise.py +++ b/src/walberla/codegen/boundaries/linkwise.py @@ -39,8 +39,8 @@ class NoSlip(GenericLinkwiseBoundary): name: Name of the generated sweep class lb_method: lbmpy Method description pdf_field: Symbolic LBM PDF field - wall_normal: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the wall into the fluid, - or `FreeSlip.IRREGULAR` to indicate a non-grid-aligned boundary + wall_orientation: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the fluid to the wall, + or `NoSlip.IRREGULAR` to indicate a non-grid-aligned boundary target: Target architecture for the code generator """ @@ -49,13 +49,13 @@ class NoSlip(GenericLinkwiseBoundary): name: str, lb_method: AbstractLbMethod, pdf_field: Field, - wall_normal: tuple[int, int, int] | _IrregularSentinel, + wall_orientation: tuple[int, int, int] | _IrregularSentinel, target: Target | None = None, ): self._name = name self._lb_method = lb_method self._pdf_field = pdf_field - self._wall_normal = wall_normal + self._wall_normal = wall_orientation self._target = target @property @@ -86,8 +86,7 @@ class NoSlip(GenericLinkwiseBoundary): assert isinstance(self._wall_normal, tuple) wall_normal = self._wall_normal - x_w = (0,) * stencil.D - x_b = tuple(x + c for x, c in zip(x_w, wall_normal)) + x_b = (0,) * stencil.D f = self._pdf_field @@ -100,10 +99,10 @@ class NoSlip(GenericLinkwiseBoundary): asms = [] - for i_out, c_out in enumerate(stencil): - if wall_aligned(c_out): - i_inverse = stencil.inverse_index(c_out) - asms.append(Assignment(f[x_w](i_out), f[x_b](i_inverse))) + for i_out, x_w in enumerate(stencil): + if wall_aligned(x_w): + i_inverse = stencil.inverse_index(x_w) + asms.append(Assignment(f[x_w](i_inverse), f[x_b](i_out))) return AssignmentCollection(asms) @@ -210,7 +209,7 @@ class FreeSlip(GenericLinkwiseBoundary): name: Name of the generated sweep class lb_method: lbmpy Method description pdf_field: Symbolic LBM PDF field - wall_normal: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the wall into the fluid, + wall_orientation: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the wall into the fluid, or `FreeSlip.IRREGULAR` to indicate a non-grid-aligned boundary target: Target architecture for the code generator """ @@ -220,13 +219,13 @@ class FreeSlip(GenericLinkwiseBoundary): name: str, lb_method: AbstractLbMethod, pdf_field: Field, - wall_normal: tuple[int, int, int] | _IrregularSentinel, + wall_orientation: tuple[int, int, int] | _IrregularSentinel, target: Target | None = None, ): self._name = name self._lb_method = lb_method self._pdf_field = pdf_field - self._wall_normal = wall_normal + self._wall_normal = wall_orientation self._target = target @property @@ -306,18 +305,15 @@ class FreeSlip(GenericLinkwiseBoundary): def _grid_aligned_assignments(self): stencil = self._lb_method.stencil - x_w = (0,) * stencil.D assert isinstance(self._wall_normal, tuple) wall_normal = self._wall_normal - - x_b = tuple(x + c for x, c in zip(x_w, wall_normal)) + inverse_wall_normal = tuple(-c for c in wall_normal) f = self._pdf_field - def wall_aligned(vec): - """Test if v1 is aligned with v2, i.e. v1 has the same nonzero entries as v2""" - for x_v, x_n in zip(vec, wall_normal): + def is_missing(vec): + for x_v, x_n in zip(vec, inverse_wall_normal): if x_n != 0 and x_v != x_n: return False return True @@ -329,11 +325,15 @@ class FreeSlip(GenericLinkwiseBoundary): asms = [] - for i_out, c_out in enumerate(stencil): - c_mirrored = wall_mirror(c_out) - i_mirrored = stencil.index(c_mirrored) - if wall_aligned(c_out): - asms.append(Assignment(f[x_w](i_out), f[x_b](i_mirrored))) + for i_missing, c_missing in enumerate(stencil): + # Iterate all inbound populations to the fluid cell crossing the wall + if is_missing(c_missing): + x_w = tuple(-c for c in c_missing) + c_refl = wall_mirror(c_missing) + i_refl = stencil.index(c_refl) + x_orig = tuple(w - n for w, n in zip(x_w, wall_normal)) + + asms.append(Assignment(f[x_w](i_missing), f[x_orig](i_refl))) return AssignmentCollection(asms) diff --git a/tests/BasicLbmScenarios/LbmAlgorithms.py b/tests/BasicLbmScenarios/LbmAlgorithms.py index 2f9b8762139c35a59ab9fb78593ad0cf9efa8a9b..1ba0036ee6e5032d62a8141ec76f8e3c35c09b0c 100644 --- a/tests/BasicLbmScenarios/LbmAlgorithms.py +++ b/tests/BasicLbmScenarios/LbmAlgorithms.py @@ -97,16 +97,16 @@ with SourceFileGenerator(keep_unknown_argv=True) as sfg: sfg.generate(lb_init_constant_sweep) with sfg.namespace("bc_grid_aligned"): - sfg.generate(NoSlip("NoSlipTop", lb_update.method, f, wall_normal=(0, 0, -1))) + sfg.generate(NoSlip("NoSlipTop", lb_update.method, f, wall_orientation=(0, 0, 1), target=cfg.target)) - sfg.generate(NoSlip("NoSlipBottom", lb_update.method, f, wall_normal=(0, 0, 1))) + sfg.generate(NoSlip("NoSlipBottom", lb_update.method, f, wall_orientation=(0, 0, -1), target=cfg.target)) sfg.generate( - FreeSlip("FreeSlipTop", lb_update.method, f, wall_normal=(0, 0, -1)) + FreeSlip("FreeSlipTop", lb_update.method, f, wall_orientation=(0, 0, 1), target=cfg.target) ) sfg.generate( - FreeSlip("FreeSlipBottom", lb_update.method, f, wall_normal=(0, 0, 1)) + FreeSlip("FreeSlipBottom", lb_update.method, f, wall_orientation=(0, 0, -1), target=cfg.target) ) with sfg.namespace("bc_sparse"): @@ -114,7 +114,7 @@ with SourceFileGenerator(keep_unknown_argv=True) as sfg: "FreeSlipIrregular", lb_update.method, f, - wall_normal=FreeSlip.IRREGULAR, + wall_orientation=FreeSlip.IRREGULAR, target=cfg.target, ) sfg.generate(irreg_freeslip) diff --git a/tests/BasicLbmScenarios/SimDomain.hpp b/tests/BasicLbmScenarios/SimDomain.hpp index 50991de38916d28852543350700ab0e1b8018c68..4417699a8d2eec630f684ce46755fee0fecd45dd 100644 --- a/tests/BasicLbmScenarios/SimDomain.hpp +++ b/tests/BasicLbmScenarios/SimDomain.hpp @@ -103,12 +103,12 @@ struct SimDomain auto freeSlipBottom() { - return sweep::BorderSweep< stencil::Direction::B, gen::bc_grid_aligned::FreeSlipBottom > { blocks, gen::bc_grid_aligned::FreeSlipBottom { gpuFields.pdfsId }, 0 }; + return sweep::BorderSweep< stencil::Direction::B, gen::bc_grid_aligned::FreeSlipBottom > { blocks, gen::bc_grid_aligned::FreeSlipBottom { gpuFields.pdfsId } }; } auto noSlipTop() { - return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::NoSlipTop > { blocks, gen::bc_grid_aligned::NoSlipTop { gpuFields.pdfsId }, -1 }; + return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::NoSlipTop > { blocks, gen::bc_grid_aligned::NoSlipTop { gpuFields.pdfsId } }; } auto @@ -167,6 +167,21 @@ struct SimDomain return { cpuFields.pdfsId, cpuFields.rhoId, cpuFields.uId, force, omega }; } + auto + freeSlipTop() { + return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::FreeSlipTop > { blocks, gen::bc_grid_aligned::FreeSlipTop { cpuFields.pdfsId } }; + } + + auto + freeSlipBottom() { + return sweep::BorderSweep< stencil::Direction::B, gen::bc_grid_aligned::FreeSlipBottom > { blocks, gen::bc_grid_aligned::FreeSlipBottom { cpuFields.pdfsId } }; + } + + auto + noSlipTop() { + return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::NoSlipTop > { blocks, gen::bc_grid_aligned::NoSlipTop { cpuFields.pdfsId } }; + } + auto irregularFreeSlipFactory() { return gen::bc_sparse::FreeSlipIrregularFactory(blocks, cpuFields.pdfsId); } diff --git a/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp b/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp index e058065c434bba7f2ae9bc005ed84eeff2858bcb..5636011b615efe60732545be16714551baca601a 100644 --- a/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp +++ b/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp @@ -50,7 +50,6 @@ void fullyPeriodic(Environment& env) } } -#if defined(LBM_SCENARIOS_GPU_BUILD) /** * Periodic channel flow with a no-slip boundary at the top * and a symmetry plane at the bottom implemented using the free-slip boundary. @@ -64,7 +63,7 @@ void mirroredHalfChannel(Environment& env) * Need one more cell in z-direction for the free-slip boundary to be on the inner layer */ SimDomain dom{ SimDomainBuilder{ - .blocks = { 1, 1, 1 }, .cellsPerBlock = { 4, 4, zCells + 1 }, .periodic = { true, true, false } } + .blocks = { 1, 1, 1 }, .cellsPerBlock = { 4, 4, zCells }, .periodic = { true, true, false } } .build() }; /* Hagen-Poiseuille-law in lattice units */ @@ -106,8 +105,9 @@ void mirroredHalfChannel(Environment& env) auto streamCollide = dom.streamCollideSweep(omega, force); auto noSlipTop = dom.noSlipTop(); auto freeSlipBottom = dom.freeSlipBottom(); + auto velOutput = field::createVTKOutput< VectorField_T >(dom.cpuFields.uId, *dom.blocks, "vel"); - for (uint_t t = 0; t < 10; ++t) + for (uint_t t = 0; t < 50; ++t) { dom.forAllBlocks([&](IBlock& b) { streamCollide(&b); }); dom.syncGhostLayers(); @@ -124,10 +124,12 @@ void mirroredHalfChannel(Environment& env) real_t expected{ velocityProfile(cellCenter[2]) }; real_t actual{ velField.get(c, 0) }; - WALBERLA_CHECK_FLOAT_EQUAL(expected, actual); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(expected, actual, 1e-5); }); }); + // velOutput(); + dom.forAllBlocks([&](IBlock& b) { noSlipTop(&b); freeSlipBottom(&b); @@ -135,8 +137,6 @@ void mirroredHalfChannel(Environment& env) } } -#endif - /** * Pipe flow with circular cross-section and free-slip walls. * The pipe flow is initialized with a constant velocity in x-direction. @@ -251,7 +251,7 @@ void freeSlipPipe(Environment& env) int main(int argc, char** argv) { walberla::Environment env{ argc, argv }; - BasicLbmScenarios::fullyPeriodic(env); - // BasicLbmScenarios::mirroredHalfChannel(env); - BasicLbmScenarios::freeSlipPipe(env); + // BasicLbmScenarios::fullyPeriodic(env); + BasicLbmScenarios::mirroredHalfChannel(env); + // BasicLbmScenarios::freeSlipPipe(env); } diff --git a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py index a7f5521a54facc081498c55e4ca72aeb433bbe0f..693fd68c40adaddba491218cbc2b225c0d8d2148 100644 --- a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py +++ b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py @@ -55,7 +55,7 @@ with SourceFileGenerator() as sfg: "FreeSlip", lb_method, pdfs, - wall_normal=FreeSlip.IRREGULAR, + wall_orientation=FreeSlip.IRREGULAR, target=target )