VirtualFluids 0.2.0
Parallel CFD LBM Solver
Loading...
Searching...
No Matches
Side.cpp
Go to the documentation of this file.
1//=======================================================================================
2// ____ ____ __ ______ __________ __ __ __ __
3// \ \ | | | | | _ \ |___ ___| | | | | / \ | |
4// \ \ | | | | | |_) | | | | | | | / \ | |
5// \ \ | | | | | _ / | | | | | | / /\ \ | |
6// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____
7// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______|
8// \ \ | | ________________________________________________________________
9// \ \ | | | ______________________________________________________________|
10// \ \| | | | __ __ __ __ ______ _______
11// \ | | |_____ | | | | | | | | | _ \ / _____)
12// \ | | _____| | | | | | | | | | | \ \ \_______
13// \ | | | | |_____ | \_/ | | | | |_/ / _____ |
14// \ _____| |__| |________| \_______/ |__| |______/ (_______/
15//
16// This file is part of VirtualFluids. VirtualFluids is free software: you can
17// redistribute it and/or modify it under the terms of the GNU General Public
18// License as published by the Free Software Foundation, either version 3 of
19// the License, or (at your option) any later version.
20//
21// VirtualFluids is distributed in the hope that it will be useful, but WITHOUT
22// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24// for more details.
25//
26// SPDX-License-Identifier: GPL-3.0-or-later
27// SPDX-FileCopyrightText: Copyright © VirtualFluids Project contributors, see AUTHORS.md in root folder
28//
33//=======================================================================================
34#include "Side.h"
35
37#include "grid/Grid.h"
38#include "grid/NodeValues.h"
39
40#include "utilities/math/Math.h"
41#include <algorithm>
42#include <array>
43#include <cstddef>
44#include <stdexcept>
45#include <vector>
46
47namespace vf::gpu {
48
49using namespace grid_generator;
50
51std::array<real, 3> Side::getNormal() const
52{
53 std::array<real, 3> normal;
54 if(this->getCoordinate()==X_INDEX)
55 normal = {(real)this->getDirection(), 0.0, 0.0};
56 if(this->getCoordinate()==Y_INDEX)
57 normal = {0.0, (real)this->getDirection(), 0.0};
58 if(this->getCoordinate()==Z_INDEX)
59 normal = {0.0, 0.0, (real)this->getDirection()};
60 return normal;
61}
62
64{
65 return sideToD3Q27.at(whoAmI());
66}
67
68void Side::addIndices(SPtr<Grid> grid, SPtr<BoundaryCondition> boundaryCondition, std::string coord, real constant,
70{
71 for (real v2 = startOuter; v2 <= endOuter; v2 += grid->getDelta())
72 {
73 for (real v1 = startInner; v1 <= endInner; v1 += grid->getDelta())
74 {
75 const uint index = getIndex(grid, coord, constant, v1, v2);
76
77 if(index == INVALID_INDEX)
78 continue;
79
80 if ( grid->getFieldEntry(index) == vf::gpu::FLUID
81 || grid->getFieldEntry(index) == vf::gpu::FLUID_CFC
82 || grid->getFieldEntry(index) == vf::gpu::FLUID_CFF
83 || grid->getFieldEntry(index) == vf::gpu::FLUID_FCC
84 || grid->getFieldEntry(index) == vf::gpu::FLUID_FCF
85 || grid->getFieldEntry(index) == vf::gpu::FLUID_FCF
86 // Overlap of BCs on edge nodes
87 || grid->nodeHasBC(index) )
88 {
89 if(boundaryCondition->getType() != vf::gpu::BC_AD)
90 grid->setFieldEntry(index, boundaryCondition->getType());
91 boundaryCondition->indices.push_back(index);
92 setQs(grid, boundaryCondition, index);
93 boundaryCondition->setAdditionalIndices(grid, index);
94 boundaryCondition->patches.push_back(0);
95 }
96 }
97 }
98
99 const auto currentBCSide = this->whoAmI();
101 {
102 if(boundaryCondition->getType() != vf::gpu::BC_AD)
103 grid->addBCalreadySet(currentBCSide);
104 else
105 grid->addADBCalreadySet(currentBCSide);
106 }
107}
108
109void Side::setQs(SPtr<Grid> grid, SPtr<BoundaryCondition> boundaryCondition, uint index)
110{
111 std::vector<real> qNode(grid->getEndDirection() + 1);
112
113 for (int dir = 0; dir <= grid->getEndDirection(); dir++) {
114 real x, y, z;
115 grid->transIndexToCoords(index, x, y, z);
116
117 std::array<real, 3> coords = { x, y, z };
118 std::array<real, 3> neighborCoords = getNeighborCoordinates(grid.get(), coords, (size_t)dir);
119
121
122 const uint neighborIndex = grid->transCoordToIndex(neighborCoords[0], neighborCoords[1], neighborCoords[2]);
123
125 const bool alignedWithNormal = this->isAlignedWithMyNormal(grid.get(), dir);
126 if (grid->isStopperForBC(neighborIndex) && alignedWithNormal) {
127 qNode[dir] = 0.5;
128 } else {
129 qNode[dir] = -1.0;
130 }
131
132 // reset diagonals in case they were set by another bc
133 if(boundaryCondition->getType() == vf::gpu::BC_AD)
134 resetDiagonalsInCaseOfOtherBC(grid.get(), qNode, dir, coords, grid->getADBCAlreadySet());
135 else
136 resetDiagonalsInCaseOfOtherBC(grid.get(), qNode, dir, coords, grid->getBCAlreadySet());
137 }
138
139 boundaryCondition->qs.push_back(qNode);
140}
141
142std::array<real, 3> Side::getNeighborCoordinates(Grid *grid, const std::array<real, 3> &coordinates, size_t direction) const
143{
144 return { coordinates[0] + grid->getDirection()[direction * DIMENSION + 0] * grid->getDelta(),
145 coordinates[1] + grid->getDirection()[direction * DIMENSION + 1] * grid->getDelta(),
146 coordinates[2] + grid->getDirection()[direction * DIMENSION + 2] * grid->getDelta() };
147}
148
149bool Side::neighborNormalToSideIsAStopper(Grid *grid, const std::array<real, 3> &coordinates, SideType side) const
150{
151 const auto neighborCoords = getNeighborCoordinates(grid, coordinates, sideToD3Q27.at(side));
152 const auto neighborIndex = grid->transCoordToIndex(neighborCoords[0], neighborCoords[1], neighborCoords[2]);
153 return grid->isStopperForBC(neighborIndex);
154}
155
156void Side::resetDiagonalsInCaseOfOtherBC(Grid *grid, std::vector<real> &qNode, int dir,
157 const std::array<real, 3> &coordinates, const std::vector<SideType>& BCAlreadySet) const
158{
159 // When to reset a diagonal q to -1:
160 // - it is normal to another boundary condition which was already set
161 // - and it actually is influenced by the other bc:
162 // We check if its neighbor in the regular direction to the other bc is a stopper. If it is a stopper, it is influenced by the other bc.
163 if(qNode[dir] != 0.5)
164 return;
165
166 for (const auto& otherDir : BCAlreadySet) {
167
168 // only reset normals for nodes on edges and corners, not on faces
169 if (!neighborNormalToSideIsAStopper(grid, coordinates, otherDir))
170 continue;
171
172 const auto otherNormal = normals.at(otherDir);
173 if (isAlignedWithNormal(grid, dir, otherNormal)) {
174 qNode[dir] = -1.0;
175 }
176 }
177}
178
179bool Side::isAlignedWithMyNormal(const Grid *grid, int dir) const
180{
181 std::array<real, 3> normal = this->getNormal();
182 return isAlignedWithNormal(grid, dir, normal);
183}
184
185bool Side::isAlignedWithNormal(const Grid *grid, int dir, const std::array<real, 3> &normal) const
186{
187 return (normal[0] * grid->getDirection()[dir * DIMENSION + 0] +
188 normal[1] * grid->getDirection()[dir * DIMENSION + 1] +
189 normal[2] * grid->getDirection()[dir * DIMENSION + 2]) > 0;
190}
191
192void Side::correctNeighborForPeriodicBoundaries(const Grid *grid, std::array<real, 3>& coords, std::array<real, 3>& neighborCoords) const
193{
194 // correct neighbor coordinates in case of periodic boundaries
195 if (grid->getPeriodicityX() &&
196 grid->getFieldEntry(grid->transCoordToIndex(neighborCoords[0], coords[1], coords[2])) == vf::gpu::STOPPER_OUT_OF_GRID_BOUNDARY) {
197 if (neighborCoords[0] > coords[0])
198 neighborCoords[0] = grid->getFirstFluidNode(coords.data(), 0, grid->getStartX());
199 else
200 neighborCoords[0] = grid->getLastFluidNode(coords.data(), 0, grid->getEndX());
201 }
202
203 if (grid->getPeriodicityY() &&
204 grid->getFieldEntry(grid->transCoordToIndex(coords[0], neighborCoords[1], coords[2])) == vf::gpu::STOPPER_OUT_OF_GRID_BOUNDARY) {
205 if (neighborCoords[1] > coords[1])
206 neighborCoords[1] = grid->getFirstFluidNode(coords.data(), 1, grid->getStartY());
207 else
208 neighborCoords[1] = grid->getLastFluidNode(coords.data(), 1, grid->getEndY());
209 }
210
211 if (grid->getPeriodicityZ() &&
212 grid->getFieldEntry(grid->transCoordToIndex(coords[0], coords[1], neighborCoords[2])) == vf::gpu::STOPPER_OUT_OF_GRID_BOUNDARY) {
213 if (neighborCoords[2] > coords[2])
214 neighborCoords[2] = grid->getFirstFluidNode(coords.data(), 2, grid->getStartZ());
215 else
216 neighborCoords[2] = grid->getLastFluidNode(coords.data(), 2, grid->getEndZ());
217 }
218}
219
220uint Side::getIndex(SPtr<Grid> grid, std::string coord, real constant, real v1, real v2)
221{
222 if (coord == "x")
223 return grid->transCoordToIndex(constant, v1, v2);
224 if (coord == "y")
225 return grid->transCoordToIndex(v1, constant, v2);
226 if (coord == "z")
227 return grid->transCoordToIndex(v1, v2, constant);
228 return INVALID_INDEX;
229}
230
231
232void Geometry::addIndices(const std::vector<SPtr<Grid>> &grids, uint level, SPtr<BoundaryCondition> boundaryCondition)
233{
234 auto geometryBoundaryCondition = std::dynamic_pointer_cast<GeometryBoundaryCondition>(boundaryCondition);
235 if(geometryBoundaryCondition == nullptr)
236 throw std::runtime_error("Tried to set unallowed boundary condition on geometry");
237
238 std::vector<real> qNode(grids[level]->getEndDirection() + 1);
239
240 for (uint index = 0; index < grids[level]->getSize(); index++)
241 {
242 if (grids[level]->getFieldEntry(index) != vf::gpu::BC_SOLID)
243 continue;
244
245 for (int dir = 0; dir <= grids[level]->getEndDirection(); dir++)
246 {
247 const real q = grids[level]->getQValue(index, dir);
248
249 qNode[dir] = q;
250
251 // also the neighbor if any Qs are required
252 real x,y,z;
253 grids[level]->transIndexToCoords( index, x, y, z );
254
255 x += grids[level]->getDirection()[dir * DIMENSION + 0] * grids[level]->getDelta();
256 y += grids[level]->getDirection()[dir * DIMENSION + 1] * grids[level]->getDelta();
257 z += grids[level]->getDirection()[dir * DIMENSION + 2] * grids[level]->getDelta();
258
259 uint neighborIndex = grids[level]->transCoordToIndex( x, y, z );
260
261 if( qNode[dir] < -0.5 && ( grids[level]->getFieldEntry(neighborIndex) == vf::gpu::STOPPER_OUT_OF_GRID_BOUNDARY ||
262 grids[level]->getFieldEntry(neighborIndex) == vf::gpu::STOPPER_OUT_OF_GRID ||
263 grids[level]->getFieldEntry(neighborIndex) == vf::gpu::STOPPER_SOLID ) )
264 qNode[dir] = 0.5;
265 }
266
267 geometryBoundaryCondition->indices.push_back(index);
268 geometryBoundaryCondition->qs.push_back(qNode);
269 geometryBoundaryCondition->patches.push_back(grids[level]->getQPatch(index));
270 }
271}
272
273
274
275void MX::addIndices(const std::vector<SPtr<Grid>> &grid, uint level, SPtr<BoundaryCondition> boundaryCondition)
276{
277 real startInner = grid[level]->getStartY();
278 real endInner = grid[level]->getEndY();
279
280 real startOuter = grid[level]->getStartZ();
281 real endOuter = grid[level]->getEndZ();
282
283 real coordinateNormal = grid[level]->getStartX() + grid[level]->getDelta();
284
285 if( coordinateNormal > grid[0]->getStartX() + grid[0]->getDelta() ) return;
286
287 Side::addIndices(grid[level], boundaryCondition, "x", coordinateNormal, startInner, endInner, startOuter, endOuter);
288
289}
290
291void PX::addIndices(const std::vector<SPtr<Grid>> &grid, uint level, SPtr<BoundaryCondition> boundaryCondition)
292{
293 real startInner = grid[level]->getStartY();
294 real endInner = grid[level]->getEndY();
295
296 real startOuter = grid[level]->getStartZ();
297 real endOuter = grid[level]->getEndZ();
298
299 real coordinateNormal = grid[level]->getEndX() - grid[level]->getDelta();
300
301 if( coordinateNormal < grid[0]->getEndX() - grid[0]->getDelta() ) return;
302
303 Side::addIndices(grid[level], boundaryCondition, "x", coordinateNormal, startInner, endInner, startOuter, endOuter);
304}
305
306void MY::addIndices(const std::vector<SPtr<Grid>> &grid, uint level, SPtr<BoundaryCondition> boundaryCondition)
307{
308 real startInner = grid[level]->getStartX();
309 real endInner = grid[level]->getEndX();
310
311 real startOuter = grid[level]->getStartZ();
312 real endOuter = grid[level]->getEndZ();
313
314 real coordinateNormal = grid[level]->getStartY() + grid[level]->getDelta();
315
316 if( coordinateNormal > grid[0]->getStartY() + grid[0]->getDelta() ) return;
317
318 Side::addIndices(grid[level], boundaryCondition, "y", coordinateNormal, startInner, endInner, startOuter, endOuter);
319}
320
321
322void PY::addIndices(const std::vector<SPtr<Grid>> &grid, uint level, SPtr<BoundaryCondition> boundaryCondition)
323{
324 real startInner = grid[level]->getStartX();
325 real endInner = grid[level]->getEndX();
326
327 real startOuter = grid[level]->getStartZ();
328 real endOuter = grid[level]->getEndZ();
329
330 real coordinateNormal = grid[level]->getEndY() - grid[level]->getDelta();
331
332 if( coordinateNormal < grid[0]->getEndY() - grid[0]->getDelta() ) return;
333
334 Side::addIndices(grid[level], boundaryCondition, "y", coordinateNormal, startInner, endInner, startOuter, endOuter);
335}
336
337
338void MZ::addIndices(const std::vector<SPtr<Grid>> &grid, uint level, SPtr<BoundaryCondition> boundaryCondition)
339{
340 real startInner = grid[level]->getStartX();
341 real endInner = grid[level]->getEndX();
342
343 real startOuter = grid[level]->getStartY();
344 real endOuter = grid[level]->getEndY();
345
346 real coordinateNormal = grid[level]->getStartZ() + grid[level]->getDelta();
347
348 if( coordinateNormal > grid[0]->getStartZ() + grid[0]->getDelta() ) return;
349
350 Side::addIndices(grid[level], boundaryCondition, "z", coordinateNormal, startInner, endInner, startOuter, endOuter);
351}
352
353void PZ::addIndices(const std::vector<SPtr<Grid>> &grid, uint level, SPtr<BoundaryCondition> boundaryCondition)
354{
355 real startInner = grid[level]->getStartX();
356 real endInner = grid[level]->getEndX();
357
358 real startOuter = grid[level]->getStartY();
359 real endOuter = grid[level]->getEndY();
360
361 real coordinateNormal = grid[level]->getEndZ() - grid[level]->getDelta();
362
363 if( coordinateNormal < grid[0]->getEndZ() - grid[0]->getDelta() ) return;
364
365 Side::addIndices(grid[level], boundaryCondition, "z", coordinateNormal, startInner, endInner, startOuter, endOuter);
366}
367
368}
369
void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition) override
Definition Side.cpp:232
virtual real getEndY() const =0
virtual real getStartZ() const =0
virtual const std::vector< int > & getDirection() const =0
virtual real getEndX() const =0
virtual real getFirstFluidNode(real coords[3], int direction, real startCoord) const =0
virtual real getDelta() const =0
virtual bool getPeriodicityY() const =0
virtual bool getPeriodicityX() const =0
virtual real getStartY() const =0
virtual char getFieldEntry(uint matrixIndex) const =0
virtual real getLastFluidNode(real coords[3], int direction, real startCoord) const =0
virtual uint transCoordToIndex(const real &x, const real &y, const real &z) const =0
virtual real getEndZ() const =0
virtual real getStartX() const =0
virtual bool getPeriodicityZ() const =0
void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition) override
Definition Side.cpp:275
void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition) override
Definition Side.cpp:306
void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition) override
Definition Side.cpp:338
void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition) override
Definition Side.cpp:291
void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition) override
Definition Side.cpp:322
void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition) override
Definition Side.cpp:353
const std::map< SideType, size_t > sideToD3Q27
Definition Side.h:107
virtual int getDirection() const =0
size_t getD3Q27Direction() const
Definition Side.cpp:63
virtual bool isAlignedWithMyNormal(const Grid *grid, int dir) const
Definition Side.cpp:179
virtual void correctNeighborForPeriodicBoundaries(const Grid *grid, std::array< real, 3 > &coords, std::array< real, 3 > &neighbors) const
Definition Side.cpp:192
virtual int getCoordinate() const =0
void setQs(SPtr< Grid > grid, SPtr< grid_generator::BoundaryCondition > boundaryCondition, uint index)
Definition Side.cpp:109
virtual SideType whoAmI() const =0
virtual void addIndices(const std::vector< SPtr< Grid > > &grid, uint level, SPtr< grid_generator::BoundaryCondition > boundaryCondition)=0
const std::map< SideType, const std::array< real, 3 > > normals
Definition Side.h:102
std::array< real, 3 > getNormal() const
Definition Side.cpp:51
bool isAlignedWithNormal(const Grid *grid, int dir, const std::array< real, 3 > &normal) const
Definition Side.cpp:185
std::shared_ptr< T > SPtr
float real
Definition DataTypes.h:42
unsigned int uint
Definition DataTypes.h:47
#define INVALID_INDEX
Definition DataTypes.h:48
@ z
Definition Axis.h:44
@ x
Definition Axis.h:42
@ y
Definition Axis.h:43
#define DIMENSION
Definition global.h:38
#define X_INDEX
Definition Side.h:46
#define Y_INDEX
Definition Side.h:47
#define Z_INDEX
Definition Side.h:48
SideType
Definition Side.h:63