diff --git a/include/sfg/IndexVectors.hpp b/include/sfg/SparseIteration.hpp similarity index 100% rename from include/sfg/IndexVectors.hpp rename to include/sfg/SparseIteration.hpp diff --git a/src/sfg_walberla/api.py b/src/sfg_walberla/api.py index b6a1aeb7dcb177cd62adf1572580b74093511033..0be30b8dc161a51ba386b036ec897fbc019f5b5c 100644 --- a/src/sfg_walberla/api.py +++ b/src/sfg_walberla/api.py @@ -305,7 +305,7 @@ def glfield(field: Field, ci: str | AugExpr | None = None): class IndexListBufferPtr(SrcField): _template = cpptype( - "walberla::sfg::internal::IndexListBuffer< {IndexStruct} >", "sfg/IndexVectors.hpp" + "walberla::sfg::internal::IndexListBuffer< {IndexStruct} >", "sfg/SparseIteration.hpp" ) def __init__(self, idx_struct: PsStructType): diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b75a729e6afd2fc0c610b87bdc10d746850297df..59a075a72448d40f6743ba8e7bfbcd15e8e71bc8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,5 +15,3 @@ add_subdirectory(${CMAKE_SOURCE_DIR}/.. ${CMAKE_BINARY_DIR}/sfg-walberla) # Test Directories include(CTest) - -add_subdirectory( SparseIteration ) diff --git a/tests/SparseIteration/CMakeLists.txt b/tests/SparseIteration/CMakeLists.txt deleted file mode 100644 index 23666fabf4d41684ad3489000ac15993ab841fac..0000000000000000000000000000000000000000 --- a/tests/SparseIteration/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ - -add_executable( TestSparseSweeps TestSparseSweeps.cpp ) -walberla_generate_sources( TestSparseSweeps SCRIPTS SparseSweep.py ) -target_link_libraries( TestSparseSweeps PRIVATE core blockforest field sfg_walberla ) - -add_test( NAME TestSparseSweeps COMMAND TestSparseSweeps ) diff --git a/user_manual/CMakeLists.txt b/user_manual/CMakeLists.txt index 59c36c295de0103a5eb5657faee2ff1dfadc1fb4..fa52a83142e2873531d9438f09e31c4c2a86e7bb 100644 --- a/user_manual/CMakeLists.txt +++ b/user_manual/CMakeLists.txt @@ -13,5 +13,4 @@ FetchContent_MakeAvailable(walberla) add_subdirectory(${CMAKE_SOURCE_DIR}/.. ${CMAKE_BINARY_DIR}/sfg-walberla) -add_subdirectory( GeneratorScriptBasics ) -add_subdirectory( ForceDrivenChannel ) +add_subdirectory( examples ) diff --git a/user_manual/FullyPeriodicAde/AdvectionDiffusionSweep.py b/user_manual/FullyPeriodicAde/AdvectionDiffusionSweep.py deleted file mode 100644 index 876da3b324faa49e13a18a589161ffe08dfb204a..0000000000000000000000000000000000000000 --- a/user_manual/FullyPeriodicAde/AdvectionDiffusionSweep.py +++ /dev/null @@ -1,8 +0,0 @@ -from pystencilssfg import SourceFileGenerator - -from sfg_walberla import Sweep -from sfg_walberla.symbolic import cell - - -with SourceFileGenerator() as sfg: - pass diff --git a/user_manual/FullyPeriodicAde/CMakeLists.txt b/user_manual/FullyPeriodicAde/CMakeLists.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/user_manual/Makefile b/user_manual/Makefile index d931dfac6dcefe86452b20b310c390c0ea648d86..a25a0fb5753254bcfe5f61266a6b7655c85f6ce0 100644 --- a/user_manual/Makefile +++ b/user_manual/Makefile @@ -9,6 +9,7 @@ SOURCEDIR = . BUILDDIR = _sphinx_build ZIPPED_EXAMPLES := zipped-examples +EXAMPLES_DIR := examples include examples.mk @@ -33,7 +34,7 @@ clean: ZipExamples: $(foreach example, $(EXAMPLES), $(ZIPPED_EXAMPLES)/$(example).zip) -$(ZIPPED_EXAMPLES)/%.zip: %/* +$(ZIPPED_EXAMPLES)/%.zip: $(EXAMPLES_DIR)/%/* @$(dir_guard) @echo Zipping $(<D) @zip -r $@ $(<D) diff --git a/user_manual/conf.py b/user_manual/conf.py index cfa54f38b4a54d40be07e51cb183f088bdf36c32..01a1b95a1eac67d6ded174aa8f4ee18ff8a59e2c 100644 --- a/user_manual/conf.py +++ b/user_manual/conf.py @@ -6,7 +6,7 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = 'waLBerla next-codegen' +project = 'sfg-waLBerla' copyright = '2024, Frederik Hennig' author = 'Frederik Hennig' diff --git a/user_manual/examples.mk b/user_manual/examples.mk index 2d78f20423a18f80a6bc70282b541fdaee4ac96d..4ab97ae0510e8b4cebe7a5b73de8313a6a88447b 100644 --- a/user_manual/examples.mk +++ b/user_manual/examples.mk @@ -1 +1 @@ -EXAMPLES = GeneratorScriptBasics ForceDrivenChannel +EXAMPLES = GeneratorScriptBasics SparseSpiral ForceDrivenChannel diff --git a/user_manual/examples/CMakeLists.txt b/user_manual/examples/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b1419920a911b2eff471d98ad8429d8fc44c51fd --- /dev/null +++ b/user_manual/examples/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory( GeneratorScriptBasics ) +add_subdirectory( ForceDrivenChannel ) +add_subdirectory( SparseSpiral ) \ No newline at end of file diff --git a/user_manual/ForceDrivenChannel/CMakeLists.txt b/user_manual/examples/ForceDrivenChannel/CMakeLists.txt similarity index 100% rename from user_manual/ForceDrivenChannel/CMakeLists.txt rename to user_manual/examples/ForceDrivenChannel/CMakeLists.txt diff --git a/user_manual/ForceDrivenChannel/Channel.prm b/user_manual/examples/ForceDrivenChannel/Channel.prm similarity index 100% rename from user_manual/ForceDrivenChannel/Channel.prm rename to user_manual/examples/ForceDrivenChannel/Channel.prm diff --git a/user_manual/ForceDrivenChannel/ForceDrivenChannel.cpp b/user_manual/examples/ForceDrivenChannel/ForceDrivenChannel.cpp similarity index 100% rename from user_manual/ForceDrivenChannel/ForceDrivenChannel.cpp rename to user_manual/examples/ForceDrivenChannel/ForceDrivenChannel.cpp diff --git a/user_manual/ForceDrivenChannel/ForceDrivenChannel.md b/user_manual/examples/ForceDrivenChannel/ForceDrivenChannel.md similarity index 100% rename from user_manual/ForceDrivenChannel/ForceDrivenChannel.md rename to user_manual/examples/ForceDrivenChannel/ForceDrivenChannel.md diff --git a/user_manual/ForceDrivenChannel/LbmAlgorithms.py b/user_manual/examples/ForceDrivenChannel/LbmAlgorithms.py similarity index 100% rename from user_manual/ForceDrivenChannel/LbmAlgorithms.py rename to user_manual/examples/ForceDrivenChannel/LbmAlgorithms.py diff --git a/user_manual/GeneratorScriptBasics/BasicCodegen.py b/user_manual/examples/GeneratorScriptBasics/BasicCodegen.py similarity index 100% rename from user_manual/GeneratorScriptBasics/BasicCodegen.py rename to user_manual/examples/GeneratorScriptBasics/BasicCodegen.py diff --git a/user_manual/GeneratorScriptBasics/BasicCodegenApp.cpp b/user_manual/examples/GeneratorScriptBasics/BasicCodegenApp.cpp similarity index 100% rename from user_manual/GeneratorScriptBasics/BasicCodegenApp.cpp rename to user_manual/examples/GeneratorScriptBasics/BasicCodegenApp.cpp diff --git a/user_manual/GeneratorScriptBasics/CMakeLists.txt b/user_manual/examples/GeneratorScriptBasics/CMakeLists.txt similarity index 100% rename from user_manual/GeneratorScriptBasics/CMakeLists.txt rename to user_manual/examples/GeneratorScriptBasics/CMakeLists.txt diff --git a/user_manual/GeneratorScriptBasics/GeneratorScriptBasics.md b/user_manual/examples/GeneratorScriptBasics/GeneratorScriptBasics.md similarity index 100% rename from user_manual/GeneratorScriptBasics/GeneratorScriptBasics.md rename to user_manual/examples/GeneratorScriptBasics/GeneratorScriptBasics.md diff --git a/user_manual/examples/SparseSpiral/CMakeLists.txt b/user_manual/examples/SparseSpiral/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6ec9191dc263b3eee1015fa00433cbc1987a71a1 --- /dev/null +++ b/user_manual/examples/SparseSpiral/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable( SparseSpiral SparseSpiral.cpp ) +walberla_generate_sources( SparseSpiral SCRIPTS SpiralSweep.py ) +target_link_libraries( SparseSpiral PRIVATE core blockforest field vtk sfg_walberla ) + diff --git a/tests/SparseIteration/TestSparseSweeps.cpp b/user_manual/examples/SparseSpiral/SparseSpiral.cpp similarity index 67% rename from tests/SparseIteration/TestSparseSweeps.cpp rename to user_manual/examples/SparseSpiral/SparseSpiral.cpp index 272930b78f835fe387a86806662b1275e706ac15..f2b469b62870376f3b9aa47f5afc823a458b4dc7 100644 --- a/tests/SparseIteration/TestSparseSweeps.cpp +++ b/user_manual/examples/SparseSpiral/SparseSpiral.cpp @@ -2,13 +2,14 @@ #include "blockforest/all.h" #include "field/GhostLayerField.h" #include "field/AddToStorage.h" -#include "sfg/IndexVectors.hpp" +#include "field/vtk/all.h" +#include "sfg/SparseIteration.hpp" #include <array> -#include "gen/TestSparseSweeps/SparseSweep.hpp" +#include "gen/SparseSpiral/SparseSweep.hpp" -namespace TestSparseSweeps +namespace SparseSpiral { using namespace walberla; @@ -17,16 +18,22 @@ namespace TestSparseSweeps using PointField = field::GhostLayerField<real_t, 3>; + constexpr real_t radius { 15.0 }; + constexpr Vector3< real_t > center { 20, 20, 0 }; + constexpr real_t height { 120. }; + constexpr real_t width { 4.0 }; + Vector3<real_t> pointOnSpiral(real_t z) { - real_t two_pi_z{2.0 * math::pi * z}; - return Vector3<real_t>{cos(two_pi_z), sin(two_pi_z), z}; + real_t t{4.0 * math::pi * z / height}; + return center + Vector3<real_t>{radius * cos(t), radius * sin(t), z}; } void main(int argc, char **argv) { + Environment env{ argc, argv }; - AABB domainAabb{0., 0., 0., 40., 40., 120.}; + AABB domainAabb{0., 0., 0., 40., 40., height }; array<uint_t, 3> gridSize{4, 4, 12}; array<uint_t, 3> cpb{10, 10, 10}; @@ -42,18 +49,18 @@ namespace TestSparseSweeps { Vector3<real_t> globalPoint{blocks->getCellCenter(globalCell)}; Vector3<real_t> spiralPoint{pointOnSpiral(globalPoint[2])}; - return (globalPoint - spiralPoint).sqrLength() < 2.0; + return (globalPoint - spiralPoint).sqrLength() < width; }; CellInterval allCells{{0, 0, 0}, {cell_idx_c(cpb[0]), cell_idx_c(cpb[1]), cell_idx_c(cpb[2])}}; for (auto &b : *blocks) { - vector<sfg::CellIdx> idxVec{indexList.get(b)}; + vector<sfg::CellIdx> & idxVec{indexList.get(b)}; for (Cell c : allCells) { Cell globalCell{c}; - blocks->transformBlockLocalToGlobalCell(c, b); + blocks->transformBlockLocalToGlobalCell(globalCell, b); if (isOnSpiral(globalCell)) { idxVec.emplace_back(c); @@ -61,7 +68,7 @@ namespace TestSparseSweeps } } - gen::SparseSetCoordinates sweep{blocks, fID, indexList.bufferId()}; + gen::SpiralSweep sweep{blocks, fID, indexList.bufferId()}; for (auto &b : *blocks) { @@ -74,7 +81,7 @@ namespace TestSparseSweeps for (Cell c : allCells) { Cell globalCell{c}; - blocks->transformBlockLocalToGlobalCell(c, b); + blocks->transformBlockLocalToGlobalCell(globalCell, b); if (isOnSpiral(c)) { Vector3< real_t > cellCenter { blocks->getCellCenter(globalCell) }; @@ -84,11 +91,14 @@ namespace TestSparseSweeps } } } + + auto vtkWriter = field::createVTKOutput< PointField >(fID, *blocks, "f", 1, 0); + vtkWriter(); } } int main(int argc, char **argv) { - TestSparseSweeps::main(argc, argv); + SparseSpiral::main(argc, argv); return 0; -} \ No newline at end of file +} diff --git a/tests/SparseIteration/SparseSweep.py b/user_manual/examples/SparseSpiral/SpiralSweep.py similarity index 82% rename from tests/SparseIteration/SparseSweep.py rename to user_manual/examples/SparseSpiral/SpiralSweep.py index 4489d3beee63edae16f324fb82c50a568134b22b..f9808a5ad79fdfa5b9444e6035e7b5773460b0ab 100644 --- a/tests/SparseIteration/SparseSweep.py +++ b/user_manual/examples/SparseSpiral/SpiralSweep.py @@ -4,7 +4,7 @@ from sfg_walberla.symbolic import cell from pystencils import fields, Assignment with SourceFileGenerator() as sfg: - sfg.namespace("TestSparseSweeps::gen") + sfg.namespace("SparseSpiral::gen") f = fields("f(3): [3D]", layout="fzyx") asms = [ @@ -13,7 +13,7 @@ with SourceFileGenerator() as sfg: Assignment(f.center(2), cell.z()), ] - sweep = Sweep("SparseSetCoordinates", asms) + sweep = Sweep("SpiralSweep", asms) sweep.sparse = True sfg.generate(sweep) diff --git a/user_manual/guides/SparseSweeps.md b/user_manual/guides/SparseSweeps.md new file mode 100644 index 0000000000000000000000000000000000000000..03fea2eb4b4a187354a0b4ebf5bfefed62ead208 --- /dev/null +++ b/user_manual/guides/SparseSweeps.md @@ -0,0 +1,34 @@ +# Sparse Sweeps + +:::{admonition} Example Code +The code shown in this guide is taken from the *SparseSpiral* example: +{download}`SparseSpiral.zip </zipped-examples/SparseSpiral.zip>` +::: + + +`sfg-walberla` supports the generation of sparse sweeps, which operate only on a subset of cells +defined by a user-provided *index list*. + +To turn your sweep into a sparse sweep, simply set its `sparse` property to `True`. +To illustrate, here's a sparse sweep that stores the coordinates of each cell +in a field: + +```{literalinclude} ../examples/SparseSpiral/SpiralSweep.py +:caption: SpiralSweep.py +:lines: 10-17 +:dedent: 4 +``` + +In your C++ code, you must set up an index list which lists all cells the sweep should operate on. +Due to waLBerla's block-structured nature, the index list will actually be a collection of cell vectors, +with one vector per block. +The SFG library provides `sfg::SparseIndexList` for this, which is defined in `sfg/SparseIteration.hpp`. +The following code sample create and populate an index list, using a prediate here called `isOnSpiral`. +The index list's internal block data ID must then be passed to the sweep's constructor. + +:::{literalinclude} ../examples/SparseSpiral/SparseSpiral.cpp +:caption: SparseSpiral.cpp +:lines: 46,56-72 +:dedent: 8 +:language: C++ +::: diff --git a/user_manual/index.md b/user_manual/index.md index 473b4f1a05c50df6418adf4cad216475acf8e0dd..a48e3fe493164d216d069af31192de6f64a37b51 100644 --- a/user_manual/index.md +++ b/user_manual/index.md @@ -1,19 +1,13 @@ # The Next Generation of waLBerla Code Generation -Welcome to *The Next Generation of waLBerla Code Generation*. -This book is aimed at teaching you how to use the next generation of code generators for waLBerla -by walking through a set of example applications, each designed to highlight specific features. - -The next-gen code generators for waLBerla are based on bleeding-edge developments in -[pystencils 2.0][pystencils_2_0] and [pystencils-sfg][pystencils-sfg], -and are currently located in the separate [sfg-walberla][sfg-walberla] repository. +Welcome to the `sfg-walberla` project, +where the next generation of code generators for waLBerla is being developed. +These are based on bleeding-edge developments in +[pystencils 2.0][pystencils_2_0] and [pystencils-sfg][pystencils-sfg]. This project is still unstable and immature, but growing steadily. -Until the next-gen code generators are stabilized and merged with the waLBerla master, -setting up a build system and development environment for working with them is slightly more -complicated. Since you will need such an environment to follow along with the examples -in this book, start by reading the chapter [](EnvSetup). -Afterward, you are free to explore the remainder of the book. +In this user manual, you will find guidance and information about how to use the new +code generation infrastructure in your simulation applications. ## Table of Contents @@ -22,14 +16,21 @@ Afterward, you are free to explore the remainder of the book. :maxdepth: 1 CMakeSetup/CMakeSetup -GeneratorScriptBasics/GeneratorScriptBasics +examples/GeneratorScriptBasics/GeneratorScriptBasics +::: + +:::{toctree} +:caption: User Guides +:maxdepth: 1 + +guides/SparseSweeps ::: :::{toctree} -:caption: Basic LBM Simulations +:caption: Examples :maxdepth: 1 -ForceDrivenChannel/ForceDrivenChannel +examples/ForceDrivenChannel/ForceDrivenChannel ::: :::{toctree} diff --git a/user_manual/reference/PythonEnvironment.md b/user_manual/reference/PythonEnvironment.md index 298d83a05835c0ff193257fbf00e0d38405b83ec..df1530814c6606a9998f221ee30dd2d125c55728 100644 --- a/user_manual/reference/PythonEnvironment.md +++ b/user_manual/reference/PythonEnvironment.md @@ -5,9 +5,9 @@ used by the waLBerla code generation system. ## Using the Private Virtual Environment -If the CMake cache variable `WALBERLA_CODEGEN_PRIVATE_VENV` is enabled, -`sfg-walberla` creates a new Python virtual environment within the CMake build tree, +By default, `sfg-walberla` creates a new Python virtual environment within the CMake build tree, and there installs all packages required for code generation. +This can be disabled by setting the `WALBERLA_CODEGEN_PRIVATE_VENV` CMake cache variable to `FALSE`. ### Install Additional Packages @@ -26,14 +26,13 @@ editable install, or `-r <requirements-file>` to install packages from a require ## Using an External Virtual Environment -To have even more control over your Python environment, you can configure sfg-walberla to -forego creating a private virtual environment, and instead use the Python interpreter -supplied from the outside. +If `WALBERLA_CODEGEN_PRIVATE_VENV` is set to `FALSE`, sfg-walberla will use the Python interpreter +found in the CMake environment for running the code generators. +You can customize your Python interpreter by setting the `Python_EXECUTABLE` or `Python_ROOT_DIR` hints. -To explicitly specify a Python interpreter, you need to set the `WALBERLA_CODEGEN_PRIVATE_VENV` cache -variable to `FALSE`, and set `Python_EXECUTABLE` to point at your Python binary. -For instance, at configuration time: +:::{seealso} +[FindPython CMake Module](https://cmake.org/cmake/help/latest/module/FindPython.html) +::: -```bash -cmake -S . -B build -DWALBERLA_CODEGEN_PRIVATE_VENV=FALSE -DPython_EXECUTABLE=<path-to-python> -``` +Sfg-walberla will check if the required packages are installed into the given external Python environment, +and raise an error if any are missing.