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/HostFieldAllocator.h>
44#include <gpu/communication/MemcpyPackInfo.h>
45#include <gpu/communication/UniformGPUScheme.h>
48#include "../BoundaryHandling.hpp"
49#include "../BoundaryPackInfo.hpp"
50#include "../utils/boundary.hpp"
51#include "../utils/types_conversion.hpp"
55#if defined(__CUDACC__)
75#include <initializer_list>
90template <
typename FloatType, lbmpy::Arch Architecture>
94 typename detail::KernelTrait<FloatType,
97 typename detail::KernelTrait<FloatType,
105 typename detail::BoundaryHandlingTrait<
106 FloatType, Architecture>::DynamicUBB>;
108 std::variant<CollisionModelThermalized, CollisionModelLeesEdwards>;
119 template <
typename FT, lbmpy::Arch AT = lbmpy::Arch::CPU>
struct FieldTrait {
120 using PdfField = field::GhostLayerField<FT, Stencil::Size>;
122 template <
class Field>
123 using PackInfo = field::communication::PackInfo<Field>;
128 template <
class Stencil>
130 blockforest::communication::UniformBufferedScheme<Stencil>;
131 template <
class Stencil>
133 blockforest::communication::UniformBufferedScheme<Stencil>;
136#if defined(__CUDACC__)
140 template <
class Field>
141 using MemcpyPackInfo = gpu::communication::MemcpyPackInfo<Field>;
144 template <
typename Stencil>
145 class UniformGPUScheme
146 :
public gpu::communication::UniformGPUScheme<Stencil> {
148 explicit UniformGPUScheme(
auto const &bf)
149 : gpu::communication::UniformGPUScheme<Stencil>(
155 template <
class Field>
using PackInfo = MemcpyPackInfo<Field>;
160 template <
class Stencil>
162 template <
class Stencil>
164 blockforest::communication::UniformBufferedScheme<Stencil>;
176#if defined(__CUDACC__)
177 using GPUField = gpu::GPUField<FloatType>;
180 using VectorFieldCpu =
197 return numeric_cast<FloatType>(t);
201 return static_cast<std::size_t
>(Stencil::Size);
205 return std::is_same_v<FloatType, double>;
209 class CollideSweepVisitor {
214 cm.configure(m_storage, b);
219 cm.setV_s(
static_cast<decltype(cm.getV_s())
>(
220 m_lees_edwards_callbacks->get_shear_velocity()));
224 CollideSweepVisitor() =
default;
225 CollideSweepVisitor(std::shared_ptr<StructuredBlockStorage> storage) {
226 m_storage = std::move(storage);
228 CollideSweepVisitor(std::shared_ptr<StructuredBlockStorage> storage,
229 std::shared_ptr<LeesEdwardsPack> callbacks) {
230 m_storage = std::move(storage);
231 m_lees_edwards_callbacks = std::move(callbacks);
235 std::shared_ptr<StructuredBlockStorage> m_storage{};
236 std::shared_ptr<LeesEdwardsPack> m_lees_edwards_callbacks{};
238 CollideSweepVisitor m_run_collide_sweep{};
240 FloatType shear_mode_relaxation_rate()
const {
241 return FloatType{2} / (FloatType{6} *
m_viscosity + FloatType{1});
244 FloatType odd_mode_relaxation_rate(
245 FloatType shear_relaxation,
246 FloatType magic_number = FloatType{3} / FloatType{16})
const {
247 return (FloatType{4} - FloatType{2} * shear_relaxation) /
248 (FloatType{4} * magic_number * shear_relaxation + FloatType{2} -
252 void reset_boundary_handling(std::shared_ptr<BlockStorage>
const &blocks) {
257 FloatType pressure_tensor_correction_factor()
const {
261 void pressure_tensor_correction(Matrix3<FloatType> &tensor)
const {
262 auto const revert_factor = pressure_tensor_correction_factor();
263 for (
auto const i : {1u, 2u, 3u, 5u, 6u, 7u}) {
264 tensor[i] *= revert_factor;
268 void pressure_tensor_correction(std::span<FloatType, 9ul> tensor)
const {
269 auto const revert_factor = pressure_tensor_correction_factor();
270 for (
auto const i : {1u, 2u, 3u, 5u, 6u, 7u}) {
271 tensor[i] *= revert_factor;
275 class interpolation_illegal_access :
public std::runtime_error {
277 explicit interpolation_illegal_access(std::string
const &field,
279 std::array<int, 3>
const &node,
281 : std::runtime_error(
"Access to LB " + field +
" field failed") {
283 <<
"], weight " <<
weight <<
"\n";
290 std::string
const &reason)
291 : std::runtime_error(
"VTKOutput object '" + vtk_uid +
"' " + reason) {}
312#if defined(__CUDACC__)
313 std::optional<BlockDataID> m_pdf_cpu_field_id;
314 std::optional<BlockDataID> m_vel_cpu_field_id;
329 typename stencil::D3Q27>;
332 typename stencil::D3Q27>;
339 Architecture>::template RegularCommScheme<Stencil>;
340 template <
class Field>
361 std::shared_ptr<InterpolateAndShiftAtBoundary<_PdfField, FloatType>>
363 std::shared_ptr<InterpolateAndShiftAtBoundary<_VectorField, FloatType>>
365 std::shared_ptr<InterpolateAndShiftAtBoundary<_VectorField, FloatType>>
377#if defined(__CUDACC__)
378 std::shared_ptr<gpu::HostFieldAllocator<FloatType>> m_host_field_allocator;
381 [[nodiscard]] std::optional<CellInterval>
385 auto const &cell_min = lower_corner;
389 if (not lower_bc or not upper_bc) {
393 auto const block_extent =
395 auto const global_lower_cell = lower_bc->cell;
396 auto const global_upper_cell = upper_bc->cell +
to_cell(block_extent);
397 return {CellInterval(global_lower_cell, global_upper_cell)};
404 auto block_lower_corner =
m_lattice->get_block_corner(
block,
true);
405 if (not(upper_corner > block_lower_corner)) {
408 for (uint_t f = 0u; f < 3u; ++f) {
409 block_lower_corner[f] = std::max(block_lower_corner[f], lower_corner[f]);
411 auto block_upper_corner =
m_lattice->get_block_corner(
block,
false);
412 if (not(block_upper_corner > lower_corner)) {
415 for (uint_t f = 0u; f < 3u; ++f) {
416 block_upper_corner[f] = std::min(block_upper_corner[f], upper_corner[f]);
419 auto const block_lower_cell =
to_cell(block_lower_corner - block_offset);
420 auto const block_upper_cell =
to_cell(block_upper_corner - block_offset);
421 return {CellInterval(block_lower_cell, block_upper_cell)};
436 auto const &blocks =
m_lattice->get_blocks();
437 auto const n_ghost_layers =
m_lattice->get_ghost_layers();
439#ifdef ESPRESSO_BUILD_WITH_AVX_KERNELS
440#if defined(__AVX512F__)
441 constexpr uint_t alignment = 64u;
442#elif defined(__AVX__)
443 constexpr uint_t alignment = 32u;
444#elif defined(__SSE__)
445 constexpr uint_t alignment = 16u;
447#error "Unsupported arch, check walberla src/field/allocation/FieldAllocator.h"
449 using value_type =
typename Field::value_type;
450 using Allocator = field::AllocateAligned<value_type, alignment>;
451 auto const allocator = std::make_shared<Allocator>();
452 auto const empty_set = Set<SUID>::emptySet();
453 return field::addToStorage<Field>(
454 blocks, tag, field::internal::defaultSize, FloatType{0}, field::fzyx,
455 n_ghost_layers,
false, {}, empty_set, empty_set, allocator);
457 return field::addToStorage<Field>(blocks, tag, FloatType{0}, field::fzyx,
461#if defined(__CUDACC__)
463 auto field_id = gpu::addGPUFieldToStorage<GPUField>(
464 blocks, tag, Field::F_SIZE, field::fzyx, n_ghost_layers);
465 if constexpr (std::is_same_v<Field, _VectorField>) {
467 auto field =
block->template getData<GPUField>(field_id);
470 }
else if constexpr (std::is_same_v<Field, _PdfField>) {
472 auto field =
block->template getData<GPUField>(field_id);
474 field, std::array<FloatType, Stencil::Size>{});
483 auto const setup = [
this]<
typename PackInfoPdf,
typename PackInfoVec>() {
484 auto const &blocks =
m_lattice->get_blocks();
486 std::make_shared<PDFStreamingCommunicator>(blocks);
498 setup.template operator()<PackInfoPdf, PackInfoVec>();
508 auto const &blocks =
m_lattice->get_blocks();
509 auto const n_ghost_layers =
m_lattice->get_ghost_layers();
510 if (n_ghost_layers == 0u)
511 throw std::runtime_error(
"At least one ghost layer must be used");
520#if defined(__CUDACC__)
521 m_host_field_allocator =
522 std::make_shared<gpu::HostFieldAllocator<FloatType>>();
529 for (
auto b = blocks->begin(); b != blocks->end(); ++b) {
535 blocks,
"flag field", n_ghost_layers);
537 reset_boundary_handling(
m_lattice->get_blocks());
561 std::make_shared<BoundaryFullCommunicator>(blocks);
563 std::make_shared<field::communication::PackInfo<FlagField>>(
565 auto boundary_packinfo = std::make_shared<
575 m_reset_force = std::make_shared<ResetForce<PdfField, VectorField>>(
582 m_stream = std::make_shared<StreamSweep>(
587 void integrate_stream(std::shared_ptr<BlockStorage>
const &blocks) {
588 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
592 void integrate_collide(std::shared_ptr<BlockStorage>
const &blocks) {
594 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
595 std::visit(m_run_collide_sweep, cm_variant, std::variant<IBlock *>(&*b));
596 if (
auto *cm = std::get_if<CollisionModelThermalized>(&cm_variant)) {
597 cm->setTime_step(cm->getTime_step() + 1u);
601 auto has_lees_edwards_bc()
const {
602 return std::holds_alternative<CollisionModelLeesEdwards>(
606 void apply_lees_edwards_pdf_interpolation(
607 std::shared_ptr<BlockStorage>
const &blocks) {
608 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
612 void apply_lees_edwards_vel_interpolation_and_shift(
613 std::shared_ptr<BlockStorage>
const &blocks) {
614 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
618 void apply_lees_edwards_last_applied_force_interpolation(
619 std::shared_ptr<BlockStorage>
const &blocks) {
620 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
624 void integrate_reset_force(std::shared_ptr<BlockStorage>
const &blocks) {
625 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
629 void integrate_boundaries(std::shared_ptr<BlockStorage>
const &blocks) {
630 for (
auto b = blocks->begin(); b != blocks->end(); ++b)
634 void integrate_push_scheme() {
637 integrate_reset_force(blocks);
639 integrate_collide(blocks);
643 integrate_boundaries(blocks);
646 integrate_stream(blocks);
655 void integrate_pull_scheme() {
659 integrate_boundaries(blocks);
662 integrate_stream(blocks);
664 integrate_collide(blocks);
666 integrate_reset_force(blocks);
678 auto &vtk_handle = it.second;
679 if (vtk_handle->enabled) {
680 vtk::writeFiles(vtk_handle->ptr)();
681 vtk_handle->execution_count++;
688 if (has_lees_edwards_bc()) {
689 integrate_pull_scheme();
691 integrate_push_scheme();
707 if (has_lees_edwards_bc()) {
709 apply_lees_edwards_pdf_interpolation(blocks);
718 if (has_lees_edwards_bc()) {
720 apply_lees_edwards_vel_interpolation_and_shift(blocks);
729 if (has_lees_edwards_bc()) {
731 apply_lees_edwards_last_applied_force_interpolation(blocks);
746 if (has_lees_edwards_bc()) {
748 apply_lees_edwards_pdf_interpolation(blocks);
749 apply_lees_edwards_vel_interpolation_and_shift(blocks);
750 apply_lees_edwards_last_applied_force_interpolation(blocks);
758 if (has_lees_edwards_bc()) {
761 apply_lees_edwards_pdf_interpolation(blocks);
762 apply_lees_edwards_vel_interpolation_and_shift(blocks);
763 apply_lees_edwards_last_applied_force_interpolation(blocks);
771 auto const omega = shear_mode_relaxation_rate();
772 auto const omega_odd = odd_mode_relaxation_rate(omega);
778 omega_odd, omega, seed, uint32_t{0u});
780 m_run_collide_sweep = CollideSweepVisitor(blocks);
785 std::unique_ptr<LeesEdwardsPack> &&lees_edwards_pack)
override {
787#if defined(__CUDACC__)
789 throw std::runtime_error(
"Lees-Edwards LB doesn't support GPU yet");
792 auto const shear_direction = lees_edwards_pack->shear_direction;
793 auto const shear_plane_normal = lees_edwards_pack->shear_plane_normal;
794 auto const shear_vel =
FloatType_c(lees_edwards_pack->get_shear_velocity());
795 auto const omega = shear_mode_relaxation_rate();
796 if (shear_plane_normal != 1u) {
797 throw std::domain_error(
798 "Lees-Edwards LB only supports shear_plane_normal=\"y\"");
801 auto const n_ghost_layers = lattice.get_ghost_layers();
802 auto const blocks = lattice.get_blocks();
803 if (lattice.get_node_grid()[shear_direction] != 1 or
804 lattice.get_node_grid()[shear_plane_normal] != 1 or
805 blocks->getSize(shear_direction) != 1ul or
806 blocks->getSize(shear_plane_normal) != 1ul) {
807 throw std::domain_error(
"LB LEbc doesn't support domain decomposition "
808 "along the shear and normal directions.");
811 FloatType_c(lattice.get_grid_dimensions()[shear_plane_normal]);
818 std::make_shared<InterpolateAndShiftAtBoundary<_PdfField, FloatType>>(
820 shear_direction, shear_plane_normal,
825 shear_direction, shear_plane_normal,
831 n_ghost_layers, shear_direction, shear_plane_normal,
837 unsigned int shear_plane_normal)
const override {
841 throw std::runtime_error(
842 "MD and LB Lees-Edwards boundary conditions disagree");
860 std::optional<Utils::Vector3d>
862 bool consider_ghosts =
false)
const override {
867 if (is_boundary and *is_boundary) {
875 auto field = bc->block->template uncheckedFastGetData<VectorField>(
890 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
895 auto const vel = to_vector3<FloatType>(v);
916 template <
typename Kernel>
920 Kernel &&kernel)
const {
921 auto const local_grid =
to_vector3i(ci.max() - ci.min() +
Cell(1, 1, 1));
922 auto const block_grid =
to_vector3i(bci.max() - bci.min() +
Cell(1, 1, 1));
923 auto const lower_cell = bci.min();
924 auto const upper_cell = bci.max();
929 for (
auto x = lower_cell.x(), i = 0; x <= upper_cell.x(); ++x, ++i) {
930 for (
auto y = lower_cell.y(), j = 0; y <= upper_cell.y(); ++y, ++j) {
931 for (
auto z = lower_cell.z(), k = 0; z <= upper_cell.z(); ++z, ++k) {
937 kernel(
static_cast<unsigned>(block_index),
938 static_cast<unsigned>(local_index), node);
947 std::vector<double> out;
948 uint_t values_size = 0;
949 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
950 out = std::vector<double>(3u * ci->numCells());
952 for (
auto &
block : *lattice.get_blocks()) {
953 auto const block_offset = lattice.get_block_corner(
block,
true);
955 block_offset,
block)) {
959 assert(values.size() == 3u * bci->numCells());
960 values_size += 3u * bci->numCells();
962 auto kernel = [&values, &out,
this](
unsigned const block_index,
963 unsigned const local_index,
966 auto const &vec =
m_boundary->get_node_value_at_boundary(node);
967 for (uint_t f = 0u; f < 3u; ++f) {
968 out[3u * local_index + f] = double_c(vec[f]);
971 for (uint_t f = 0u; f < 3u; ++f) {
972 out[3u * local_index + f] =
973 double_c(values[3u * block_index + f]);
981 assert(values_size == 3u * ci->numCells());
988 std::vector<double>
const &
velocity)
override {
991 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
994 for (
auto &
block : *lattice.get_blocks()) {
995 auto const block_offset = lattice.get_block_corner(
block,
true);
997 block_offset,
block)) {
999 auto force_field =
block.template getData<VectorField>(
1003 std::vector<FloatType> values(3u * bci->numCells());
1005 auto kernel = [&values, &
velocity](
unsigned const block_index,
1006 unsigned const local_index,
1008 for (uint_t f = 0u; f < 3u; ++f) {
1009 values[3u * block_index + f] =
1010 numeric_cast<FloatType>(
velocity[3u * local_index + f]);
1022 [[nodiscard]]
bool is_gpu() const noexcept
override {
1027 std::vector<Utils::Vector3d>
const &forces)
override {
1028 assert(pos.size() == forces.size());
1033 for (std::size_t i = 0ul; i < pos.size(); ++i) {
1037#if defined(__CUDACC__)
1040 auto const &
block = *(lattice.get_blocks()->begin());
1041 auto const origin =
block.getAABB().min();
1042 std::vector<FloatType> host_pos;
1043 std::vector<FloatType> host_force;
1044 host_pos.reserve(3ul * pos.size());
1045 host_force.reserve(3ul * forces.size());
1046 assert(lattice.get_blocks()->getNumberOfBlocks() == 1u);
1047 for (
auto const &vec : pos) {
1049 for (std::size_t i : {0ul, 1ul, 2ul}) {
1050 host_pos.emplace_back(
static_cast<FloatType
>(vec[i] - origin[i]));
1053 for (
auto const &vec : forces) {
1055 for (std::size_t i : {0ul, 1ul, 2ul}) {
1056 host_force.emplace_back(
static_cast<FloatType
>(vec[i]));
1059 auto const gl = lattice.get_ghost_layers();
1060 auto field =
block.template uncheckedFastGetData<VectorField>(
1067 std::vector<Utils::Vector3d>
1072 std::vector<Utils::Vector3d> vel{};
1074 vel.reserve(pos.size());
1075 for (
auto const &vec : pos) {
1077 assert(res.has_value());
1078 vel.emplace_back(*res);
1081#if defined(__CUDACC__)
1084 auto const &
block = *(lattice.get_blocks()->begin());
1085 auto const origin =
block.getAABB().min();
1086 std::vector<FloatType> host_pos;
1087 host_pos.reserve(3ul * pos.size());
1088 assert(lattice.get_blocks()->getNumberOfBlocks() == 1u);
1089 for (
auto const &vec : pos) {
1091 for (std::size_t i : {0ul, 1ul, 2ul}) {
1092 host_pos.emplace_back(
static_cast<FloatType
>(vec[i] - origin[i]));
1095 auto const gl = lattice.get_ghost_layers();
1099 vel.reserve(res.size() / 3ul);
1100 for (
auto it = res.begin(); it != res.end(); it += 3) {
1102 static_cast<double>(*(it + 1)),
1103 static_cast<double>(*(it + 2))});
1110 std::optional<Utils::Vector3d>
1112 bool consider_points_in_halo =
false)
const override {
1115 if (!consider_points_in_halo and !
m_lattice->pos_in_local_domain(pos))
1116 return std::nullopt;
1117 if (consider_points_in_halo and !
m_lattice->pos_in_local_halo(pos))
1118 return std::nullopt;
1121 pos, [
this, &v, &pos](std::array<int, 3>
const node,
double weight) {
1127 throw interpolation_illegal_access(
"velocity", pos, node,
weight);
1132 return {std::move(v)};
1135 std::optional<double>
1137 bool consider_points_in_halo =
false)
const override {
1139 if (!consider_points_in_halo and !
m_lattice->pos_in_local_domain(pos))
1140 return std::nullopt;
1141 if (consider_points_in_halo and !
m_lattice->pos_in_local_halo(pos))
1142 return std::nullopt;
1145 pos, [
this, &dens, &pos](std::array<int, 3>
const node,
double weight) {
1151 throw interpolation_illegal_access(
"density", pos, node,
weight);
1156 return {std::move(dens)};
1164 auto const force_at_node = [
this, &force](std::array<int, 3>
const node,
1172 auto const weighted_force = to_vector3<FloatType>(
weight * force);
1174 bc->block->template uncheckedFastGetData<VectorField>(
1183 std::optional<Utils::Vector3d>
1187 return std::nullopt;
1195 std::optional<Utils::Vector3d>
1197 bool consider_ghosts =
false)
const override {
1201 return std::nullopt;
1217 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1222 auto const vec = to_vector3<FloatType>(force);
1231 std::vector<double> out;
1232 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1233 out = std::vector<double>(3u * ci->numCells());
1235 for (
auto const &
block : *lattice.get_blocks()) {
1236 auto const block_offset = lattice.get_block_corner(
block,
true);
1238 block_offset,
block)) {
1239 auto const field =
block.template getData<VectorField>(
1242 assert(values.size() == 3u * bci->numCells());
1244 auto kernel = [&values, &out](
unsigned const block_index,
1245 unsigned const local_index,
1247 for (uint_t f = 0u; f < 3u; ++f) {
1248 out[3u * local_index + f] = values[3u * block_index + f];
1261 std::vector<double>
const &force)
override {
1264 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1265 assert(force.size() == 3u * ci->numCells());
1267 for (
auto &
block : *lattice.get_blocks()) {
1268 auto const block_offset = lattice.get_block_corner(
block,
true);
1270 block_offset,
block)) {
1272 auto force_field =
block.template getData<VectorField>(
1276 std::vector<FloatType> values(3u * bci->numCells());
1278 auto kernel = [&values, &force](
unsigned const block_index,
1279 unsigned const local_index,
1281 for (uint_t f = 0u; f < 3u; ++f) {
1282 values[3u * block_index + f] =
1283 numeric_cast<FloatType>(force[3u * local_index + f]);
1296 std::optional<std::vector<double>>
1298 bool consider_ghosts =
false)
const override {
1302 return std::nullopt;
1304 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1306 std::vector<double> population(Stencil::Size);
1307 for (uint_t f = 0u; f < Stencil::Size; ++f) {
1308 population[f] = double_c(pop[f]);
1311 return {std::move(population)};
1315 std::vector<double>
const &population)
override {
1322 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1327 std::array<FloatType, Stencil::Size> pop;
1328 for (uint_t f = 0u; f < Stencil::Size; ++f) {
1340 std::vector<double> out;
1341 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1342 out = std::vector<double>(
stencil_size() * ci->numCells());
1344 for (
auto const &
block : *lattice.get_blocks()) {
1345 auto const block_offset = lattice.get_block_corner(
block,
true);
1347 block_offset,
block)) {
1348 auto const pdf_field =
1351 assert(values.size() ==
stencil_size() * bci->numCells());
1353 auto kernel = [&values, &out,
this](
unsigned const block_index,
1354 unsigned const local_index,
1371 std::vector<double>
const &population)
override {
1372 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1373 assert(population.size() ==
stencil_size() * ci->numCells());
1375 for (
auto &
block : *lattice.get_blocks()) {
1376 auto const block_offset = lattice.get_block_corner(
block,
true);
1378 block_offset,
block)) {
1380 auto force_field =
block.template getData<VectorField>(
1384 std::vector<FloatType> values(
stencil_size() * bci->numCells());
1386 auto kernel = [&values, &population,
1387 this](
unsigned const block_index,
1388 unsigned const local_index,
1392 numeric_cast<FloatType>(
1406 std::optional<double>
1408 bool consider_ghosts =
false)
const override {
1412 return std::nullopt;
1415 bc->block->template uncheckedFastGetData<PdfField>(
m_pdf_field_id);
1426 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1435 std::vector<double> out;
1436 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1437 out = std::vector<double>(ci->numCells());
1439 for (
auto const &
block : *lattice.get_blocks()) {
1440 auto const block_offset = lattice.get_block_corner(
block,
true);
1442 block_offset,
block)) {
1443 auto const pdf_field =
1446 assert(values.size() == bci->numCells());
1448 auto kernel = [&values, &out](
unsigned const block_index,
1449 unsigned const local_index,
1451 out[local_index] = values[block_index];
1463 std::vector<double>
const &
density)
override {
1465 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1466 assert(
density.size() == ci->numCells());
1468 for (
auto &
block : *lattice.get_blocks()) {
1469 auto const block_offset = lattice.get_block_corner(
block,
true);
1471 block_offset,
block)) {
1473 std::vector<FloatType> values(bci->numCells());
1475 auto kernel = [&values, &
density](
unsigned const block_index,
1476 unsigned const local_index,
1478 values[block_index] = numeric_cast<FloatType>(
density[local_index]);
1488 std::optional<Utils::Vector3d>
1490 bool consider_ghosts =
false)
const override {
1493 if (!bc or !
m_boundary->node_is_boundary(node))
1494 return std::nullopt;
1509 node, to_vector3<FloatType>(
velocity), *bc);
1511 return bc.has_value();
1517 std::vector<std::optional<Utils::Vector3d>> out;
1518 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1519 out = std::vector<std::optional<Utils::Vector3d>>(ci->numCells());
1521 for (
auto const &
block : *lattice.get_blocks()) {
1522 auto const block_offset = lattice.get_block_corner(
block,
true);
1524 block_offset,
block)) {
1526 auto kernel = [&out,
this](
unsigned const,
unsigned const local_index,
1532 out[local_index] = std::nullopt;
1539 assert(out.size() == ci->numCells());
1546 std::vector<std::optional<Utils::Vector3d>>
const &
velocity)
override {
1549 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1552 for (
auto &
block : *lattice.get_blocks()) {
1553 auto const block_offset = lattice.get_block_corner(
block,
true);
1555 block_offset,
block)) {
1558 this](
unsigned const,
unsigned const local_index,
1561 assert(bc->block->getAABB() ==
block.getAABB());
1562 auto const &opt =
velocity[local_index];
1565 node, to_vector3<FloatType>(*opt), *bc);
1567 m_boundary->remove_node_from_boundary(node, *bc);
1577 std::optional<Utils::Vector3d>
1580 if (!bc or !
m_boundary->node_is_boundary(node))
1581 return std::nullopt;
1592 m_boundary->remove_node_from_boundary(node, *bc);
1594 return bc.has_value();
1599 bool consider_ghosts =
false)
const override {
1603 return std::nullopt;
1611 std::vector<bool> out;
1612 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1613 out = std::vector<bool>(ci->numCells());
1615 for (
auto const &
block : *lattice.get_blocks()) {
1616 auto const block_offset = lattice.get_block_corner(
block,
true);
1618 block_offset,
block)) {
1620 auto kernel = [&out,
this](
unsigned const,
unsigned const local_index,
1622 out[local_index] =
m_boundary->node_is_boundary(node);
1628 assert(out.size() == ci->numCells());
1644 reset_boundary_handling(
get_lattice().get_blocks());
1653 std::vector<double>
const &data_flat)
override {
1664 std::optional<Utils::VectorXd<9>>
1668 return std::nullopt;
1670 auto pdf_field = bc->block->template getData<PdfField>(
m_pdf_field_id);
1672 pressure_tensor_correction(tensor);
1680 std::vector<double> out;
1681 if (
auto const ci =
get_interval(lower_corner, upper_corner)) {
1682 out = std::vector<double>(9u * ci->numCells());
1684 for (
auto const &
block : *lattice.get_blocks()) {
1685 auto const block_offset = lattice.get_block_corner(
block,
true);
1687 block_offset,
block)) {
1688 auto const pdf_field =
1691 assert(values.size() == 9u * bci->numCells());
1693 auto kernel = [&values, &out,
this](
unsigned const block_index,
1694 unsigned const local_index,
1696 pressure_tensor_correction(
1697 std::span<FloatType, 9ul>(&values[9u * block_index], 9ul));
1698 for (uint_t f = 0u; f < 9u; ++f) {
1699 out[9u * local_index + f] = values[9u * block_index + f];
1712 Matrix3<FloatType> tensor(FloatType{0});
1719 pressure_tensor_correction(tensor);
1720 return to_vector9d(tensor) * (1. /
static_cast<double>(number_of_nodes));
1725 Vector3<FloatType> mom(FloatType{0});
1744 [[nodiscard]]
double get_kT() const noexcept
override {
1745 return numeric_cast<double>(
m_kT);
1748 [[nodiscard]]
unsigned int get_seed() const noexcept
override {
1754 if (!cm or
m_kT == 0.) {
1755 return std::nullopt;
1757 return {
static_cast<uint64_t
>(cm->getTime_step())};
1762 if (!cm or
m_kT == 0.) {
1763 throw std::runtime_error(
"This LB instance is unthermalized");
1766 static_cast<uint32_t
>(std::numeric_limits<uint_t>::max()));
1767 cm->setTime_step(
static_cast<uint32_t
>(counter));
1785 vtk_obj.addCellExclusionFilter(fluid_filter);
1789 template <
typename Field_T, u
int_t F_SIZE_ARG,
typename OutputType>
1790 class VTKWriter :
public vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG> {
1792 VTKWriter(ConstBlockDataID
const &block_id, std::string
const &
id,
1793 FloatType unit_conversion)
1794 : vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG>(id),
1800 WALBERLA_ASSERT_NOT_NULLPTR(this->block_);
1809 template <
typename OutputType =
float>
1814 using Base::evaluate;
1817 OutputType
evaluate(cell_idx_t
const x, cell_idx_t
const y,
1818 cell_idx_t
const z, cell_idx_t
const)
override {
1819 WALBERLA_ASSERT_NOT_NULLPTR(this->
m_field);
1826 template <
typename OutputType =
float>
1831 using Base::evaluate;
1834 OutputType
evaluate(cell_idx_t
const x, cell_idx_t
const y,
1835 cell_idx_t
const z, cell_idx_t
const f)
override {
1836 WALBERLA_ASSERT_NOT_NULLPTR(this->
m_field);
1843 template <
typename OutputType =
float>
1848 using Base::evaluate;
1851 std::string
const &
id, FloatType unit_conversion,
1852 FloatType off_diag_factor)
1853 :
Base(block_id, id, unit_conversion),
1857 OutputType
evaluate(cell_idx_t
const x, cell_idx_t
const y,
1858 cell_idx_t
const z, cell_idx_t
const f)
override {
1859 WALBERLA_ASSERT_NOT_NULLPTR(this->
m_field);
1860 auto const pressure =
1862 auto const revert_factor =
1864 return numeric_cast<OutputType>(this->
m_conversion * revert_factor *
1865 pressure[uint_c(f)]);
1873 int flag_observables)
override {
1874#if defined(__CUDACC__)
1875 auto const allocate_cpu_field_if_empty =
1876 [&]<
typename Field>(
auto const &blocks, std::string name,
1877 std::optional<BlockDataID> &cpu_field) {
1878 if (not cpu_field) {
1879 cpu_field = field::addToStorage<Field>(
1880 blocks, name, FloatType{0}, field::fzyx,
1881 m_lattice->get_ghost_layers(), m_host_field_allocator);
1886 auto const unit_conversion =
FloatType_c(units.at(
"density"));
1887#if defined(__CUDACC__)
1889 auto const &blocks =
m_lattice->get_blocks();
1890 allocate_cpu_field_if_empty.template operator()<PdfFieldCpu>(
1891 blocks,
"pdfs_cpu", m_pdf_cpu_field_id);
1892 vtk_obj.addBeforeFunction(gpu::fieldCpyFunctor<PdfFieldCpu, PdfField>(
1900 auto const unit_conversion =
FloatType_c(units.at(
"velocity"));
1901#if defined(__CUDACC__)
1903 auto const &blocks =
m_lattice->get_blocks();
1904 allocate_cpu_field_if_empty.template operator()<VectorFieldCpu>(
1905 blocks,
"vel_cpu", m_vel_cpu_field_id);
1906 vtk_obj.addBeforeFunction(
1907 gpu::fieldCpyFunctor<VectorFieldCpu, VectorField>(
1915 auto const unit_conversion =
FloatType_c(units.at(
"pressure"));
1916#if defined(__CUDACC__)
1918 auto const &blocks =
m_lattice->get_blocks();
1919 allocate_cpu_field_if_empty.template operator()<PdfFieldCpu>(
1920 blocks,
"pdfs_cpu", m_pdf_cpu_field_id);
1921 vtk_obj.addBeforeFunction(gpu::fieldCpyFunctor<PdfFieldCpu, PdfField>(
1925 vtk_obj.addCellDataWriter(
1928 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.
auto const & get_grid_dimensions() const
walberla::blockforest::StructuredBlockForest Lattice_T
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value) noexcept
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
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
void copy_block_buffer(CellInterval const &bci, CellInterval const &ci, Utils::Vector3i const &block_offset, Utils::Vector3i const &lower_corner, Kernel &&kernel) const
Synchronize data between a sliced block and a container.
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
BlockDataID m_vel_tmp_field_id
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
bool is_double_precision() const noexcept 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
void ghost_communication_laf() 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()
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.
void ghost_communication_full()
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_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::optional< CellInterval > get_block_interval(Utils::Vector3i const &lower_corner, Utils::Vector3i const &upper_corner, Utils::Vector3i const &block_offset, IBlock const &block) const
std::shared_ptr< InterpolateAndShiftAtBoundary< _PdfField, FloatType > > m_lees_edwards_pdf_interpol_sweep
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
LatticeWalberla::Lattice_T BlockStorage
Lattice model (e.g.
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()
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)
int get_linear_index(int a, int b, int c, const Vector3i &adim, MemoryOrder memory_order=MemoryOrder::COLUMN_MAJOR)
get the linear index from the position (a,b,c) in a 3D grid of dimensions adim.
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)
auto reduce(GhostLayerField< double, uint_t{19u}> const *pdf_field)
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)
auto to_vector3d(Vector3< T > const &v) noexcept
void interpolate_bspline_at_pos(Utils::Vector3d const &pos, Function const &f)
void set_boundary_from_grid(BoundaryModel &boundary, LatticeWalberla const &lattice, std::vector< int > const &raster_flat, std::vector< DataType > const &data_flat)
auto get_min_corner(IBlock const &block)
Get the block-local coordinates of the lower corner of a block.
Cell to_cell(Utils::Vector3i const &xyz)
Utils::Vector3i to_vector3i(Vector3< int > const &v) noexcept
auto to_vector9d(Matrix3< T > const &m) noexcept
std::vector< Utils::Vector3d > fill_3D_vector_array(std::vector< double > const &vec_flat, Utils::Vector3i const &grid_size)
static Utils::Vector3d velocity(Particle const &p_ref, Particle const &p_vs)
Velocity of the virtual site.
DEVICE_QUALIFIER constexpr size_type size() const 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