52 std::shared_ptr<StructuredBlockForest> blocks, BlockDataID field_id,
53 BlockDataID tmp_field_id,
unsigned int n_ghost_layers,
54 unsigned int shear_direction,
unsigned int shear_plane_normal,
56 std::function<
double()>
get_shift = []() {
return 0.0; })
57 : m_blocks(std::move(blocks)), m_field_id(field_id),
58 m_tmp_field_id(tmp_field_id), m_n_ghost_layers(uint_c(n_ghost_layers)),
59 m_shear_direction(uint_c(shear_direction)),
60 m_shear_plane_normal(uint_c(shear_plane_normal)),
63 if (m_n_ghost_layers != 1u) {
64 throw std::domain_error(
"The Lees-Edwards sweep is implemented "
65 "for a ghost layer of thickness 1");
67 if (m_shear_plane_normal == 0u) {
68 m_slab_min = stencil::W;
69 m_slab_max = stencil::E;
70 }
else if (m_shear_plane_normal == 1u) {
71 m_slab_min = stencil::S;
72 m_slab_max = stencil::N;
73 }
else if (m_shear_plane_normal == 2u) {
74 m_slab_min = stencil::B;
75 m_slab_max = stencil::T;
80 return numeric_cast<FloatType>(m_get_pos_offset());
83 FloatType
get_shift()
const {
return numeric_cast<FloatType>(m_get_shift()); }
86 kernel(
block, m_slab_min);
87 kernel(
block, m_slab_max);
91 void kernel(IBlock *
block, stencil::Direction slab_dir) {
93 assert(m_blocks->getNumberOfCells(*
block, m_shear_plane_normal) >= 2u);
94 auto const dir = m_shear_direction;
95 auto const dim = cell_idx_c(m_blocks->getNumberOfCells(*
block, dir));
96 auto const length = numeric_cast<FloatType>(dim);
99 auto field =
block->template getData<FieldType>(m_field_id);
100 auto tmp_field =
block->template getData<FieldType>(m_tmp_field_id);
103 field->getGhostRegion(slab_dir, ci, cell_idx_t{1},
true);
109 auto const prefactor =
110 ((slab_dir == m_slab_max) ? FloatType{-1} : FloatType{1});
111 auto const offset =
static_cast<FloatType
>(
get_pos_offset()) * prefactor;
112 auto const folded_offset = modulo(offset, length);
114 auto const weight1 = FloatType{1} - std::fmod(folded_offset, FloatType{1});
115 auto const weight2 = std::fmod(folded_offset, FloatType{1});
116 for (
auto const &&cell : ci) {
119 auto const source_pos =
static_cast<FloatType
>(cell[dir]) + folded_offset;
120 auto const folded_source_pos = modulo(source_pos, length);
122 source1[dir] = cell_idx_c(std::floor(folded_source_pos));
124 source2[dir] = cell_idx_c(modulo(FloatType(source1[dir] + 1), length));
126 for (uint_t q = 0u; q < FieldType::F_SIZE; ++q) {
127 tmp_field->get(cell, q) =
128 field->get(source1, q) * weight1 + field->get(source2, q) * weight2;
130 tmp_field->get(cell, m_shear_direction) -= prefactor * shift;
134 for (
auto const &&cell : ci) {
135 for (uint_t f = 0; f < FieldType::F_SIZE; ++f) {
136 field->get(cell, f) = tmp_field->get(cell, f);
141 FloatType modulo(FloatType a, FloatType b)
const {
142 auto const res = std::fmod(a, b);
143 return (res < FloatType{0}) ? res + b : res;
147 std::shared_ptr<StructuredBlockForest> m_blocks;
148 BlockDataID m_field_id;
149 BlockDataID m_tmp_field_id;
150 uint_t m_n_ghost_layers;
151 uint_t m_shear_direction;
152 uint_t m_shear_plane_normal;
153 std::function<double()> m_get_pos_offset;
154 std::function<double()> m_get_shift;
155 stencil::Direction m_slab_min;
156 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;})