Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
AMRBlockCellLowering.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10#pragma once
11
23#include <array>
24#include <variant>
25
26namespace shammodels::amr {
27
28 enum StencilPosition {
29 xp1 = 0,
30 xm1 = 1,
31 yp1 = 2,
32 ym1 = 3,
33 zp1 = 4,
34 zm1 = 5,
35 };
36
38
39 static constexpr u32 dim = 3;
41
42 template<StencilPosition stencil_pos>
43 inline static constexpr std::array<i32, 3> get_relative_offset_vec() {
44 if constexpr (stencil_pos == xp1) {
45 return std::array<i32, 3>{1, 0, 0};
46 } else if constexpr (stencil_pos == xm1) {
47 return std::array<i32, 3>{-1, 0, 0};
48 } else if constexpr (stencil_pos == yp1) {
49 return std::array<i32, 3>{0, 1, 0};
50 } else if constexpr (stencil_pos == ym1) {
51 return std::array<i32, 3>{0, -1, 0};
52 } else if constexpr (stencil_pos == zp1) {
53 return std::array<i32, 3>{0, 0, 1};
54 } else if constexpr (stencil_pos == zm1) {
55 return std::array<i32, 3>{0, 0, -1};
56 } else {
57 static_assert(
58 shambase::always_false_v<decltype(stencil_pos)>, "non-exhaustive visitor!");
59 }
60 }
61
62 template<StencilPosition stencil_pos>
63 inline static constexpr i32 get_relative_offset() {
64 return AMRBlock::get_index_relative(get_relative_offset_vec<stencil_pos>());
65 }
66
67 template<StencilPosition stencil_pos>
68 inline static constexpr cell::StencilElement lower_block_to_cell(
69 u32 block_id,
70 u32 local_cell_id,
71 std::array<u32, dim> lcoord,
72 block::StencilElement block_stencil_el) {
73
74 // check if still within block (and return if thats the case)
75
76 i32 offset_lcoord = i32(local_cell_id) + get_relative_offset<stencil_pos>();
77
78 if (offset_lcoord > 0 && offset_lcoord < AMRBlock::block_size) {
80 cell::SameLevel{block_id * AMRBlock::block_size + offset_lcoord}};
81 }
82
83 // the previous part has not returned so we have to look at the neighbouring block
84
85 constexpr std::array<i32, 3> off = get_relative_offset_vec<stencil_pos>();
86
87 // offset local coordinates
88 std::array<i32, dim> coord_off = {
89 lcoord[0] + off[0],
90 lcoord[1] + off[1],
91 lcoord[2] + off[2],
92 };
93
94 // make the local coord relative to the neighbouring block
95 if constexpr (stencil_pos == xp1) {
96 coord_off[0] -= AMRBlock::side_size;
97 } else if constexpr (stencil_pos == xm1) {
98 coord_off[0] += AMRBlock::side_size;
99 } else if constexpr (stencil_pos == yp1) {
100 coord_off[1] -= AMRBlock::side_size;
101 } else if constexpr (stencil_pos == ym1) {
102 coord_off[1] += AMRBlock::side_size;
103 } else if constexpr (stencil_pos == zp1) {
104 coord_off[2] -= AMRBlock::side_size;
105 } else if constexpr (stencil_pos == zm1) {
106 coord_off[2] += AMRBlock::side_size;
107 } else {
108 static_assert(
109 shambase::always_false_v<decltype(stencil_pos)>, "non-exhaustive visitor!");
110 }
111
112 return block_stencil_el.visitor_ret<cell::StencilElement>(
113 [&](block::SameLevel st) {
114 return cell::SameLevel{
115 st.block_idx * AMRBlock::block_size
117 {u32(coord_off[0]), u32(coord_off[1]), u32(coord_off[2])})};
118 },
119 [&](block::Levelm1 st) {
120 std::array<u32, 3> mod_coord{
121 u32(coord_off[0]) % 2,
122 u32(coord_off[1]) % 2,
123 u32(coord_off[2]) % 2,
124 };
125
126 std::array<i32, 3> block_pos_offset{
127 (0b100 & st.neighbourgh_state) >> 2,
128 (0b010 & st.neighbourgh_state) >> 1,
129 (0b001 & st.neighbourgh_state) >> 0,
130 };
131
132 block_pos_offset[0] *= AMRBlock::side_size / 2;
133 block_pos_offset[1] *= AMRBlock::side_size / 2;
134 block_pos_offset[2] *= AMRBlock::side_size / 2;
135
136 coord_off = {
137 block_pos_offset[0] + (coord_off[0] / 2),
138 block_pos_offset[1] + (coord_off[1] / 2),
139 block_pos_offset[2] + (coord_off[2] / 2),
140 };
141
142 auto neigh_state
143 = cell::Levelm1::STATE(mod_coord[0] * 4 + mod_coord[1] * 2 + mod_coord[2]);
144
145 return cell::Levelm1{
146 neigh_state,
147 st.block_idx * AMRBlock::block_size
149 {u32(coord_off[0]), u32(coord_off[1]), u32(coord_off[2])})};
150 },
151 [&](block::Levelp1 st) {
152 std::array<u32, 3> mod_coord{
153 u32(coord_off[0] / (AMRBlock::side_size / 2)),
154 u32(coord_off[1] / (AMRBlock::side_size / 2)),
155 u32(coord_off[2] / (AMRBlock::side_size / 2)),
156 };
157 u32 child_select = mod_coord[0] * 4 + mod_coord[1] * 2 + mod_coord[2];
158
159 coord_off
160 = {int((coord_off[0] * 2) % AMRBlock::side_size),
161 int((coord_off[1] * 2) % AMRBlock::side_size),
162 int((coord_off[2] * 2) % AMRBlock::side_size)};
163
164 u32 idx_tmp = st.block_child_idxs[child_select] * AMRBlock::block_size
166 {u32(coord_off[0]), u32(coord_off[1]), u32(coord_off[2])});
167
168 return cell::Levelp1{idx_tmp};
169 },
170 [&](block::StencilElement::None st) {
171 return cell::StencilElement::None{};
172 });
173 }
174 };
175
176} // namespace shammodels::amr
utility to manipulate AMR blocks
utility to manipulate AMR blocks
utility to manipulate AMR blocks
std::uint32_t u32
32 bit unsigned integer
std::int32_t i32
32 bit integer
constexpr bool always_false_v
Helper variable template that is always false. Especially useful to perform static asserts based on t...
Traits for C++ types.
utility class to handle AMR blocks
Definition AMRBlock.hpp:35
static constexpr u32 get_index(std::array< u32, dim > coord) noexcept
Get the local index within the AMR block.
Definition AMRBlock.hpp:52
Stencil element, describe the state of a cell relative to another.
Stencil element, describe the state of a cell relative to another.