ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
LBVTK.impl.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2019-2026 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22/**
23 * @file
24 * Out-of-class VTK writer registration definition for
25 * @ref walberla::LBWalberlaImpl.
26 */
27
28#include <field/iterators/IteratorMacros.h>
29
30#include <memory>
31#include <optional>
32#include <string>
33
34namespace walberla {
35
36/**
37 * @brief Base class for LB field VTK writers.
38 * Provides unit conversion and field access for cell-based VTK output.
39 * All field is copied to a Vector container before writing.
40 * @tparam FloatType Internal LB precision (float or double).
41 * @tparam VecType Vector type to copy the field data into.
42 * @tparam F_SIZE_ARG Number of components per cell (1, 3, or 9).
43 * @tparam OutputType VTK output precision (default: float).
44 */
45template <typename FloatType, typename VecType, uint_t F_SIZE_ARG,
46 typename OutputType>
47class VTKWriter : public vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG> {
48public:
49 VTKWriter(ConstBlockDataID const &block_id, std::string const &id,
50 FloatType unit_conversion)
51 : vtk::BlockCellDataWriter<OutputType, F_SIZE_ARG>(id),
52 m_conversion(unit_conversion), m_content{} {}
53
54protected:
55 void configure() override { WALBERLA_ASSERT_NOT_NULLPTR(this->block_); }
56
57 std::size_t get_first_index(cell_idx_t const x, cell_idx_t const y,
58 cell_idx_t const z) {
59 return (static_cast<std::size_t>(x) * m_dims[2] * m_dims[1] +
60 static_cast<std::size_t>(y) * m_dims[2] +
61 static_cast<std::size_t>(z)) *
62 F_SIZE_ARG;
63 }
64
65 FloatType m_conversion;
66 VecType m_content;
67 Vector3<uint_t> m_dims;
68
69public:
70 void set_content(VecType content) { m_content = std::move(content); }
71
72 void set_dims(Vector3<uint_t> dims) { m_dims = dims; }
73};
74
75template <typename FloatType, typename OutputType = float>
77 : public VTKWriter<FloatType, std::vector<FloatType>, 1u, OutputType> {
78public:
80 using Base::Base;
81 using Base::evaluate;
82
83protected:
84 OutputType evaluate(cell_idx_t const x, cell_idx_t const y,
85 cell_idx_t const z, cell_idx_t const) override {
86 WALBERLA_ASSERT(!this->m_content.empty());
87 auto const density = this->m_content[this->get_first_index(x, y, z)];
88 return numeric_cast<OutputType>(this->m_conversion * density);
89 }
90};
91
92template <typename FloatType, typename OutputType = float>
94 : public VTKWriter<FloatType, std::vector<FloatType>, 3u, OutputType> {
95public:
97 using Base::Base;
98 using Base::evaluate;
99
100protected:
101 OutputType evaluate(cell_idx_t const x, cell_idx_t const y,
102 cell_idx_t const z, cell_idx_t const f) override {
103 WALBERLA_ASSERT(!this->m_content.empty());
104 auto velocity = this->m_content[this->get_first_index(x, y, z) + f];
105 return numeric_cast<OutputType>(this->m_conversion * velocity);
106 }
107};
108
109template <typename FloatType, typename OutputType = float>
111 : public VTKWriter<FloatType, std::vector<FloatType>, 9u, OutputType> {
112public:
114 using Base::Base;
115 using Base::evaluate;
116
117protected:
118 OutputType evaluate(cell_idx_t const x, cell_idx_t const y,
119 cell_idx_t const z, cell_idx_t const f) override {
120 WALBERLA_ASSERT(!this->m_content.empty());
121 auto pressure = this->m_content[this->get_first_index(x, y, z) + f];
122 return numeric_cast<OutputType>(this->m_conversion * pressure);
123 }
124};
125
126template <typename FlagField_T, typename OutputType = float>
127class BoundaryVTKWriter : public vtk::BlockCellDataWriter<OutputType, 1u> {
128public:
129 using Base = vtk::BlockCellDataWriter<OutputType, 1u>;
130 using Base::evaluate;
131 BoundaryVTKWriter(ConstBlockDataID const &flag_field_id,
132 std::string const &id, FlagUID const &boundary_flag)
133 : vtk::BlockCellDataWriter<OutputType, 1u>(id),
134 m_flag_field_id(flag_field_id), m_flag_field(nullptr),
135 m_boundary_flag(boundary_flag) {}
136
137protected:
138 void configure() override {
139 WALBERLA_ASSERT_NOT_NULLPTR(this->block_);
140 m_flag_field = this->block_->template getData<FlagField_T>(m_flag_field_id);
142 }
143
144 OutputType evaluate(cell_idx_t const x, cell_idx_t const y,
145 cell_idx_t const z, cell_idx_t const) override {
146 WALBERLA_ASSERT_NOT_NULLPTR(m_flag_field);
147 return m_flag_field->isFlagSet(x, y, z, m_boundary_flag_value)
148 ? OutputType{1}
149 : OutputType{0};
150 }
151
152 ConstBlockDataID const m_flag_field_id;
153 FlagField_T const *m_flag_field;
154 FlagUID const m_boundary_flag;
155 typename FlagField_T::flag_t m_boundary_flag_value;
156};
157
158template <typename FloatType, lbmpy::Arch Architecture>
160 walberla::vtk::VTKOutput &vtk_obj, LatticeModel::units_map const &units,
161 int flag_observables) {
162 if (flag_observables & static_cast<int>(OutputVTK::density)) {
163 auto const unit_conversion = FloatType_c(units.at("density"));
164 auto const blocks = m_lattice->get_blocks();
165 WALBERLA_ASSERT_NOT_NULLPTR(blocks);
166 auto density_writer = std::make_shared<DensityVTKWriter<FloatType, float>>(
167 m_pdf_field_id, "density", unit_conversion);
168 auto before_function = [this, blocks, density_writer]() {
169 for (auto &block : *blocks) {
170 auto *pdf_field = block.template getData<PdfField>(m_pdf_field_id);
171 auto const bci = pdf_field->xyzSize();
172 density_writer->set_content(
173 lbm::accessor::Density::get(pdf_field, m_density, bci));
174 density_writer->set_dims(
175 Vector3<uint_t>(bci.xSize(), bci.ySize(), bci.zSize()));
176 }
177 };
178 vtk_obj.addBeforeFunction(std::move(before_function));
179 vtk_obj.addCellDataWriter(density_writer);
180 }
181 if (flag_observables & static_cast<int>(OutputVTK::velocity_vector)) {
182 auto const unit_conversion = FloatType_c(units.at("velocity"));
183 auto const blocks = m_lattice->get_blocks();
184 WALBERLA_ASSERT_NOT_NULLPTR(blocks);
185 auto velocity_writer =
186 std::make_shared<VelocityVTKWriter<FloatType, float>>(
187 m_pdf_field_id, "velocity_vector", unit_conversion);
188 auto before_function = [this, blocks, velocity_writer]() {
189 for (auto &block : *blocks) {
190 auto *velocity_field =
191 block.template getData<VectorField>(m_velocity_field_id);
192
193 auto const offset = m_lattice->get_block_corner(block, true);
194 auto const *flag_field =
195 block.template getData<FlagField>(m_flag_field_id);
196 auto const boundary_flag = flag_field->getFlag(Boundary_flag);
197 WALBERLA_FOR_ALL_CELLS_XYZ(flag_field, {
198 if (flag_field->isFlagSet(x, y, z, boundary_flag)) {
199 Cell const global(offset[0] + x, offset[1] + y, offset[2] + z);
200 auto const &vel = m_boundary->get_node_value_at_boundary(global);
201 Cell const local(x, y, z);
202 lbm::accessor::Vector::set(velocity_field, vel, local);
203 }
204 }) // WALBERLA_FOR_ALL_CELLS_XYZ
205
206 auto const bci = velocity_field->xyzSize();
207 velocity_writer->set_content(
208 lbm::accessor::Vector::get(velocity_field, bci));
209 velocity_writer->set_dims(
210 Vector3<uint_t>(bci.xSize(), bci.ySize(), bci.zSize()));
211 }
212 };
213
214 vtk_obj.addBeforeFunction(std::move(before_function));
215 vtk_obj.addCellDataWriter(velocity_writer);
216 }
217 if (flag_observables & static_cast<int>(OutputVTK::pressure_tensor)) {
218 auto const unit_conversion = FloatType_c(units.at("pressure"));
219 auto const blocks = m_lattice->get_blocks();
220 WALBERLA_ASSERT_NOT_NULLPTR(blocks);
221 auto pressure_writer =
222 std::make_shared<PressureTensorVTKWriter<FloatType, float>>(
223 m_pdf_field_id, "pressure_tensor", unit_conversion);
224 auto before_function = [this, blocks, pressure_writer]() {
225 for (auto &block : *blocks) {
226 auto *pdf_field = block.template getData<PdfField>(m_pdf_field_id);
227 auto const bci = pdf_field->xyzSize();
228 auto values =
229 lbm::accessor::PressureTensor::get(pdf_field, m_density, bci);
230 for (std::size_t n = 0u; n < values.size(); n += 9u) {
231 pressure_tensor_correction(
232 std::span<FloatType, 9ul>(&values[n], 9ul));
233 }
234 pressure_writer->set_content(std::move(values));
235 pressure_writer->set_dims(
236 Vector3<uint_t>(bci.xSize(), bci.ySize(), bci.zSize()));
237 }
238 };
239 vtk_obj.addBeforeFunction(std::move(before_function));
240 vtk_obj.addCellDataWriter(pressure_writer);
241 }
242 if (flag_observables & static_cast<int>(OutputVTK::boundary)) {
243 vtk_obj.addCellDataWriter(
244 std::make_shared<BoundaryVTKWriter<FlagField, float>>(
245 m_flag_field_id, "boundary", Boundary_flag));
246 }
247}
248
249} // namespace walberla
std::unordered_map< std::string, double > units_map
vtk::BlockCellDataWriter< OutputType, 1u > Base
FlagField_T const * m_flag_field
BoundaryVTKWriter(ConstBlockDataID const &flag_field_id, std::string const &id, FlagUID const &boundary_flag)
FlagField_T::flag_t m_boundary_flag_value
ConstBlockDataID const m_flag_field_id
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) override
void register_vtk_field_writers(walberla::vtk::VTKOutput &vtk_obj, LatticeModel::units_map const &units, int flag_observables) override
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const f) override
Base class for LB field VTK writers.
void configure() override
VTKWriter(ConstBlockDataID const &block_id, std::string const &id, FloatType unit_conversion)
Vector3< uint_t > m_dims
void set_dims(Vector3< uint_t > dims)
std::size_t get_first_index(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z)
void set_content(VecType content)
OutputType evaluate(cell_idx_t const x, cell_idx_t const y, cell_idx_t const z, cell_idx_t const f) override
static double * block(double *p, std::size_t index, std::size_t size)
Definition elc.cpp:175
double get(GhostLayerField< double, uint_t{19u}> const *pdf_field, double const density, Cell const &cell)
auto get(GhostLayerField< double, uint_t{19u}> const *pdf_field, double const density, Cell const &cell)
auto get(GhostLayerField< double, uint_t{3u}> const *vec_field, Cell const &cell)
\file PackInfoPdfDoublePrecision.cpp \author pystencils
static Utils::Vector3d velocity(Particle const &p_ref, Particle const &p_vs)
Velocity of the virtual site.
Definition relative.cpp:65