OpenLB 1.8.1
Loading...
Searching...
No Matches
ibm3D.h
Go to the documentation of this file.
1/* Lattice Boltzmann sample, written in C++, using the OpenLB
2 * library
3 *
4 * Copyright (C) 2024 Shota Ito, Adrian Kummerländer
5 * E-mail contact: info@openlb.net
6 * The most recent release of OpenLB can be downloaded at
7 * <http://www.openlb.net/>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25#ifndef IMMERSED_BOUNDARY_METHOD_3D_H
26#define IMMERSED_BOUNDARY_METHOD_3D_H
27
28#include "stencil.h"
29
30namespace olb {
31
32namespace ibm {
33
34template <int WIDTH>
37
40 >;
41
42 template <typename CELLS, typename PARAMETERS>
43 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
44 {
45 using V = typename CELLS::template value_t<names::NavierStokes>::value_t;
46
47 Vector<V,3> u{}; // interpolated vel. of particle with physR
48 auto particle = cells.template get<names::Points>(); // current particle assoc. with cells
49 auto f_cell = cells.template get<names::NavierStokes>(); // closest lattice cell to particle
50 auto f_physR = f_cell.template getField<descriptors::LOCATION>(); // physR of fluid cell
51 auto p_physR = particle.template getField<fields::PHYS_R>(); // physR of particle
52 V dx = parameters.template get<fields::converter::PHYS_DELTA_X>(); // delta x of fluid cell
53 Vector<int,3> rel_lat_min;
54 for (int d = 0; d < 3; ++d) {
55 rel_lat_min[d] = static_cast<int>(util::floor((p_physR[d] - f_physR[d]) / dx - WIDTH / 2.) + 1);
56 }
57 for (int x = rel_lat_min[0]; x < WIDTH + rel_lat_min[0]; ++x) {
58 for (int y = rel_lat_min[1]; y < WIDTH + rel_lat_min[1]; ++y) {
59 for (int z = rel_lat_min[2]; z < WIDTH + rel_lat_min[2]; ++z) {
60 auto n_physR = f_cell.neighbor({x, y, z}).template getField<descriptors::LOCATION>(); // physR of cell inside stencil
61 auto dist = (n_physR - p_physR) / dx; // lat. dist.
62 Vector<V,3> u_tmp{};
63 f_cell.neighbor({x, y, z}).computeU(u_tmp.data()); // get fluid vel.
64 u_tmp *= Stencil<V,WIDTH>::weight(dist[0]) *
66 Stencil<V,WIDTH>::weight(dist[2]); // mult. interp. weights
67 u += u_tmp; // add contribution
68 }
69 }
70 }
71 particle.template setField<fields::membrane::VELOCITY>(u);
72 }
73};
74
75template <int WIDTH>
78
81 >;
82
83 template <typename CELLS, typename PARAMETERS>
84 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
85 {
86 using V = typename CELLS::template value_t<names::NavierStokes>::value_t;
87
88 auto particle = cells.template get<names::Points>(); // current particle assoc. with cells
89 auto f_cell = cells.template get<names::NavierStokes>(); // closest lattice cell to particle
90 auto f_physR = f_cell.template getField<descriptors::LOCATION>(); // physR of fluid cell
91 auto p_physR = particle.template getField<fields::PHYS_R>(); // physR of particle
92 V dx = parameters.template get<fields::converter::PHYS_DELTA_X>(); // delta x of fluid cell
93 Vector<int,3> rel_lat_min;
94 for (int d = 0; d < 3; ++d) {
95 rel_lat_min[d] = static_cast<int>(util::floor((p_physR[d] - f_physR[d]) / dx - WIDTH / 2.) + 1);
96 }
97
98 for (int x = rel_lat_min[0]; x < WIDTH + rel_lat_min[0]; ++x) {
99 for (int y = rel_lat_min[1]; y < WIDTH + rel_lat_min[1]; ++y) {
100 for (int z = rel_lat_min[2]; z < WIDTH + rel_lat_min[2]; ++z) {
101 auto n_physR = f_cell.neighbor({x, y, z}).template getField<descriptors::LOCATION>(); // physR of cell inside stencil
102 auto dist = (n_physR - p_physR) / dx; // lat. dist.
103 auto f_F = f_cell.neighbor({x,y,z}).template getField<descriptors::FORCE>(); // old fluid force
104 auto p_F = particle.template getField<fields::membrane::FORCE>(); // get solid-node force
105 p_F *= Stencil<V,WIDTH>::weight(dist[0]) *
106 Stencil<V,WIDTH>::weight(dist[1]) *
107 Stencil<V,WIDTH>::weight(dist[2]); // mult. interp. weights
108 f_cell.neighbor({x,y,z}).template setField<descriptors::FORCE>(f_F + p_F); // update by adding force contribution
109 }
110 }
111 }
112 }
113};
114
115}
116
118template<int WIDTH, typename COUPLEES>
120private:
121 template <typename VALUED_DESCRIPTOR>
122 using ptr_to_lattice = std::conditional_t<
123 VALUED_DESCRIPTOR::descriptor_t::template provides<descriptors::POPULATION>(),
124 SuperLattice<typename VALUED_DESCRIPTOR::value_t,
125 typename VALUED_DESCRIPTOR::descriptor_t>,
126 SuperD<typename VALUED_DESCRIPTOR::value_t,
127 typename VALUED_DESCRIPTOR::descriptor_t>
128 >*;
129
130 utilities::TypeIndexedTuple<typename COUPLEES::template map_values<
131 ptr_to_lattice
132 >> _lattices;
133
134 std::unique_ptr<SuperLatticePointCoupling<ibm::InterpolateVelocityO<WIDTH>,COUPLEES>> _interpolateO;
135 std::unique_ptr<SuperLatticePointCoupling<ibm::SpreadForceO<WIDTH>,COUPLEES>> _spreadForceO;
136public:
137 template<typename... MAP>
138 SuperImmersedBoundaryCoupling3D(std::integral_constant<int,WIDTH>, MAP&&... args)
139 {
140 auto map = std::make_tuple(&args...);
141 COUPLEES::keys_t::for_each([&](auto id) {
142 using name_t = typename decltype(id)::type;
143 constexpr unsigned idx = COUPLEES::keys_t::template index<name_t>();
144 _lattices.template set<name_t>(std::get<2*idx+1>(map));
145 });
146
147 _interpolateO = std::make_unique<SuperLatticePointCoupling<ibm::InterpolateVelocityO<WIDTH>,COUPLEES>>(
150 names::Points{}, *(_lattices.get(meta::id<names::Points>{})));
151 _spreadForceO = std::make_unique<SuperLatticePointCoupling<ibm::SpreadForceO<WIDTH>,COUPLEES>>(
154 names::Points{}, *(_lattices.get(meta::id<names::Points>{})));
155
156 // set the LOCATION FIELD
157 auto sLattice = _lattices.get(meta::id<names::NavierStokes>{});
158 auto& load = sLattice->getLoadBalancer();
159 for (int iC=0; iC < load.size(); ++iC) {
160 sLattice->getBlock(iC).forSpatialLocations([&](LatticeR<3> latticeR) {
161 int latR[4] {iC, latticeR[0], latticeR[1], latticeR[2]};
162 auto physR = sLattice->getCuboidDecomposition().getPhysR(latR);
163 sLattice->getBlock(iC).get(latticeR).template setField<descriptors::LOCATION>(physR);
164 });
165 }
166 }
167
168 template <typename T>
169 void setPhysDeltaX(T dx)
170 {
171 _interpolateO->template setParameter<fields::converter::PHYS_DELTA_X>(dx);
172 _spreadForceO->template setParameter<fields::converter::PHYS_DELTA_X>(dx);
173 }
174
175 void execute()
176 {
177 // purge force field
178 auto sLattice = _lattices.get(meta::id<names::NavierStokes>{});
179 auto& load = sLattice->getLoadBalancer();
180 using V = typename std::remove_reference<decltype(*sLattice)>::type::value_t;
181 for (int iC=0; iC < load.size(); ++iC) {
182 sLattice->getBlock(iC).forSpatialLocations([&](LatticeR<3> latticeR) {
183 int latR[4] {0, latticeR[0], latticeR[1], latticeR[2]};
184 sLattice->getBlock(iC).get(latR[1],latR[2],latR[3]).template setField<descriptors::FORCE>(V{0.0});
185 });
186 }
187
188 // spread force from membrane to fluid
189 _spreadForceO->execute();
190
191 // interpolate fluid velocity on membrane surface
192 _interpolateO->execute();
193 }
194};
195
196template <int WIDTH, typename... MAP>
197SuperImmersedBoundaryCoupling3D(std::integral_constant<int,WIDTH>, MAP&&...)
199 WIDTH,
200 typename meta::map<MAP...>::template map_values<descriptors::extract_valued_descriptor_t>
201>;
202
203}
204
205#endif
Wrapper class to perform the immersed boundary method.
Definition ibm3D.h:119
SuperImmersedBoundaryCoupling3D(std::integral_constant< int, WIDTH >, MAP &&... args)
Definition ibm3D.h:138
Super class maintaining block lattices for a cuboid decomposition.
Plain old scalar vector.
ADf< T, DIM > floor(const ADf< T, DIM > &a)
Definition aDiff.h:869
Top level namespace for all of OpenLB.
SuperImmersedBoundaryCoupling3D(std::integral_constant< int, WIDTH >, MAP &&...) -> SuperImmersedBoundaryCoupling3D< WIDTH, typename meta::map< MAP... >::template map_values< descriptors::extract_valued_descriptor_t > >
OperatorScope
Block-wide operator application scopes.
@ PerCellWithParameters
Per-cell application with parameters, i.e. OPERATOR::apply is passed a CELL concept implementation an...
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:77
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Definition ibm3D.h:43
static constexpr OperatorScope scope
Definition ibm3D.h:36
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Definition ibm3D.h:84
static constexpr OperatorScope scope
Definition ibm3D.h:77
Identity type to pass non-constructible types as value.
Definition meta.h:79
Plain wrapper for list of types.
Definition meta.h:276
Mapping between KEYs and instances of type VALUEs.