62 FlagUID
const Domain_flag{
"domain"};
64 FlagUID
const Boundary_flag{
"boundary"};
67 class DynamicValueCallback {
69 DynamicValueCallback() {
71 std::make_shared<typename decltype(m_value_boundary)::element_type>();
74 [[nodiscard]] ValueType operator()(
76 std::shared_ptr<blockforest::StructuredBlockForest>
const &blocks,
77 IBlock &
block)
const {
79 blocks->transformBlockLocalToGlobalCell(global,
block, local);
80 return get_value(global);
83 void set_node_boundary_value(
Cell const &global, ValueType
const &val) {
84 (*m_value_boundary)[global] = val;
87 void unset_node_boundary_value(
Cell const &global) {
88 assert(m_value_boundary->contains(global));
89 m_value_boundary->erase(global);
92 [[nodiscard]]
auto &get_node_boundary_value(
Cell const &global)
const {
93 return get_value(global);
96 bool node_is_boundary(
Cell const &global)
const {
97 return m_value_boundary->contains(global);
100#if defined(__CUDACC__)
107 void rebuild_flat_map_device(CellInterval
const &local_domain) {
108 std::vector<int> indices;
109 std::vector<FloatType> values;
110 auto const &local_origin = local_domain.min();
111 for (
auto const &[cell, value] : *m_value_boundary) {
112 if (local_domain.contains(cell)) {
113 for (
auto i : {0, 1, 2}) {
114 indices.emplace_back(cell[i] - local_origin[i]);
116 if constexpr (std::is_arithmetic_v<ValueType>) {
117 values.emplace_back(
static_cast<FloatType
>(value));
119 for (
auto i : {0, 1, 2}) {
120 values.emplace_back(
static_cast<FloatType
>(value[i]));
125 m_flat_indices =
decltype(m_flat_indices)(indices.begin(), indices.end());
126 m_flat_values =
decltype(m_flat_values)(values.begin(), values.end());
129 auto get_flattened_map_device()
const {
130 return std::make_pair(&m_flat_indices, &m_flat_values);
135#if defined(__CUDACC__)
136 thrust::device_vector<int> m_flat_indices;
137 thrust::device_vector<FloatType> m_flat_values;
139 std::shared_ptr<std::unordered_map<Cell, ValueType>> m_value_boundary;
140 static constexpr ValueType default_value{};
142 [[nodiscard]]
auto const &get_value(
Cell const &cell)
const {
143 if (m_value_boundary->contains(cell)) {
144 return m_value_boundary->at(cell);
146 return default_value;
150 [[nodiscard]]
inline auto get_flag_field_and_flag(IBlock *
block)
const {
151 auto const flag_field =
152 block->template uncheckedFastGetData<FlagField>(m_flag_field_id);
153 auto const boundary_flag = flag_field->getFlag(Boundary_flag);
154 return std::make_tuple(flag_field, boundary_flag);
162 BlockDataID value_field_id, BlockDataID flag_field_id,
163 CellInterval
const &local_domain)
164 : m_blocks(
std::move(blocks)), m_flag_field_id(flag_field_id),
165 m_callback(DynamicValueCallback()), m_local_domain(local_domain),
166 m_pending_changes(false) {
168 for (
auto &
block : *m_blocks) {
169 flag_reset_kernel(
block.template getData<FlagField>(m_flag_field_id));
172 std::function callback = m_callback;
174 std::make_shared<BoundaryClass>(m_blocks, value_field_id, callback);
181 return m_callback.node_is_boundary(
to_cell(node));
186 return m_callback.get_node_boundary_value(
to_cell(node));
191 auto [flag_field, boundary_flag] = get_flag_field_and_flag(bc.
block);
192 m_callback.set_node_boundary_value(
to_cell(node), v);
193 flag_field->addFlag(bc.
cell, boundary_flag);
194 m_pending_changes =
true;
198 ValueType
const &v) {
199 m_callback.set_node_boundary_value(
to_cell(node), v);
204 auto [flag_field, boundary_flag] = get_flag_field_and_flag(bc.
block);
205 m_callback.unset_node_boundary_value(
to_cell(node));
206 flag_field->removeFlag(bc.
cell, boundary_flag);
207 m_pending_changes =
true;
212 if (m_pending_changes) {
213 m_boundary->template fillFromFlagField<FlagField>(
214 m_blocks, m_flag_field_id, Boundary_flag, Domain_flag);
215#if defined(__CUDACC__)
216 m_callback.rebuild_flat_map_device(m_local_domain);
218 m_pending_changes =
false;
223 auto const field =
block.template getData<FlagField>(m_flag_field_id);
224 return {
static_cast<int>(field->xSize()),
static_cast<int>(field->ySize()),
225 static_cast<int>(field->zSize())};
228#if defined(__CUDACC__)
229 auto get_flattened_map_device()
const {
230 return m_callback.get_flattened_map_device();
235 return m_boundary->getForce(
block);
239 using ForceVector = BoundaryClass::ForceVector;
240 auto const force_vector_id = m_boundary->getForceVectorID();
241 auto *forceVector =
block->getData<ForceVector>(force_vector_id);
242 forceVector->syncCPU();
243 return m_boundary->getForceVector(
block);
246 return m_boundary->getIndexVector(
block);
250 std::shared_ptr<StructuredBlockForest> m_blocks;
251 BlockDataID m_flag_field_id;
252 DynamicValueCallback m_callback;
253 std::shared_ptr<BoundaryClass> m_boundary;
254 CellInterval m_local_domain;
255 bool m_pending_changes;
258 void flag_reset_kernel(
FlagField *flag_field) {
260 if (!flag_field->flagExists(Domain_flag))
261 flag_field->registerFlag(Domain_flag);
262 if (!flag_field->flagExists(Boundary_flag))
263 flag_field->registerFlag(Boundary_flag);
265 auto domain_flag = flag_field->getFlag(Domain_flag);
266 auto boundary_flag = flag_field->getFlag(Boundary_flag);
267 for (
auto it = flag_field->begin(); it != flag_field->end(); ++it) {
268 flag_field->addFlag(it.x(), it.y(), it.z(), domain_flag);
269 flag_field->removeFlag(it.x(), it.y(), it.z(), boundary_flag);