29#include <blockforest/Initialization.h>
30#include <blockforest/StructuredBlockForest.h>
31#include <blockforest/communication/UniformBufferedScheme.h>
32#include <domain_decomposition/BlockDataID.h>
33#include <domain_decomposition/IBlock.h>
34#include <field/AddToStorage.h>
35#include <field/GhostLayerField.h>
36#include <field/communication/PackInfo.h>
37#include <field/vtk/FlagFieldCellFilter.h>
38#include <field/vtk/VTKWriter.h>
39#include <stencil/D3Q19.h>
40#include <stencil/D3Q27.h>
41#if defined(__CUDACC__)
42#include <gpu/AddGPUFieldToStorage.h>
43#include <gpu/communication/MemcpyPackInfo.h>
44#include <gpu/communication/UniformGPUScheme.h>
47#include "../BoundaryHandling.hpp"
48#include "../BoundaryPackInfo.hpp"
49#include "../utils/boundary.hpp"
50#include "../utils/types_conversion.hpp"
54#if defined(__CUDACC__)
73#include <initializer_list>
88template <
typename FloatType, lbmpy::Arch Architecture>
92 typename detail::KernelTrait<FloatType,
95 typename detail::KernelTrait<FloatType,
103 typename detail::BoundaryHandlingTrait<
104 FloatType, Architecture>::Dynamic_UBB>;
106 std::variant<CollisionModelThermalized, CollisionModelLeesEdwards>;
117 template <
typename FT, lbmpy::Arch AT = lbmpy::Arch::CPU>
struct FieldTrait {
118 using PdfField = field::GhostLayerField<FT, Stencil::Size>;
120 template <
class Field>
121 using PackInfo = field::communication::PackInfo<Field>;
126 template <
class Stencil>
128 blockforest::communication::UniformBufferedScheme<Stencil>;
129 template <
class Stencil>
131 blockforest::communication::UniformBufferedScheme<Stencil>;
134#if defined(__CUDACC__)
138 template <
class Field>
139 using MemcpyPackInfo = gpu::communication::MemcpyPackInfo<Field>;
142 template <
typename Stencil>
143 class UniformGPUScheme
144 :
public gpu::communication::UniformGPUScheme<Stencil> {
146 explicit UniformGPUScheme(
auto const &bf)
147 : gpu::communication::UniformGPUScheme<Stencil>(
153 template <
class Field>
using PackInfo = MemcpyPackInfo<Field>;
158 template <
class Stencil>
160 template <
class Stencil>
162 blockforest::communication::UniformBufferedScheme<Stencil>;
174#if defined(__CUDACC__)
175 using GPUField = gpu::GPUField<FloatType>;
191 return numeric_cast<FloatType>(t);
195 return static_cast<std::size_t
>(Stencil::Size);
199 return std::is_same_v<FloatType, double>;
203 class CollideSweepVisitor {
208 cm.configure(m_storage, b);
213 cm.v_s_ =
static_cast<decltype(cm.v_s_)
>(
214 m_lees_edwards_callbacks->get_shear_velocity());
218 CollideSweepVisitor() =
default;
219 CollideSweepVisitor(std::shared_ptr<StructuredBlockStorage> storage) {
220 m_storage = std::move(storage);
222 CollideSweepVisitor(std::shared_ptr<StructuredBlockStorage> storage,
223 std::shared_ptr<LeesEdwardsPack> callbacks) {
224 m_storage = std::move(storage);
225 m_lees_edwards_callbacks = std::move(callbacks);
229 std::shared_ptr<StructuredBlockStorage> m_storage{};
230 std::shared_ptr<LeesEdwardsPack> m_lees_edwards_callbacks{};
232 CollideSweepVisitor m_run_collide_sweep{};
234 FloatType shear_mode_relaxation_rate()
const {
235 return FloatType{2} / (FloatType{6} *
m_viscosity + FloatType{1});
238 FloatType odd_mode_relaxation_rate(
239 FloatType shear_relaxation,
240 FloatType magic_number = FloatType{3} / FloatType{16})
const {
241 return (FloatType{4} - FloatType{2} * shear_relaxation) /
242 (FloatType{4} * magic_number * shear_relaxation + FloatType{2} -
246 void reset_boundary_handling() {
252 FloatType pressure_tensor_correction_factor()
const {
256 void pressure_tensor_correction(Matrix3<FloatType> &tensor)
const {
257 auto const revert_factor = pressure_tensor_correction_factor();
258 for (
auto const i : {1u, 2u, 3u, 5u, 6u, 7u}) {
259 tensor[i] *= revert_factor;
263 void pressure_tensor_correction(std::span<FloatType, 9ul> tensor)
const {
264 auto const revert_factor = pressure_tensor_correction_factor();
265 for (
auto const i : {1u, 2u, 3u, 5u, 6u, 7u}) {
266 tensor[i] *= revert_factor;
270 class interpolation_illegal_access :
public std::runtime_error {
272 explicit interpolation_illegal_access(std::string
const &field,
274 std::array<int, 3>
const &node,
276 : std::runtime_error(
"Access to LB " + field +
" field failed") {
278 <<
"], weight " <<
weight <<
"\n";
285 std::string
const &reason)
286 : std::runtime_error(
"VTKOutput object '" + vtk_uid +
"' " + reason) {}
319 typename stencil::D3Q27>;
322 typename stencil::D3Q27>;
329 Architecture>::template RegularCommScheme<Stencil>;
330 template <
class Field>
351 std::shared_ptr<InterpolateAndShiftAtBoundary<_PdfField, FloatType>>
353 std::shared_ptr<InterpolateAndShiftAtBoundary<_VectorField, FloatType>>
355 std::shared_ptr<InterpolateAndShiftAtBoundary<_VectorField, FloatType>>
367 [[nodiscard]] std::optional<CellInterval>
371 auto const &cell_min = lower_corner;
375 if (not lower_bc or not upper_bc) {
378 assert(&(*(lower_bc->block)) == &(*(upper_bc->block)));
379 return {CellInterval(lower_bc->cell, upper_bc->cell)};
394 auto const &blocks =
m_lattice->get_blocks();
395 auto const n_ghost_layers =
m_lattice->get_ghost_layers();
397#ifdef ESPRESSO_BUILD_WITH_AVX_KERNELS
398#if defined(__AVX512F__)
399 constexpr uint_t alignment = 64u;
400#elif defined(__AVX__)
401 constexpr uint_t alignment = 32u;
402#elif defined(__SSE__)
403 constexpr uint_t alignment = 16u;
405#error "Unsupported arch, check walberla src/field/allocation/FieldAllocator.h"
407 using value_type =
typename Field::value_type;
408 using Allocator = field::AllocateAligned<value_type, alignment>;
409 auto const allocator = std::make_shared<Allocator>();
410 auto const empty_set = Set<SUID>::emptySet();
411 return field::addToStorage<Field>(
412 blocks, tag, field::internal::defaultSize, FloatType{0}, field::fzyx,
413 n_ghost_layers,
false, {}, empty_set, empty_set, allocator);
415 return field::addToStorage<Field>(blocks, tag, FloatType{0}, field::fzyx,
419#if defined(__CUDACC__)
421 auto field_id = gpu::addGPUFieldToStorage<GPUField>(
422 blocks, tag, Field::F_SIZE, field::fzyx, n_ghost_layers);
423 if constexpr (std::is_same_v<Field, _VectorField>) {
425 auto field =
block->template getData<GPUField>(field_id);
428 }
else if constexpr (std::is_same_v<Field, _PdfField>) {
430 auto field =
block->template getData<GPUField>(field_id);
432 field, std::array<FloatType, Stencil::Size>{});
441 auto const setup = [
this]<
typename PackInfoPdf,
typename PackInfoVec>() {
442 auto const &blocks =
m_lattice->get_blocks();
444 std::make_shared<PDFStreamingCommunicator>(blocks);
456 setup.template operator()<PackInfoPdf, PackInfoVec>();
466 auto const &blocks =
m_lattice->get_blocks();
467 auto const n_ghost_layers =
m_lattice->get_ghost_layers();
468 if (n_ghost_layers == 0u)
469 throw std::runtime_error(
"At least one ghost layer must be used");
483 for (
auto b = blocks->begin(); b != blocks->end(); ++b) {
489 blocks,
"flag field", n_ghost_layers);
491 reset_boundary_handling();
515 std::make_shared<BoundaryFullCommunicator>(blocks);
517 std::make_shared<field::communication::PackInfo<FlagField>>(
519 auto boundary_packinfo = std::make_shared<
529 m_reset_force = std::make_shared<ResetForce<PdfField, VectorField>>(
536 m_stream = std::make_shared<StreamSweep>(
541 void integrate_stream(std::shared_ptr<Lattice_T>
const &blocks) {
542 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
546 void integrate_collide(std::shared_ptr<Lattice_T>
const &blocks) {
548 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
549 std::visit(m_run_collide_sweep, cm_variant, std::variant<IBlock *>(&*b));
550 if (
auto *cm = std::get_if<CollisionModelThermalized>(&cm_variant)) {
555 auto has_lees_edwards_bc()
const {
556 return std::holds_alternative<CollisionModelLeesEdwards>(
560 void apply_lees_edwards_pdf_interpolation(
561 std::shared_ptr<Lattice_T>
const &blocks) {
562 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
566 void apply_lees_edwards_vel_interpolation_and_shift(
567 std::shared_ptr<Lattice_T>
const &blocks) {
568 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
572 void apply_lees_edwards_last_applied_force_interpolation(
573 std::shared_ptr<Lattice_T>
const &blocks) {
574 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
578 void integrate_reset_force(std::shared_ptr<Lattice_T>
const &blocks) {
579 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
583 void integrate_boundaries(std::shared_ptr<Lattice_T>
const &blocks) {
584 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
588 void integrate_push_scheme() {
591 integrate_reset_force(blocks);
593 integrate_collide(blocks);
597 integrate_boundaries(blocks);
600 integrate_stream(blocks);
609 void integrate_pull_scheme() {
613 integrate_boundaries(blocks);
616 integrate_stream(blocks);
618 integrate_collide(blocks);
620 integrate_reset_force(blocks);
632 auto &vtk_handle = it.second;
633 if (vtk_handle->enabled) {
634 vtk::writeFiles(vtk_handle->ptr)();
635 vtk_handle->execution_count++;
642 if (has_lees_edwards_bc()) {
643 integrate_pull_scheme();
645 integrate_push_scheme();
661 if (has_lees_edwards_bc()) {
663 apply_lees_edwards_pdf_interpolation(blocks);
672 if (has_lees_edwards_bc()) {
674 apply_lees_edwards_vel_interpolation_and_shift(blocks);
683 if (has_lees_edwards_bc()) {
685 apply_lees_edwards_last_applied_force_interpolation(blocks);
700 if (has_lees_edwards_bc()) {
702 apply_lees_edwards_pdf_interpolation(blocks);
703 apply_lees_edwards_vel_interpolation_and_shift(blocks);
704 apply_lees_edwards_last_applied_force_interpolation(blocks);
712 if (has_lees_edwards_bc()) {
715 apply_lees_edwards_pdf_interpolation(blocks);
716 apply_lees_edwards_vel_interpolation_and_shift(blocks);
717 apply_lees_edwards_last_applied_force_interpolation(blocks);
725 auto const omega = shear_mode_relaxation_rate();
726 auto const omega_odd = odd_mode_relaxation_rate(omega);
732 omega_odd, omega, seed, uint32_t{0u});
734 m_run_collide_sweep = CollideSweepVisitor(blocks);
739 std::unique_ptr<LeesEdwardsPack> &&lees_edwards_pack)
override {
741#if defined(__CUDACC__)
743 throw std::runtime_error(
"Lees-Edwards LB doesn't support GPU yet");
746 auto const shear_direction = lees_edwards_pack->shear_direction;
747 auto const shear_plane_normal = lees_edwards_pack->shear_plane_normal;
748 auto const shear_vel =
FloatType_c(lees_edwards_pack->get_shear_velocity());
749 auto const omega = shear_mode_relaxation_rate();
750 if (shear_plane_normal != 1u) {
751 throw std::domain_error(
752 "Lees-Edwards LB only supports shear_plane_normal=\"y\"");
755 auto const n_ghost_layers = lattice.get_ghost_layers();
756 auto const blocks = lattice.get_blocks();
758 FloatType_c(lattice.get_grid_dimensions()[shear_plane_normal]);
765 std::make_shared<InterpolateAndShiftAtBoundary<_PdfField, FloatType>>(
767 shear_direction, shear_plane_normal,
772 shear_direction, shear_plane_normal,
778 n_ghost_layers, shear_direction, shear_plane_normal,
784 unsigned int shear_plane_normal)
const override {
788 throw std::runtime_error(
789 "MD and LB Lees-Edwards boundary conditions disagree");
807 std::optional<Utils::Vector3d>
809 bool consider_ghosts =
false)
const override {
814 if (is_boundary and *is_boundary) {
822 auto field = bc->block->template uncheckedFastGetData<VectorField>(
837 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
842 auto const vel = to_vector3<FloatType>(v);
852 std::vector<double> out;
853 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
855 auto const &
block = *(lattice.get_blocks()->begin());
859 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
860 assert(values.size() == 3u * ci->numCells());
861 if constexpr (std::is_same_v<
typename decltype(values)::value_type,
863 out = std::move(values);
865 out = std::vector<double>(values.begin(), values.end());
867 auto const local_offset = std::get<0>(lattice.get_local_grid_range());
868 auto const lower_cell = ci->min();
869 auto const upper_cell = ci->max();
870 auto it = out.begin();
871 for (
auto x = lower_cell.x(); x <= upper_cell.x(); ++x) {
872 for (
auto y = lower_cell.y(); y <= upper_cell.y(); ++y) {
873 for (
auto z = lower_cell.z(); z <= upper_cell.z(); ++z) {
876 auto const &vec =
m_boundary->get_node_value_at_boundary(node);
877 for (uint_t f = 0u; f < 3u; ++f) {
878 (*it) = double_c(vec[f]);
879 std::advance(it, 1l);
882 std::advance(it, 3l);
893 std::vector<double>
const &
velocity)
override {
896 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
898 auto &
block = *(lattice.get_blocks()->begin());
903 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
911 [[nodiscard]]
bool is_gpu() const noexcept
override {
916 std::vector<Utils::Vector3d>
const &forces)
override {
917 assert(pos.size() == forces.size());
922 for (std::size_t i = 0ul; i < pos.size(); ++i) {
926#if defined(__CUDACC__)
929 auto const &
block = *(lattice.get_blocks()->begin());
930 auto const origin =
block.getAABB().min();
931 std::vector<FloatType> host_pos;
932 std::vector<FloatType> host_force;
933 host_pos.reserve(3ul * pos.size());
934 host_force.reserve(3ul * forces.size());
935 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
936 for (
auto const &vec : pos) {
938 for (std::size_t i : {0ul, 1ul, 2ul}) {
939 host_pos.emplace_back(
static_cast<FloatType
>(vec[i] - origin[i]));
942 for (
auto const &vec : forces) {
944 for (std::size_t i : {0ul, 1ul, 2ul}) {
945 host_force.emplace_back(
static_cast<FloatType
>(vec[i]));
948 auto const gl = lattice.get_ghost_layers();
949 auto field =
block.template uncheckedFastGetData<VectorField>(
956 std::vector<Utils::Vector3d>
962 std::vector<Utils::Vector3d> vel{};
963 vel.reserve(pos.size());
964 for (
auto const &vec : pos) {
966 assert(res.has_value());
967 vel.emplace_back(*res);
971#if defined(__CUDACC__)
974 auto const &
block = *(lattice.get_blocks()->begin());
975 auto const origin =
block.getAABB().min();
976 std::vector<FloatType> host_pos;
977 host_pos.reserve(3ul * pos.size());
978 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
979 for (
auto const &vec : pos) {
981 for (std::size_t i : {0ul, 1ul, 2ul}) {
982 host_pos.emplace_back(
static_cast<FloatType
>(vec[i] - origin[i]));
985 auto const gl = lattice.get_ghost_layers();
989 std::vector<Utils::Vector3d> vel{};
990 vel.reserve(res.size() / 3ul);
991 for (
auto it = res.begin(); it != res.end(); it += 3) {
993 static_cast<double>(*(it + 1)),
994 static_cast<double>(*(it + 2))});
1002 std::optional<Utils::Vector3d>
1004 bool consider_points_in_halo =
false)
const override {
1007 if (!consider_points_in_halo and !
m_lattice->pos_in_local_domain(pos))
1008 return std::nullopt;
1009 if (consider_points_in_halo and !
m_lattice->pos_in_local_halo(pos))
1010 return std::nullopt;
1013 pos, [
this, &v, &pos](std::array<int, 3>
const node,
double weight) {
1019 throw interpolation_illegal_access(
"velocity", pos, node,
weight);
1024 return {std::move(v)};
1027 std::optional<double>
1029 bool consider_points_in_halo =
false)
const override {
1031 if (!consider_points_in_halo and !
m_lattice->pos_in_local_domain(pos))
1032 return std::nullopt;
1033 if (consider_points_in_halo and !
m_lattice->pos_in_local_halo(pos))
1034 return std::nullopt;
1037 pos, [
this, &dens, &pos](std::array<int, 3>
const node,
double weight) {
1043 throw interpolation_illegal_access(
"density", pos, node,
weight);
1048 return {std::move(dens)};
1056 auto const force_at_node = [
this, &force](std::array<int, 3>
const node,
1061 auto const weighted_force = to_vector3<FloatType>(
weight * force);
1063 bc->block->template uncheckedFastGetData<VectorField>(
1072 std::optional<Utils::Vector3d>
1076 return std::nullopt;
1084 std::optional<Utils::Vector3d>
1086 bool consider_ghosts =
false)
const override {
1090 return std::nullopt;
1106 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1111 auto const vec = to_vector3<FloatType>(force);
1120 std::vector<double> out;
1121 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1123 auto const &
block = *(lattice.get_blocks()->begin());
1127 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
1128 assert(values.size() == 3u * ci->numCells());
1129 if constexpr (std::is_same_v<
typename decltype(values)::value_type,
1131 out = std::move(values);
1133 out = std::vector<double>(values.begin(), values.end());
1141 std::vector<double>
const &force)
override {
1144 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1146 auto &
block = *(lattice.get_blocks()->begin());
1151 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
1152 assert(force.size() == 3u * ci->numCells());
1153 std::vector<FloatType>
const values(force.begin(), force.end());
1159 std::optional<std::vector<double>>
1161 bool consider_ghosts =
false)
const override {
1165 return std::nullopt;
1167 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1169 std::vector<double> population(Stencil::Size);
1170 for (uint_t f = 0u; f < Stencil::Size; ++f) {
1171 population[f] = double_c(pop[f]);
1174 return {std::move(population)};
1178 std::vector<double>
const &population)
override {
1185 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1190 std::array<FloatType, Stencil::Size> pop;
1191 for (uint_t f = 0u; f < Stencil::Size; ++f) {
1203 std::vector<double> out;
1204 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1206 auto const &
block = *(lattice.get_blocks()->begin());
1209 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
1210 assert(values.size() ==
stencil_size() * ci->numCells());
1211 if constexpr (std::is_same_v<
typename decltype(values)::value_type,
1213 out = std::move(values);
1215 out = std::vector<double>(values.begin(), values.end());
1223 std::vector<double>
const &population)
override {
1224 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1226 auto &
block = *(lattice.get_blocks()->begin());
1231 assert(population.size() ==
stencil_size() * ci->numCells());
1232 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
1233 std::vector<FloatType>
const values(population.begin(), population.end());
1240 std::optional<double>
1242 bool consider_ghosts =
false)
const override {
1246 return std::nullopt;
1249 bc->block->template uncheckedFastGetData<PdfField>(
m_pdf_field_id);
1260 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1269 std::vector<double> out;
1270 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1272 auto const &
block = *(lattice.get_blocks()->begin());
1275 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
1276 assert(values.size() == ci->numCells());
1277 if constexpr (std::is_same_v<
typename decltype(values)::value_type,
1279 out = std::move(values);
1281 out = std::vector<double>(values.begin(), values.end());
1289 std::vector<double>
const &
density)
override {
1291 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1293 auto &
block = *(lattice.get_blocks()->begin());
1295 assert(
density.size() == ci->numCells());
1296 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
1297 std::vector<FloatType>
const values(
density.begin(),
density.end());
1302 std::optional<Utils::Vector3d>
1304 bool consider_ghosts =
false)
const override {
1307 if (!bc or !
m_boundary->node_is_boundary(node))
1308 return std::nullopt;
1320 node, to_vector3<FloatType>(
velocity), *bc);
1322 return bc.has_value();
1328 std::vector<std::optional<Utils::Vector3d>> out;
1329 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1331 auto const local_offset = std::get<0>(lattice.get_local_grid_range());
1332 auto const lower_cell = ci->min();
1333 auto const upper_cell = ci->max();
1334 auto const n_values = ci->numCells();
1335 out.reserve(n_values);
1336 for (
auto x = lower_cell.x(); x <= upper_cell.x(); ++x) {
1337 for (
auto y = lower_cell.y(); y <= upper_cell.y(); ++y) {
1338 for (
auto z = lower_cell.z(); z <= upper_cell.z(); ++z) {
1344 out.emplace_back(std::nullopt);
1349 assert(out.size() == n_values);
1356 std::vector<std::optional<Utils::Vector3d>>
const &
velocity)
override {
1359 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1361 auto const local_offset = std::get<0>(lattice.get_local_grid_range());
1362 auto const lower_cell = ci->min();
1363 auto const upper_cell = ci->max();
1366 for (
auto x = lower_cell.x(); x <= upper_cell.x(); ++x) {
1367 for (
auto y = lower_cell.y(); y <= upper_cell.y(); ++y) {
1368 for (
auto z = lower_cell.z(); z <= upper_cell.z(); ++z) {
1371 auto const &opt = *it;
1374 node, to_vector3<FloatType>(*opt), *bc);
1376 m_boundary->remove_node_from_boundary(node, *bc);
1385 std::optional<Utils::Vector3d>
1388 if (!bc or !
m_boundary->node_is_boundary(node))
1389 return std::nullopt;
1397 m_boundary->remove_node_from_boundary(node, *bc);
1399 return bc.has_value();
1404 bool consider_ghosts =
false)
const override {
1408 return std::nullopt;
1416 std::vector<bool> out;
1417 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1419 auto const local_offset = std::get<0>(lattice.get_local_grid_range());
1420 auto const lower_cell = ci->min();
1421 auto const upper_cell = ci->max();
1422 auto const n_values = ci->numCells();
1423 out.reserve(n_values);
1424 for (
auto x = lower_cell.x(); x <= upper_cell.x(); ++x) {
1425 for (
auto y = lower_cell.y(); y <= upper_cell.y(); ++y) {
1426 for (
auto z = lower_cell.z(); z <= upper_cell.z(); ++z) {
1428 out.emplace_back(
m_boundary->node_is_boundary(node));
1432 assert(out.size() == n_values);
1448 reset_boundary_handling();
1457 std::vector<double>
const &data_flat)
override {
1468 std::optional<Utils::VectorXd<9>>
1472 return std::nullopt;
1474 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1476 pressure_tensor_correction(tensor);
1484 std::vector<double> out;
1485 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1487 auto const &
block = *(lattice.get_blocks()->begin());
1490 assert(++(lattice.get_blocks()->begin()) == lattice.get_blocks()->end());
1491 assert(values.size() == 9u * ci->numCells());
1492 for (
auto it = values.begin(); it != values.end(); std::advance(it, 9l)) {
1493 pressure_tensor_correction(std::span<FloatType, 9ul>(it, 9ul));
1495 if constexpr (std::is_same_v<
typename decltype(values)::value_type,
1497 out = std::move(values);
1499 out = std::vector<double>(values.begin(), values.end());
1508 Matrix3<FloatType> tensor(FloatType{0});
1511 WALBERLA_FOR_ALL_CELLS_XYZ(pdf_field, {
1517 pressure_tensor_correction(tensor);
1518 return to_vector9d(tensor) * (1. /
static_cast<double>(number_of_nodes));
1524 Vector3<FloatType> mom(FloatType{0});
1543 [[nodiscard]]
double get_kT() const noexcept
override {
1544 return numeric_cast<double>(
m_kT);
1547 [[nodiscard]]
unsigned int get_seed() const noexcept
override {
1553 if (!cm or
m_kT == 0.) {
1554 return std::nullopt;
1556 return {
static_cast<uint64_t
>(cm->time_step_)};
1561 if (!cm or
m_kT == 0.) {
1562 throw std::runtime_error(
"This LB instance is unthermalized");
1565 static_cast<uint32_t
>(std::numeric_limits<uint_t>::max()));
1566 cm->time_step_ =
static_cast<uint32_t
>(counter);
1583 throw std::runtime_error(
"VTK output not supported for GPU");
1587 vtk_obj.addCellExclusionFilter(fluid_filter);
1592 template <
typename Field_T, u
int_t F_SIZE_ARG,
typename OutputType>
1593 class VTKWriter :
public vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG> {
1595 VTKWriter(ConstBlockDataID
const &block_id, std::string
const &
id,
1596 FloatType unit_conversion)
1597 : vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG>(id),
1603 WALBERLA_ASSERT_NOT_NULLPTR(this->block_);
1612 template <
typename OutputType =
float>
1617 using Base::evaluate;
1620 OutputType
evaluate(cell_idx_t
const x, cell_idx_t
const y,
1621 cell_idx_t
const z, cell_idx_t
const)
override {
1622 WALBERLA_ASSERT_NOT_NULLPTR(this->
m_field);
1629 template <
typename OutputType =
float>
1634 using Base::evaluate;
1637 OutputType
evaluate(cell_idx_t
const x, cell_idx_t
const y,
1638 cell_idx_t
const z, cell_idx_t
const f)
override {
1639 WALBERLA_ASSERT_NOT_NULLPTR(this->
m_field);
1646 template <
typename OutputType =
float>
1651 using Base::evaluate;
1654 std::string
const &
id, FloatType unit_conversion,
1655 FloatType off_diag_factor)
1656 :
Base(block_id, id, unit_conversion),
1660 OutputType
evaluate(cell_idx_t
const x, cell_idx_t
const y,
1661 cell_idx_t
const z, cell_idx_t
const f)
override {
1662 WALBERLA_ASSERT_NOT_NULLPTR(this->
m_field);
1663 auto const pressure =
1665 auto const revert_factor =
1667 return numeric_cast<OutputType>(this->
m_conversion * revert_factor *
1668 pressure[uint_c(f)]);
1676 int flag_observables)
override {
1678 throw std::runtime_error(
"VTK output not supported for GPU");
1681 auto const unit_conversion =
FloatType_c(units.at(
"density"));
1686 auto const unit_conversion =
FloatType_c(units.at(
"velocity"));
1691 auto const unit_conversion =
FloatType_c(units.at(
"pressure"));
1692 vtk_obj.addCellDataWriter(
1695 pressure_tensor_correction_factor()));
LBWalberlaBase provides the public interface of the LB waLBerla bridge.
Vector implementation and trait types for boost qvm interoperability.
Interface of a lattice-based fluid model.
std::map< std::string, std::shared_ptr< VTKHandle > > m_vtk_auto
VTK writers that are executed automatically.
std::unordered_map< std::string, double > units_map
Class that runs and controls the BlockForest in waLBerla.
walberla::blockforest::StructuredBlockForest Lattice_T
auto get_grid_dimensions() const
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value)
Create a vector that has all entries set to the same value.
Boundary class optimized for sparse data.
field::FlagField< uint8_t > FlagField
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const) override
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const f) override
FloatType const m_off_diag_factor
PressureTensorVTKWriter(ConstBlockDataID const &block_id, std::string const &id, FloatType unit_conversion, FloatType off_diag_factor)
void configure() override
VTKWriter(ConstBlockDataID const &block_id, std::string const &id, FloatType unit_conversion)
FloatType const m_conversion
ConstBlockDataID const m_block_id
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const f) override
Class that runs and controls the LB on waLBerla.
void add_forces_at_pos(std::vector< Utils::Vector3d > const &pos, std::vector< Utils::Vector3d > const &forces) override
typename FieldTrait< FloatType, Architecture >::template RegularCommScheme< typename stencil::D3Q27 > RegularFullCommunicator
Full communicator.
std::vector< double > get_slice_last_applied_force(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
LatticeWalberla::Lattice_T Lattice_T
Lattice model (e.g.
std::shared_ptr< RegularFullCommunicator > m_pdf_communicator
std::vector< std::optional< Utils::Vector3d > > get_slice_velocity_at_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
std::optional< Utils::Vector3d > get_node_last_applied_force(Utils::Vector3i const &node, bool consider_ghosts=false) const override
stencil::D3Q19 Stencil
Stencil for collision and streaming operations.
std::optional< Utils::Vector3d > get_node_velocity_at_boundary(Utils::Vector3i const &node, bool consider_ghosts=false) const override
void ghost_communication() override
std::optional< Utils::Vector3d > get_node_velocity(Utils::Vector3i const &node, bool consider_ghosts=false) const override
void reallocate_ubb_field() override
std::shared_ptr< RegularFullCommunicator > m_full_communicator
BlockDataID m_pdf_tmp_field_id
typename detail::KernelTrait< FloatType, Architecture >::CollisionModelLeesEdwards CollisionModelLeesEdwards
std::size_t get_force_field_id() const noexcept override
BlockDataID m_pdf_field_id
std::shared_ptr< CollisionModel > m_collision_model
typename FieldTrait< FloatType, Architecture >::VectorField VectorField
void set_slice_velocity(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< double > const &velocity) override
unsigned int get_seed() const noexcept override
void integrate_vtk_writers() override
bool remove_node_from_boundary(Utils::Vector3i const &node) override
std::optional< Utils::Vector3d > get_node_boundary_force(Utils::Vector3i const &node) const override
std::optional< double > get_density_at_pos(Utils::Vector3d const &pos, bool consider_points_in_halo=false) const override
void set_slice_velocity_at_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< std::optional< Utils::Vector3d > > const &velocity) override
std::vector< double > get_slice_population(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
void set_rng_state(uint64_t counter) override
std::vector< double > get_slice_velocity(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
std::shared_ptr< LatticeWalberla > m_lattice
std::shared_ptr< LeesEdwardsPack > m_lees_edwards_callbacks
LBWalberlaImpl(std::shared_ptr< LatticeWalberla > lattice, double viscosity, double density)
bool set_node_last_applied_force(Utils::Vector3i const &node, Utils::Vector3d const &force) override
std::shared_ptr< InterpolateAndShiftAtBoundary< _VectorField, FloatType > > m_lees_edwards_vel_interpol_sweep
std::vector< bool > get_slice_is_boundary(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
std::vector< double > get_slice_density(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
void update_boundary_from_shape(std::vector< int > const &raster_flat, std::vector< double > const &data_flat) override
std::shared_ptr< BoundaryModel > m_boundary
std::vector< double > get_slice_pressure_tensor(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const override
bool set_node_density(Utils::Vector3i const &node, double density) override
void set_collision_model(double kT, unsigned int seed) override
std::variant< CollisionModelThermalized, CollisionModelLeesEdwards > CollisionModel
std::vector< Utils::Vector3d > get_velocities_at_pos(std::vector< Utils::Vector3d > const &pos) override
std::optional< bool > get_node_is_boundary(Utils::Vector3i const &node, bool consider_ghosts=false) const override
BlockDataID m_velocity_field_id
std::shared_ptr< ResetForce< PdfField, VectorField > > m_reset_force
void setup_streaming_communicator()
virtual bool is_double_precision() const noexcept override
BlockDataID m_flag_field_id
std::shared_ptr< StreamSweep > m_stream
FlagUID const Boundary_flag
Flag for boundary cells.
~LBWalberlaImpl() override=default
std::optional< uint64_t > get_rng_state() const override
std::optional< std::vector< double > > get_node_population(Utils::Vector3i const &node, bool consider_ghosts=false) const override
FloatType m_density
kinematic viscosity
double get_viscosity() const noexcept override
double get_kT() const noexcept override
Utils::Vector3d get_momentum() const override
void set_viscosity(double viscosity) override
std::shared_ptr< BoundaryFullCommunicator > m_boundary_communicator
std::size_t stencil_size() const noexcept override
auto add_to_storage(std::string const tag)
Convenience function to add a field with a custom allocator.
typename detail::KernelTrait< FloatType, Architecture >::InitialPDFsSetter InitialPDFsSetter
bool set_node_velocity_at_boundary(Utils::Vector3i const &node, Utils::Vector3d const &velocity) override
stencil::D3Q27 StencilFull
Stencil for ghost communication (includes domain corners).
void register_vtk_field_writers(walberla::vtk::VTKOutput &vtk_obj, LatticeModel::units_map const &units, int flag_observables) override
typename BoundaryModel::FlagField FlagField
std::optional< double > get_node_density(Utils::Vector3i const &node, bool consider_ghosts=false) const override
void check_lebc(unsigned int shear_direction, unsigned int shear_plane_normal) const override
void set_slice_density(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< double > const &density) override
void ghost_communication_laf()
void ghost_communication_vel() override
typename FieldTrait< FloatType >::PdfField _PdfField
Utils::Vector3d get_external_force() const noexcept override
BlockDataID m_force_to_be_applied_id
FloatType FloatType_c(T t) const
std::shared_ptr< RegularFullCommunicator > m_laf_communicator
std::size_t get_velocity_field_id() const noexcept override
Utils::VectorXd< 9 > get_pressure_tensor() const override
std::shared_ptr< InterpolateAndShiftAtBoundary< _PdfField, FloatType > > m_lees_edwards_pdf_interpol_sweep
BlockDataID m_vec_tmp_field_id
void set_external_force(Utils::Vector3d const &ext_force) override
std::optional< Utils::Vector3d > get_velocity_at_pos(Utils::Vector3d const &pos, bool consider_points_in_halo=false) const override
void set_slice_last_applied_force(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< double > const &force) override
void set_collision_model(std::unique_ptr< LeesEdwardsPack > &&lees_edwards_pack) override
std::shared_ptr< RegularFullCommunicator > m_vel_communicator
typename FieldTrait< FloatType, Architecture >::template BoundaryCommScheme< typename stencil::D3Q27 > BoundaryFullCommunicator
std::bitset< GhostComm::SIZE > m_pending_ghost_comm
typename FieldTrait< FloatType, Architecture >::template RegularCommScheme< Stencil > PDFStreamingCommunicator
Regular communicator.
LatticeWalberla const & get_lattice() const noexcept override
void set_slice_population(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, std::vector< double > const &population) override
typename FieldTrait< FloatType, Architecture >::template PackInfo< Field > PackInfo
double get_density() const noexcept override
typename detail::KernelTrait< FloatType, Architecture >::CollisionModelThermalized CollisionModelThermalized
typename FieldTrait< FloatType, Architecture >::PdfField PdfField
void ghost_communication_pdf() override
void register_vtk_field_filters(walberla::vtk::VTKOutput &vtk_obj) override
std::optional< Utils::Vector3d > get_node_force_to_be_applied(Utils::Vector3i const &node) const override
typename FieldTrait< FloatType >::VectorField _VectorField
bool set_node_velocity(Utils::Vector3i const &node, Utils::Vector3d const &v) override
void clear_boundaries() override
std::optional< CellInterval > get_interval(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner) const
bool set_node_population(Utils::Vector3i const &node, std::vector< double > const &population) override
bool is_gpu() const noexcept override
void ghost_communication_push_scheme()
std::shared_ptr< PDFStreamingCommunicator > m_pdf_streaming_communicator
BlockDataID m_last_applied_force_field_id
void integrate() override
std::optional< Utils::VectorXd< 9 > > get_node_pressure_tensor(Utils::Vector3i const &node) const override
std::shared_ptr< InterpolateAndShiftAtBoundary< _VectorField, FloatType > > m_lees_edwards_last_applied_force_interpol_sweep
typename detail::KernelTrait< FloatType, Architecture >::StreamSweep StreamSweep
void ghost_communication_boundary()
void ghost_communication_pdfs()
bool add_force_at_pos(Utils::Vector3d const &pos, Utils::Vector3d const &force) override
void setup_boundary_handle(std::shared_ptr< LatticeWalberla > lattice, std::shared_ptr< Boundary_T > boundary)
static double weight(int type, double r_cut, double k, double r)
static double * block(double *p, std::size_t index, std::size_t size)
T product(Vector< T, N > const &v)
void set(GhostLayerField< double, uint_t{19u}> *pdf_field, double const rho_in, Cell const &cell)
double get(GhostLayerField< double, uint_t{19u}> const *pdf_field, Cell const &cell)
void set(GhostLayerField< double, uint_t{19u}> const *pdf_field, GhostLayerField< double, uint_t{3u}> *velocity_field, GhostLayerField< double, uint_t{3u}> *force_field, Vector3< double > const &force, Cell const &cell)
std::vector< double > get(gpu::GPUField< double > const *vec_field, std::vector< double > const &pos, uint gl)
void set(gpu::GPUField< double > const *vec_field, std::vector< double > const &pos, std::vector< double > const &forces, uint gl)
auto reduce(GhostLayerField< double, uint_t{19u}> const *pdf_field, GhostLayerField< double, uint_t{3u}> const *force_field)
void set(GhostLayerField< double, uint_t{19u}> *pdf_field, std::array< double, 19u > const &pop, Cell const &cell)
auto get(GhostLayerField< double, uint_t{19u}> const *pdf_field, Cell const &cell)
void initialize(GhostLayerField< double, uint_t{19u}> *pdf_field, std::array< double, 19u > const &pop)
auto get(GhostLayerField< double, uint_t{19u}> const *pdf_field, Cell const &cell)
void initialize(GhostLayerField< double, uint_t{3u}> *vec_field, Vector3< double > const &vec)
void add(GhostLayerField< double, uint_t{3u}> *vec_field, Vector3< double > const &vec, Cell const &cell)
auto get(GhostLayerField< double, uint_t{3u}> const *vec_field, Cell const &cell)
void set(GhostLayerField< double, uint_t{19u}> *pdf_field, GhostLayerField< double, uint_t{3u}> *velocity_field, GhostLayerField< double, uint_t{3u}> const *force_field, Vector3< double > const &u, Cell const &cell)
\file PackInfoPdfDoublePrecision.cpp \author pystencils
std::optional< BlockAndCell > get_block_and_cell(::LatticeWalberla const &lattice, Utils::Vector3i const &node, bool consider_ghost_layers)
void interpolate_bspline_at_pos(Utils::Vector3d const &pos, Function const &f)
Utils::VectorXd< 9 > to_vector9d(Matrix3< double > const &m)
void set_boundary_from_grid(BoundaryModel &boundary, LatticeWalberla const &lattice, std::vector< int > const &raster_flat, std::vector< DataType > const &data_flat)
std::vector< Utils::Vector3d > fill_3D_vector_array(std::vector< double > const &vec_flat, Utils::Vector3i const &grid_size)
Utils::Vector3d to_vector3d(Vector3< float > const &v)
static Utils::Vector3d velocity(Particle const &p_ref, Particle const &p_vs)
Velocity of the virtual site.
DEVICE_QUALIFIER constexpr iterator begin() noexcept
DEVICE_QUALIFIER constexpr size_type size() const noexcept
DEVICE_QUALIFIER constexpr iterator end() noexcept
typename detail::KernelTrait< FT, AT >::PackInfoVec PackInfoStreamingVec
typename detail::KernelTrait< FT, AT >::PackInfoPdf PackInfoStreamingPdf
field::GhostLayerField< FT, uint_t{3u}> VectorField
field::communication::PackInfo< Field > PackInfo
field::GhostLayerField< FT, Stencil::Size > PdfField
blockforest::communication::UniformBufferedScheme< Stencil > RegularCommScheme
blockforest::communication::UniformBufferedScheme< Stencil > BoundaryCommScheme
GhostCommFlags
Ghost communication operations.
@ VEL
velocities communication
@ LAF
last applied forces communication
@ UBB
boundaries communication