ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
InterpolateAndShiftAtBoundary.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2021-2023 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
23
24#include <blockforest/StructuredBlockForest.h>
25#include <domain_decomposition/all.h>
26#include <stencil/D3Q19.h>
27
28#include <cmath>
29#include <functional>
30#include <memory>
31#include <stdexcept>
32#include <utility>
33
34namespace walberla {
35
36/**
37 * Lees-Edwards sweep.
38 * @todo Currently only works for 1 MPI rank! It should work in parallel if the
39 * MPI domain decomposition for the structured block forest doesn't partition
40 * along the shear direction. For example if the shear direction goes along
41 * the z-axis, it should be possible to run on 4 MPI ranks with [2, 2, 1].
42 * At the moment, ESPResSo requires system.cell_system.node_grid to be in
43 * decreasing order, therefore parallelization requires a shear direction
44 * along the z-axis and a MPI node_grid of [x, y, 1] with x >= y. This
45 * restriction on the ordering of the node_grid may be lifted in the
46 * distant future, when our FFT algorithm is replaced by a new one.
47 */
48template <class FieldType, typename FloatType>
50public:
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,
55 std::function<double()> get_pos_offset,
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)),
61 m_get_pos_offset(std::move(get_pos_offset)),
62 m_get_shift(std::move(get_shift)) {
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");
66 }
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;
76 }
77 }
78
79 FloatType get_pos_offset() const {
80 return numeric_cast<FloatType>(m_get_pos_offset());
81 }
82
83 FloatType get_shift() const { return numeric_cast<FloatType>(m_get_shift()); }
84
85 void operator()(IBlock *block) {
86 kernel(block, m_slab_min);
87 kernel(block, m_slab_max);
88 }
89
90private:
91 void kernel(IBlock *block, stencil::Direction slab_dir) {
92 // setup lengths
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);
97 auto const weight =
98 std::abs(std::fmod(get_pos_offset() + length, FloatType{1}));
99
100 // setup slab
101 auto field = block->template getData<FieldType>(m_field_id);
102 auto tmp_field = block->template getData<FieldType>(m_tmp_field_id);
103
104 CellInterval ci;
105 field->getGhostRegion(slab_dir, ci, cell_idx_t{1}, true);
106
107 // shift
108 auto const shift = get_shift();
109 // Note that the offset is applied to the interpolation source rather than
110 // the target
111 auto const prefactor =
112 ((slab_dir == m_slab_max) ? FloatType{-1} : FloatType{1});
113 auto const offset = get_pos_offset() * prefactor;
114 for (auto const &&cell : ci) {
115 Cell source1 = cell;
116 Cell source2 = cell;
117 source1[dir] = cell_idx_c(std::floor(
118 static_cast<FloatType>(source1[dir]) + offset)) %
119 dim;
120 source1[dir] = cell_idx_c(static_cast<FloatType>(source1[dir]) + length);
121 source1[dir] = cell_idx_c(source1[dir] % dim);
122
123 source2[dir] =
124 cell_idx_c(std::ceil(static_cast<FloatType>(source2[dir]) + offset)) %
125 dim;
126 source2[dir] = cell_idx_c(static_cast<FloatType>(source2[dir]) + length);
127 source2[dir] = cell_idx_c(source2[dir] % dim);
128
129 for (uint_t f = 0; f < FieldType::F_SIZE; ++f) {
130 tmp_field->get(cell, f) = field->get(source1, f) * (1 - weight) +
131 field->get(source2, f) * weight;
132 }
133 tmp_field->get(cell, m_shear_direction) -= prefactor * shift;
134 }
135
136 // swap
137 for (auto const &&cell : ci) {
138 for (uint_t f = 0; f < FieldType::F_SIZE; ++f) {
139 field->get(cell, f) = tmp_field->get(cell, f);
140 }
141 }
142 }
143
144private:
145 std::shared_ptr<StructuredBlockForest> m_blocks;
146 BlockDataID m_field_id;
147 BlockDataID m_tmp_field_id;
148 uint_t m_n_ghost_layers;
149 uint_t m_shear_direction;
150 uint_t m_shear_plane_normal;
151 std::function<double()> m_get_pos_offset;
152 std::function<double()> m_get_shift;
153 stencil::Direction m_slab_min;
154 stencil::Direction m_slab_max;
155};
156
157} // namespace walberla
float f[3]
float u[3]
Definition Cell.hpp:98
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;})
static double weight(int type, double r_cut, double k, double r)
Definition dpd.cpp:79
static double * block(double *p, std::size_t index, std::size_t size)
Definition elc.cpp:174