55 FlagUID
const Domain_flag{
"domain"};
57 FlagUID
const Boundary_flag{
"boundary"};
60 class DynamicValueCallback {
62 DynamicValueCallback() {
63 m_value_boundary = std::make_shared<std::unordered_map<Cell, T>>();
66 [[nodiscard]] T operator()(
68 std::shared_ptr<blockforest::StructuredBlockForest>
const &blocks,
69 IBlock &
block)
const {
71 blocks->transformBlockLocalToGlobalCell(global,
block, local);
72 return get_value(global);
75 void set_node_boundary_value(
Utils::Vector3i const &node, T
const &val) {
76 auto const global =
Cell(node[0], node[1], node[2]);
77 (*m_value_boundary)[global] = val;
81 auto const global =
Cell(node[0], node[1], node[2]);
82 assert(m_value_boundary->count(global));
83 m_value_boundary->erase(global);
88 auto const global =
Cell(node[0], node[1], node[2]);
89 return get_value(global);
93 auto const global =
Cell(node[0], node[1], node[2]);
94 return m_value_boundary->count(global) != 0;
98 std::shared_ptr<std::unordered_map<Cell, T>> m_value_boundary;
99 static constexpr T default_value{};
101 [[nodiscard]] T
const &get_value(
Cell const &cell)
const {
102 if (m_value_boundary->count(cell) == 0) {
103 return default_value;
105 return m_value_boundary->at(cell);
109 [[nodiscard]]
inline auto get_flag_field_and_flag(IBlock *
block)
const {
110 auto const flag_field =
111 block->template uncheckedFastGetData<FlagField>(m_flag_field_id);
112 auto const boundary_flag = flag_field->getFlag(Boundary_flag);
113 return std::make_tuple(flag_field, boundary_flag);
121 BlockDataID value_field_id, BlockDataID flag_field_id)
122 : m_blocks(std::move(blocks)), m_flag_field_id(flag_field_id),
123 m_callback(DynamicValueCallback()), m_pending_changes(false) {
125 for (
auto block = m_blocks->begin();
block != m_blocks->end(); ++
block) {
126 flag_reset_kernel(
block->template getData<FlagField>(m_flag_field_id));
129 std::function callback = m_callback;
131 std::make_shared<BoundaryClass>(m_blocks, value_field_id, callback);
137 return m_callback.node_is_boundary(node);
142 return m_callback.get_node_boundary_value(node);
147 auto [flag_field, boundary_flag] = get_flag_field_and_flag(bc.
block);
148 m_callback.set_node_boundary_value(node, v);
149 flag_field->addFlag(bc.
cell, boundary_flag);
150 m_pending_changes =
true;
154 m_callback.set_node_boundary_value(node, v);
159 auto [flag_field, boundary_flag] = get_flag_field_and_flag(bc.
block);
160 m_callback.unset_node_boundary_value(node);
161 flag_field->removeFlag(bc.
cell, boundary_flag);
162 m_pending_changes =
true;
167 if (m_pending_changes) {
168 m_boundary->template fillFromFlagField<FlagField>(
169 m_blocks, m_flag_field_id, Boundary_flag, Domain_flag);
170 m_pending_changes =
false;
175 auto const field =
block.template getData<FlagField>(m_flag_field_id);
176 return {
static_cast<int>(field->xSize()),
static_cast<int>(field->ySize()),
177 static_cast<int>(field->zSize())};
181 std::shared_ptr<StructuredBlockForest> m_blocks;
182 BlockDataID m_flag_field_id;
183 DynamicValueCallback m_callback;
184 std::shared_ptr<BoundaryClass> m_boundary;
185 bool m_pending_changes;
188 void flag_reset_kernel(
FlagField *flag_field) {
190 if (!flag_field->flagExists(Domain_flag))
191 flag_field->registerFlag(Domain_flag);
192 if (!flag_field->flagExists(Boundary_flag))
193 flag_field->registerFlag(Boundary_flag);
195 auto domain_flag = flag_field->getFlag(Domain_flag);
196 auto boundary_flag = flag_field->getFlag(Boundary_flag);
197 for (
auto it = flag_field->begin(); it != flag_field->end(); ++it) {
198 flag_field->addFlag(it.x(), it.y(), it.z(), domain_flag);
199 flag_field->removeFlag(it.x(), it.y(), it.z(), boundary_flag);