59 std::shared_ptr<StructuredBlockForest> blocks, BlockDataID field_id,
60 BlockDataID tmp_field_id,
unsigned int n_ghost_layers,
61 unsigned int shear_direction,
unsigned int shear_plane_normal,
63 std::function<
double()>
get_shift = []() {
return 0.0; })
64 : m_blocks(std::move(blocks)), m_field_id(field_id),
65 m_tmp_field_id(tmp_field_id), m_n_ghost_layers(uint_c(n_ghost_layers)),
66 m_shear_direction(uint_c(shear_direction)),
67 m_shear_plane_normal(uint_c(shear_plane_normal)),
70 if (m_n_ghost_layers != 1u) {
71 throw std::domain_error(
"The Lees-Edwards sweep is implemented "
72 "for a ghost layer of thickness 1");
74 if (m_shear_plane_normal == 0u) {
75 m_slab_min = stencil::W;
76 m_slab_max = stencil::E;
77 }
else if (m_shear_plane_normal == 1u) {
78 m_slab_min = stencil::S;
79 m_slab_max = stencil::N;
80 }
else if (m_shear_plane_normal == 2u) {
81 m_slab_min = stencil::B;
82 m_slab_max = stencil::T;
87 return numeric_cast<FloatType>(m_get_pos_offset());
90 FloatType
get_shift()
const {
return numeric_cast<FloatType>(m_get_shift()); }
93 kernel(
block, m_slab_min);
94 kernel(
block, m_slab_max);
98 void kernel(IBlock *
block, stencil::Direction slab_dir) {
100 assert(m_blocks->getNumberOfCells(*
block, m_shear_plane_normal) >= 2u);
101 auto const dir = m_shear_direction;
102 auto const dim = cell_idx_c(m_blocks->getNumberOfCells(*
block, dir));
103 auto const length = numeric_cast<FloatType>(dim);
106 auto field =
block->template getData<FieldType>(m_field_id);
107 auto tmp_field =
block->template getData<FieldType>(m_tmp_field_id);
110 field->getGhostRegion(slab_dir, ci, cell_idx_t{1},
true);
116 auto const prefactor =
117 ((slab_dir == m_slab_max) ? FloatType{-1} : FloatType{1});
118 auto const offset =
static_cast<FloatType
>(
get_pos_offset()) * prefactor;
119 auto const folded_offset = modulo(offset, length);
121 auto const weight1 = FloatType{1} - std::fmod(folded_offset, FloatType{1});
122 auto const weight2 = std::fmod(folded_offset, FloatType{1});
123 for (
auto const &&cell : ci) {
126 auto const source_pos =
static_cast<FloatType
>(cell[dir]) + folded_offset;
127 auto const folded_source_pos = modulo(source_pos, length);
129 source1[dir] = cell_idx_c(std::floor(folded_source_pos));
131 source2[dir] = cell_idx_c(modulo(FloatType(source1[dir] + 1), length));
133 for (uint_t q = 0u; q < FieldType::F_SIZE; ++q) {
134 tmp_field->get(cell, q) =
135 field->get(source1, q) * weight1 + field->get(source2, q) * weight2;
137 tmp_field->get(cell, m_shear_direction) -= prefactor * shift;
141 for (
auto const &&cell : ci) {
142 for (uint_t f = 0; f < FieldType::F_SIZE; ++f) {
143 field->get(cell, f) = tmp_field->get(cell, f);
148 FloatType modulo(FloatType a, FloatType b)
const {
149 auto const res = std::fmod(a, b);
150 return (res < FloatType{0}) ? res + b : res;
154 std::shared_ptr<StructuredBlockForest> m_blocks;
155 BlockDataID m_field_id;
156 BlockDataID m_tmp_field_id;
157 uint_t m_n_ghost_layers;
158 uint_t m_shear_direction;
159 uint_t m_shear_plane_normal;
160 std::function<double()> m_get_pos_offset;
161 std::function<double()> m_get_shift;
162 stencil::Direction m_slab_min;
163 stencil::Direction m_slab_max;
InterpolateAndShiftAtBoundary(std::shared_ptr< StructuredBlockForest > blocks, BlockDataID field_id, BlockDataID tmp_field_id, unsigned int n_ghost_layers, unsigned int shear_direction, unsigned int shear_plane_normal, std::function< double()> get_pos_offset, std::function< double()> get_shift=[]() { return 0.0;})