VirtualFluids 0.2.0
Parallel CFD LBM Solver
Loading...
Searching...
No Matches
inverseMomentumExchange.cuh
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//
29//! \author Henry Korb
30//=======================================================================================
31#ifndef StressFunctions_H
32#define StressFunctions_H
33
34#include <cmath>
35#include <cuda_runtime.h>
36
37#include <basics/DataTypes.h>
38#include <basics/constants/NumericConstants.h>
39#include <lbm/MacroscopicQuantities.h>
40#include <lbm/collision/TurbulentViscosity.h>
41#include <lbm/constants/D3Q27.h>
42
43#include "Calculation/Calculation.h"
44#include "Utilities/KernelUtilities.h"
45
46namespace vf::gpu {
47
48constexpr void findCutLinks(bool* linkIsCut, const SubgridDistances27& subgridDistances, const uint nodeIndex)
49{
50 using namespace vf::basics::constant;
51 using namespace vf::lbm::dir;
52 forEachNonRestDirection([&](auto dir) {
53 const real subgridDistance = (subgridDistances.q[dir])[nodeIndex];
54 linkIsCut[dir] = subgridDistance >= c0o1 && subgridDistance <= c1o1;
55 });
56}
57
58constexpr void computeBouncedBackDistributionsBB(const SubgridDistances27& subgridDistances, const real* populations,
59 bool* linkIsCut, real* populationsBouncedBack, const uint nodeIndex)
60{
61 using namespace vf::basics::constant;
62 using namespace vf::lbm::dir;
63
64 findCutLinks(linkIsCut, subgridDistances, nodeIndex);
65
66 forEachNonRestDirection([&](auto dir) {
67 if (!linkIsCut[dir])
68 return;
69 const size_t inverseDirection = vf::lbm::dir::inverseDir<dir>();
70 populationsBouncedBack[inverseDirection] = populations[dir];
71 });
72}
73
74constexpr void computeBouncedBackDistributionsBBPressure(const SubgridDistances27& subgridDistances, const real drho,
75 const real* populations, bool* linkIsCut,
76 real* populationsBouncedBack, const uint nodeIndex)
77{
78 using namespace vf::lbm::dir;
79
80 findCutLinks(linkIsCut, subgridDistances, nodeIndex);
81
82 forEachNonRestDirection([&](auto dir) {
83 if (!linkIsCut[dir])
84 return;
85 const size_t inverseDirection = vf::lbm::dir::inverseDir<dir>();
86 const real weight = vf::lbm::dir::getWeight<dir>();
87 populationsBouncedBack[inverseDirection] = populations[dir] - weight * drho;
88 });
89}
90
91constexpr void computeBouncedBackDistributionsInterpolated(const SubgridDistances27& subgridDistances, real3 velocity, real drho,
92 real relaxationFrequency, const real* populations,
93 bool* linkIsCut, real* populationsBouncedBack, uint nodeIndex)
94{
95 using namespace vf::basics::constant;
96 using namespace vf::lbm::dir;
97 forEachNonRestDirection([&](auto dir) {
98 using namespace vf::lbm::dir;
99 const real subgridDistance = (subgridDistances.q[dir])[nodeIndex];
100 if (subgridDistance < c0o1 || subgridDistance > c1o1) {
101 linkIsCut[dir] = false;
102 return;
103 }
104
105 linkIsCut[dir] = true;
106 const real weight = getWeight<dir>();
107 const size_t inverseDirection = inverseDir<dir>();
108 const real cu = getVelocity<dir>(velocity.x, velocity.y, velocity.z);
109 const real cu_sq = c3o2 * square(velocity) * (c1o1 + drho);
110 const real feq = getEquilibriumForBC(drho, cu, cu_sq, weight);
111
112 const real populationBouncedBack = getInterpolatedDistributionForNoSlipWithPressureBC(
113 subgridDistance, populations[dir], populations[inverseDirection], feq, relaxationFrequency, drho, weight);
114
115 populationsBouncedBack[inverseDirection] = populationBouncedBack;
116 });
117}
118
119constexpr real3 computeWallMomentumBounceBack(const bool* linkIsCut, const real* populationsBouncedBack,
120 const real* populations)
121{
122 using namespace vf::lbm::dir;
123 real3 wallMomentum {};
124 forEachNonRestDirection([&](auto dir) {
125 if (!linkIsCut[dir])
126 return;
127 const size_t inverseDirection = inverseDir<dir>();
128 const real momentum = populations[dir] + populationsBouncedBack[inverseDirection];
129
130 wallMomentum.x += momentum * getComponentX<dir>();
131 wallMomentum.y += momentum * getComponentY<dir>();
132 wallMomentum.z += momentum * getComponentZ<dir>();
133 });
134
135 return wallMomentum;
136}
137
138inline __device__ real3 computeFakeWallVelocity(const real3 wallNormal, const real3 velocityForClipping,
139 const real3 wallShearStress, const real density,
140 const real interpolationFactor, const real wallArea,
141 const real3 wallMomentum)
142{
143 using namespace vf::basics::constant;
144
145 const real3 wallModelForce = wallShearStress * wallArea;
146 const real3 wallParallelMomentum = wallMomentum - wallNormal * dot(wallMomentum, wallNormal);
147
148 const real3 force = wallModelForce - wallParallelMomentum;
149
150 // Compute wall velocity and clip (clipping only necessary for initial boundary layer development)
151 constexpr real clipWallVelo = c2o1;
152
153 const real3 clipVelocity { std::abs(clipWallVelo * velocityForClipping.x),
154 std::abs(clipWallVelo * velocityForClipping.y),
155 std::abs(clipWallVelo * velocityForClipping.z) };
156
157 return { std::clamp(-c3o1 * force.x * interpolationFactor / density, -clipVelocity.x, clipVelocity.x),
158 std::clamp(-c3o1 * force.y * interpolationFactor / density, -clipVelocity.y, clipVelocity.y),
159 std::clamp(-c1o1 * force.z * interpolationFactor / density, -clipVelocity.z, clipVelocity.z) };
160}
161
162constexpr real3 writeDistributionsBB(const Distributions27& populationReferences, const bool* linkIsCut,
163 const real* populationsBouncedBack, const real3 velocity, const real density,
164 const ListIndices& listIndices)
165{
166 using namespace vf::basics::constant;
167 using namespace vf::lbm::dir;
168
169 real3 wallMomentumAdded {};
170
171 forEachNonRestDirection([&](auto dir) {
172 if (!linkIsCut[dir])
173 return;
174 const size_t inverseDirection = inverseDir<dir>();
175 const real addedMomentum = -c6o1 * density * getWeight<dir>() * getVelocity<dir>(velocity.x, velocity.y, velocity.z);
176 const real population = populationsBouncedBack[inverseDirection] + addedMomentum;
177 writeInInverseDirection<dir>(population, listIndices, populationReferences);
178 wallMomentumAdded.x += addedMomentum * getComponentX<dir>();
179 wallMomentumAdded.y += addedMomentum * getComponentY<dir>();
180 wallMomentumAdded.z += addedMomentum * getComponentZ<dir>();
181 });
182 return wallMomentumAdded;
183}
184
185constexpr real3 writeDistributionsInterpolatedBB(const Distributions27& populationReferences, const bool* linkIsCut,
186 const real* populationsBouncedBack, const real3 velocity,
187 const real density, const SubgridDistances27& subgridDistances,
188 const ListIndices& listIndices, const uint nodeIndex)
189{
190 using namespace vf::basics::constant;
191 using namespace vf::lbm::dir;
192
193 real3 wallMomentumAdded {};
194
195 forEachNonRestDirection([&](auto dir) {
196 if (!linkIsCut[dir])
197 return;
198 const size_t inverseDirection = inverseDir<dir>();
199 const real microVelocity = getVelocity<dir>(velocity.x, velocity.y, velocity.z);
200 const real addedMomentum = -c6o1 * density * getWeight<dir>() * microVelocity / subgridDistances.q[dir][nodeIndex];
201 writeInInverseDirection<dir>(populationsBouncedBack[inverseDirection] + addedMomentum, listIndices,
202 populationReferences);
203
204 wallMomentumAdded.x += addedMomentum * getComponentX<dir>();
205 wallMomentumAdded.y += addedMomentum * getComponentY<dir>();
206 wallMomentumAdded.z += addedMomentum * getComponentZ<dir>();
207 });
208 return wallMomentumAdded;
209}
210
211}
212
213#endif