diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c3ef11475a0abf37254b5eef60130fe3dfbb4097..d501e83f223767a186a1fac6c5beccf5e144a4d0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ testsuite-clang18: CXX: clang++ CC: clang before_script: - - cd user_manual/examples + - cd tests - cmake -G Ninja -S . -B build - cd build - cmake --build . --target SfgTests @@ -31,7 +31,7 @@ build-examples: CXX: clang++ CC: clang script: - - cd tests + - cd user_manual/examples - cmake -G Ninja -S . -B build - cd build - cmake --build . --target Examples diff --git a/user_manual/conf.py b/user_manual/conf.py index 2bc06da4f2d273c00770914d3e7fd0e7555755e0..6dfd366ee11f1cc57897e825c1ac61bcd85f3bd7 100644 --- a/user_manual/conf.py +++ b/user_manual/conf.py @@ -21,7 +21,7 @@ extensions = [ ] # templates_path = ['_templates'] -exclude_patterns = ["build"] +exclude_patterns = ["*/build"] myst_enable_extensions = [ "colon_fence", diff --git a/user_manual/examples/FreeSlipBubble/FreeSlipBubble.cpp b/user_manual/examples/FreeSlipBubble/FreeSlipBubble.cpp index 6b6f6990c89189f4ad6ecab41f4818370ca0b61e..be5f93da51d38ebd445127201ba36a31d74f1900 100644 --- a/user_manual/examples/FreeSlipBubble/FreeSlipBubble.cpp +++ b/user_manual/examples/FreeSlipBubble/FreeSlipBubble.cpp @@ -72,7 +72,7 @@ namespace FreeSlipBubble const BlockDataID flagFieldId = field::addFlagFieldToStorage<FlagField_T>(blocks, "flagField"); const FlagUID fluidFlagUid{"Fluid"}; - const FlagUID freeSlipFlagUID{"FreeSlip"}; + const FlagUID boundaryFlagUID{"FreeSlip"}; const CellInterval allCells{{0, 0, 0}, {blocks->getNumberOfXCellsPerBlock() - 1, blocks->getNumberOfYCellsPerBlock() - 1, blocks->getNumberOfZCellsPerBlock() - 1}}; const Vector3< real_t > sphereCenter { 16., 16., 16. }; @@ -81,7 +81,7 @@ namespace FreeSlipBubble for (auto &block : *blocks) { FlagField_T &flagField = *block.getData<FlagField_T>(flagFieldId); - const uint8_t freeSlipFlag{flagField.getOrRegisterFlag(freeSlipFlagUID)}; + const uint8_t freeSlipFlag{flagField.getOrRegisterFlag(boundaryFlagUID)}; PdfField_T & pdfField = *block.getData< PdfField_T >(pdfsId); @@ -104,14 +104,25 @@ namespace FreeSlipBubble auto flagFieldOutput = field::createVTKOutput<FlagField_T>(flagFieldId, *blocks, "flagField", 1, 0); flagFieldOutput(); - auto freeSlip = gen::FreeSlipFactory(blocks, pdfsId).fromFlagField<FlagField_T>(flagFieldId, freeSlipFlagUID, fluidFlagUid); + // begin freeSlipFactory + gen::FreeSlipFactory freeSlipFactory{ blocks, pdfsId }; + // end freeSlipFactory + // begin freeSlipFromFlagField + gen::FreeSlip freeSlip { + freeSlipFactory.fromFlagField<FlagField_T>( + flagFieldId, + boundaryFlagUID, + fluidFlagUid + ) + }; + // end freeSlipFromFlagField // Timeloop const uint_t numTimesteps{simParams.getParameter<uint_t>("timesteps")}; SweepTimeloop loop{blocks->getBlockStorage(), numTimesteps}; - loop.add() << BeforeFunction(comm) << Sweep(makeSharedSweep(streamCollide)); - loop.add() << Sweep(freeSlip); + loop.add() << BeforeFunction(comm) << Sweep(freeSlip); + loop.add() << Sweep(makeSharedSweep(streamCollide)); RemainingTimeLogger logger{numTimesteps}; loop.addFuncAfterTimeStep(logger); diff --git a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py index a40d6b4c1349ef03a585c8a734d81e286dbbb3df..a2975f2617a73d9b129dc7bd55b1a308e9a37b2a 100644 --- a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py +++ b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py @@ -7,16 +7,15 @@ 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("FreeSlipBubble::gen") stencil = LBStencil(Stencil.D3Q19) d, q = stencil.D, stencil.Q - f: Field - f_tmp: Field - f, f_tmp, rho, u = fields( + pdfs: Field + pdfs_tmp: Field + pdfs, pdfs_tmp, rho, u = fields( f"f({q}), f_tmp({q}), rho, u({d}): double[{d}D]", layout="fzyx" ) # type: ignore @@ -25,25 +24,36 @@ with SourceFileGenerator() as sfg: output={"density": rho, "velocity": u}, ) lbm_opt = LBMOptimisation( - symbolic_field=f, - symbolic_temporary_field=f_tmp, + symbolic_field=pdfs, + symbolic_temporary_field=pdfs_tmp, ) lb_update = create_lb_update_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt) + lb_method = lb_update.method assert lb_update is not None lb_update_sweep = Sweep("LbStreamCollide", lb_update) - lb_update_sweep.swap_fields(f, f_tmp) + lb_update_sweep.swap_fields(pdfs, pdfs_tmp) sfg.generate(lb_update_sweep) lb_init = macroscopic_values_setter( lb_update.method, density=sp.Symbol("density"), velocity=sp.symbols(f"velocity_:{d}"), - pdfs=f, + pdfs=pdfs, ) lb_init_sweep = Sweep("LbInit", lb_init) sfg.generate(lb_init_sweep) - freeslip = FreeSlip("FreeSlip", lb_update.method, f, wall_normal=FreeSlip.IRREGULAR) + # begin irregular-freeslip + from sfg_walberla.boundaries import FreeSlip + + freeslip = FreeSlip( + "FreeSlip", + lb_method, + pdfs, + wall_normal=FreeSlip.IRREGULAR, + ) + sfg.generate(freeslip) + # end irregular-freeslip diff --git a/user_manual/examples/FreeSlipBubble/Periodic.prm b/user_manual/examples/FreeSlipBubble/Periodic.prm index 8bf1dace34ec190e4b79df77f7daa97927a84c56..2fd9fbd63f7836cce2ffb43723485ca4e01fdbc9 100644 --- a/user_manual/examples/FreeSlipBubble/Periodic.prm +++ b/user_manual/examples/FreeSlipBubble/Periodic.prm @@ -8,10 +8,10 @@ DomainSetup Parameters { omega 1.0; - timesteps 200; + timesteps 2000; } Output { - vtkWriteFrequency 10; + vtkWriteFrequency 100; } diff --git a/user_manual/guides/BoundaryConditions.md b/user_manual/guides/BoundaryConditions.md new file mode 100644 index 0000000000000000000000000000000000000000..7480c64f5648fd34511320785d1e450dea36bdb2 --- /dev/null +++ b/user_manual/guides/BoundaryConditions.md @@ -0,0 +1,56 @@ +(guide-boundary-conditions)= +# Boundary Conditions + +## Sparse Boundary Sweeps for Irregular Geometries + +To cover the boundary conditions at surfaces with irregular geometries +(i.e. surfaces not aligned with the cell grid), +we need to use a sparse implementation of the boundary sweep. + +### Generating Sparse Link-Wise LBM Boundary Sweeps + +For link-wise lattice Boltzmann boundary conditions, sparsity is enabled by +setting the `wall_normal` parameter to `IRREGULAR`: + +```{literalinclude} ../examples/FreeSlipBubble/LbmAlgorithms.py +:language: Python +:start-after: "# begin irregular-freeslip" +:end-before: "# end irregular-freeslip" +:linenos: +:dedent: 4 +:emphasize-lines: 7 +``` + +The above code will generate two classes: + - The `FreeSlip` sweep class, which is a [sparse sweep](#guide-sparse-sweeps) that applies + the free-slip boundary condition at each lattice link crossing the boundary surface; + - and the `FreeSlipFactory` class; which produces instances of the `FreeSlip` sweep and populates its + index vector from user-provided geometry information. + +### Populating the Index Vector + +Sparse boundary sweeps are created, and their index vectors populated, by their associated factory. +Create the factory object by passing it any required parameters: + +```{literalinclude} ../examples/FreeSlipBubble/FreeSlipBubble.cpp +:language: C++ +:start-after: "// begin freeSlipFactory" +:end-before: "// end freeSlipFactory" +:dedent: 8 +``` + +#### From a Flag Field + +One possibility to populate the sparse sweep is to extract boundary information stored in a *flag field*. +This requires that each *solid* cell considered by the boundary condition is marked with a *boundary flag*, +and each valid *fluid* cell is marked with the *fluid* flag. +Assuming that this information is stored in a flag field of type `FlagField_T` identified by `flagFieldId`, +and `boundaryFlagUID` and `fluidFlagUID` respectively identify the boundary and fluid flags, +we can create a sparse boundary sweep using the `fromFlagField` method of the factory: + +```{literalinclude} ../examples/FreeSlipBubble/FreeSlipBubble.cpp +:language: C++ +:start-after: "// begin freeSlipFromFlagField" +:end-before: "// end freeSlipFromFlagField" +:dedent: 8 +``` diff --git a/user_manual/guides/SparseSweeps.md b/user_manual/guides/SparseSweeps.md index 159313f0c8542839d117a651bacd9d8165128bdf..822d92fbc3894a07e09def2e2797b95d0f349e46 100644 --- a/user_manual/guides/SparseSweeps.md +++ b/user_manual/guides/SparseSweeps.md @@ -1,3 +1,4 @@ +(guide-sparse-sweeps)= # Sparse Sweeps :::{admonition} Example Code diff --git a/user_manual/index.md b/user_manual/index.md index a48e3fe493164d216d069af31192de6f64a37b51..29564ac46045ef4171c75bd23f1ee63d1e19985c 100644 --- a/user_manual/index.md +++ b/user_manual/index.md @@ -24,6 +24,7 @@ examples/GeneratorScriptBasics/GeneratorScriptBasics :maxdepth: 1 guides/SparseSweeps +guides/BoundaryConditions ::: :::{toctree}