Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (2)
......@@ -40,6 +40,14 @@ class SerialSweeper
for (uint_t x = 0; x < blocks_->getNumberOfXCellsPerBlock(); ++x)
func({ x, y, z });
}
void forAllCells(const CellInterval& ci, std::function< void(Cell) > func)
{
for (uint_t z = ci.zMin(); z <= ci.zMax(); ++z)
for (uint_t y = ci.yMin(); y <= ci.yMax(); ++y)
for (uint_t x = ci.xMin(); x <= ci.xMax(); ++x)
func({ x, y, z });
}
};
} // namespace walberla::experimental::sweep
......@@ -108,6 +108,20 @@ def get_build_config(sfg: SfgContext | SfgIComposer):
class DEBUG_MOCK_CMAKE:
BUILD_CONFIG: WalberlaBuildConfig | None = None
@staticmethod
def use_cpu_default():
DEBUG_MOCK_CMAKE.BUILD_CONFIG = WalberlaBuildConfig(
c_compiler_id="GNU",
cxx_compiler_id="GNU",
use_double_precision=True,
optimize_for_localhost=False,
mpi_enabled=False,
openmp_enabled=False,
hip_enabled=False,
cuda_enabled=False,
likwid_enabled=False,
)
@staticmethod
def use_hip_default():
DEBUG_MOCK_CMAKE.BUILD_CONFIG = WalberlaBuildConfig(
......
from __future__ import annotations
from typing import Sequence, Iterable, cast
from typing import Sequence, Iterable, cast, Callable
from dataclasses import dataclass
from itertools import chain
from collections import defaultdict
......@@ -167,12 +167,12 @@ class BlockforestParameters:
self,
property_cache: SweepClassProperties,
block: IBlockPtr,
cell_interval: CellInterval | None = None,
):
self._property_cache = property_cache
self._block = block
self._ci = cell_interval
self._extractions: dict[SfgVar, AugExpr] = dict()
self._extractions: dict[
SfgVar, AugExpr | Callable[[CellInterval | None], AugExpr]
] = dict()
self._blockforest: StructuredBlockForest | None = None
......@@ -214,8 +214,18 @@ class BlockforestParameters:
params_filtered = set()
mappings: dict[str, AugExpr] = dict()
mappings: dict[str, AugExpr | Callable[[CellInterval | None], AugExpr]] = dict()
for coord in range(3):
# Need to capture coord explicitly
# See https://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture
def ci_min(ci: CellInterval | None, c=coord) -> AugExpr:
return AugExpr.format("0") if ci is None else ci.min()[c]
def ci_max(ci: CellInterval | None, c=coord) -> AugExpr:
return AugExpr.format("0") if ci is None else ci.max()[c]
mappings.update(
{
domain.aabb_min[coord].name: (
......@@ -240,16 +250,8 @@ class BlockforestParameters:
),
block.aabb_min[coord].name: (self._block.getAABB().min()[coord]),
block.aabb_max[coord].name: (self._block.getAABB().max()[coord]),
block.ci_min[coord].name: (
AugExpr.format("0")
if self._ci is None
else self._ci.min()[coord]
),
block.ci_max[coord].name: (
AugExpr.format("0")
if self._ci is None
else self._ci.max()[coord]
),
block.ci_min[coord].name: ci_min,
block.ci_max[coord].name: ci_max,
block_cell_bb.cell_bb_min[coord].name: (
self.blockforest()
.getBlockCellBB(self._block.deref())
......@@ -276,8 +278,11 @@ class BlockforestParameters:
return params_filtered
def render_extractions(self, sfg: SfgComposer):
return (sfg.init(p)(expr) for p, expr in self._extractions.items())
def render_extractions(self, sfg: SfgComposer, ci: CellInterval | None):
return (
sfg.init(p)(expr if isinstance(expr, AugExpr) else expr(ci))
for p, expr in self._extractions.items()
)
@dataclass
......@@ -650,7 +655,7 @@ class Sweep(CustomGenerator):
parameters = khandle.scalar_parameters | ker_call_site_params
blockforest_params = BlockforestParameters(props, block, None)
blockforest_params = BlockforestParameters(props, block)
parameters = blockforest_params.filter_params(parameters)
vector_groups = combine_vectors(parameters)
......@@ -692,7 +697,7 @@ class Sweep(CustomGenerator):
for vector, components in vector_groups.items()
),
# Extract geometry information
*(blockforest_params.render_extractions(sfg)),
*(blockforest_params.render_extractions(sfg, ci)),
# Invoke the kernel
ker_invocation,
# Perform field swaps
......
......@@ -3,4 +3,6 @@ add_executable( TestBlockforestGeometry TestBlockforestGeometry.cpp )
walberla_generate_sources( TestBlockforestGeometry SCRIPTS GeometryKernels.py )
target_link_libraries( TestBlockforestGeometry PRIVATE walberla::core walberla::blockforest walberla::field walberla::experimental )
add_dependencies( SfgTests TestBlockforestGeometry )
add_test( NAME TestBlockforestGeometry COMMAND TestBlockforestGeometry )
import pystencils as ps
from pystencilssfg import SourceFileGenerator
from walberla.codegen import Sweep, get_build_config
from walberla.codegen.build_config import DEBUG_MOCK_CMAKE
from walberla.codegen.symbolic import cell, cell_index
DEBUG_MOCK_CMAKE.use_cpu_default()
with SourceFileGenerator() as sfg:
get_build_config(sfg).override.target = ps.Target.GenericCPU
......@@ -53,4 +55,3 @@ with SourceFileGenerator() as sfg:
sweep = Sweep("CellIndicesGlobal", asms)
sfg.generate(sweep)
......@@ -88,5 +88,73 @@ int main(int argc, char** argv)
});
}
/* The same with cell intervals */
CellInterval ci { Cell {1, 2, 1}, Cell (3, 3, 2) };
{
CellCentersGlobal cellCenters{ blocks, realFieldId };
sweeper.sweep([&](IBlock * b){ cellCenters.runOnCellInterval(b, ci); });
sweeper.sweep([&](IBlock& block) {
RealField& outp = *block.getData< RealField >(realFieldId);
sweeper.forAllCells(ci, [&](Cell c) {
Vector3< real_t > desired = blocks->getBlockLocalCellCenter(block, c);
WALBERLA_CHECK_FLOAT_EQUAL(outp.get(c, 0), desired[0]);
WALBERLA_CHECK_FLOAT_EQUAL(outp.get(c, 1), desired[1]);
WALBERLA_CHECK_FLOAT_EQUAL(outp.get(c, 2), desired[2]);
});
});
}
{
CellCentersLocal cellCenters{ blocks, realFieldId };
sweeper.sweep([&](IBlock * b){ cellCenters.runOnCellInterval(b, ci); });
sweeper.sweep([&](IBlock& block) {
RealField& outp = *block.getData< RealField >(realFieldId);
AABB blockAbb = block.getAABB();
sweeper.forAllCells(ci, [&](Cell c) {
Vector3< real_t > desired = blocks->getBlockLocalCellCenter(block, c) - blockAbb.min();
WALBERLA_CHECK_FLOAT_EQUAL(outp.get(c, 0), desired[0]);
WALBERLA_CHECK_FLOAT_EQUAL(outp.get(c, 1), desired[1]);
WALBERLA_CHECK_FLOAT_EQUAL(outp.get(c, 2), desired[2]);
});
});
}
{
CellIndicesLocal localIndices{ blocks, intFieldId };
sweeper.sweep([&](IBlock * b){ localIndices.runOnCellInterval(b, ci); });
sweeper.sweep([&](IBlock& block) {
Int64Field& outp = *block.getData< Int64Field >(intFieldId);
sweeper.forAllCells(ci, [&](Cell c) {
WALBERLA_CHECK_EQUAL(outp.get(c, 0), c[0]);
WALBERLA_CHECK_EQUAL(outp.get(c, 1), c[1]);
WALBERLA_CHECK_EQUAL(outp.get(c, 2), c[2]);
});
});
}
{
CellIndicesGlobal glocalIndices{ blocks, intFieldId };
sweeper.sweep([&](IBlock * b){ glocalIndices.runOnCellInterval(b, ci); });
sweeper.sweep([&](IBlock& block) {
Int64Field& outp = *block.getData< Int64Field >(intFieldId);
sweeper.forAllCells(ci, [&](Cell c) {
Cell globalCell{ c };
blocks->transformBlockLocalToGlobalCell(globalCell, block);
WALBERLA_CHECK_EQUAL(outp.get(c, 0), globalCell[0]);
WALBERLA_CHECK_EQUAL(outp.get(c, 1), globalCell[1]);
WALBERLA_CHECK_EQUAL(outp.get(c, 2), globalCell[2]);
});
});
}
return EXIT_SUCCESS;
}
\ No newline at end of file
......@@ -43,7 +43,7 @@ Now, you can run `cmake` to configure your build system:
```bash
mkdir build
cmake -S . -B build -DWALBERLA_CODEGEN_PRIVATE_VENV=ON
cmake -S . -B build
```
If, near the end of the long configuration log, you see two messages like this:
......@@ -55,19 +55,3 @@ If, near the end of the long configuration log, you see two messages like this:
Then your build system setup was successful!
Now you can get down to business and populate your project with simulation applications.
(adding_examples)=
## Adding Examples from this Manual
As you explore the examples in this book,
you can try out each by downloading, extracting, and including them into your project.
For example, to include the [force-driven poiseulle channel example](#ForceDrivenChannel),
extract its code into the `ForceDrivenChannel` subdirectory and add
```CMake
add_subdirectory( ForceDrivenChannel )
```
to your root `CMakeLists.txt`.
[FetchContent]: https://cmake.org/cmake/help/latest/module/FetchContent.html
......@@ -38,6 +38,7 @@ examples/ForceDrivenChannel/ForceDrivenChannel
:caption: Reference
:maxdepth: 1
reference/PystencilsLanguageExtensions
reference/PythonEnvironment
:::
......
# Extensions to the pystencils Language
The waLBerla code generator provides several extensions to the symbolic
language of pystencils, representing waLBerla-specific features and modelling aspects.
These are available through the `walberla.codegen.symbolic` module.
## Blockforest, Block, and Cell Geometry
WaLBerla's blockforest comprises a hierarchy of geometry-defining objects:
The global simulation domain, which has one or more refinement levels,
each home to a set of blocks, which in turn define a grid of cells.
Many of these geometric properties are modelled as symbolic functions
and therefore accessible to kernels.
As Sweep kernels are always defined with respect to a single archetypical cell,
these symbolic functions always relate to that cell and its parent block.
The following tables lists the available symbolic functions,
the geometric concept they represent,
as well as equivalent methods of the waLBerla C++ API.
All Python APIs are listed relative to `walberla.codegen.symbolic`.
### Domain Geometry
:::{list-table}
:header-rows: 1
:widths: auto
* - Concept
- Symbolic Functions
- C++ API
* - Domain Axis-Aligned Bounding Box
- `domain.[xyz]_min()`, `domain.[xyz]_max()`
- `StructuredBlockForest::getDomain()`
* - Domain Cell Bounding Box (Current Refinement Level)
- `domain_cell_bb.[xyz]_min()`, `domain_cell_bb.[xyz]_max()`
- `StructuredBlockStorage::getDomainCellBB()`
:::
### Block Geometry
:::{list-table}
:header-rows: 1
:widths: auto
* - Concept
- Symbolic Functions
- C++ API
* - Block Cell Bounding Box
- `block_cell_bb.[x|y|z]_min()`, `block_cell_bb.[x|y|z]_max()`
- `StructuredBlockForest::getBlockCellBB()`
:::
### Cell Geometry
:::{list-table}
:header-rows: 1
:widths: auto
* - Concept
- Symbolic Functions
- C++ API
* - Cell Center Coordinates in Global Coordinate System
- `cell.[x|y|z]()`
- `StructuredBlockForest::getBlockLocalCellCenter()`
* - Cell Center Coordinates in Block-Local Coordinate System
- `cell.local_[x|y|z]()`
- *No Equivalent*
* - Cell Spacing
- `cell.[dx|dy|dz]()`
- `StructuredBlockForest::[dx|dy|dz]()`
* - Cell Index in the Global Cell Grid
- `cell_index.[x|y|z]_global()`
- `StructuredBlockForest::transformBlockLocalToGlobalCell()`
* - Cell Index in the Block-Local Cell Grid
- `cell_index.[x|y|z]_local()`
- `StructuredBlockForest::transformGlobalToBlockLocalCell()`
:::