1//=======================================================================================
2// ____ ____ __ ______ __________ __ __ __ __
3// \ \ | | | | | _ \ |___ ___| | | | | / \ | |
4// \ \ | | | | | |_) | | | | | | | / \ | |
5// \ \ | | | | | _ / | | | | | | / /\ \ | |
6// \ \ | | | | | | \ \ | | | \__/ | / ____ \ | |____
7// \ \ | | |__| |__| \__\ |__| \________/ /__/ \__\ |_______|
8// \ \ | | ________________________________________________________________
9// \ \ | | | ______________________________________________________________|
10// \ \| | | | __ __ __ __ ______ _______
11// \ | | |_____ | | | | | | | | | _ \ / _____)
12// \ | | _____| | | | | | | | | | | \ \ \_______
13// \ | | | | |_____ | \_/ | | | | |_/ / _____ |
14// \ _____| |__| |________| \_______/ |__| |______/ (_______/
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.
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
26// SPDX-License-Identifier: GPL-3.0-or-later
27// SPDX-FileCopyrightText: Copyright © VirtualFluids Project contributors, see AUTHORS.md in root folder
30//=======================================================================================
31#ifndef StressFunctions_H
32#define StressFunctions_H
35#include <cuda_runtime.h>
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>
43#include "Calculation/Calculation.h"
44#include "Utilities/KernelUtilities.h"
48constexpr void findCutLinks(bool* linkIsCut, const SubgridDistances27& subgridDistances, const uint nodeIndex)
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;
58constexpr void computeBouncedBackDistributionsBB(const SubgridDistances27& subgridDistances, const real* populations,
59 bool* linkIsCut, real* populationsBouncedBack, const uint nodeIndex)
61 using namespace vf::basics::constant;
62 using namespace vf::lbm::dir;
64 findCutLinks(linkIsCut, subgridDistances, nodeIndex);
66 forEachNonRestDirection([&](auto dir) {
69 const size_t inverseDirection = vf::lbm::dir::inverseDir<dir>();
70 populationsBouncedBack[inverseDirection] = populations[dir];
74constexpr void computeBouncedBackDistributionsBBPressure(const SubgridDistances27& subgridDistances, const real drho,
75 const real* populations, bool* linkIsCut,
76 real* populationsBouncedBack, const uint nodeIndex)
78 using namespace vf::lbm::dir;
80 findCutLinks(linkIsCut, subgridDistances, nodeIndex);
82 forEachNonRestDirection([&](auto dir) {
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;
91constexpr void computeBouncedBackDistributionsInterpolated(const SubgridDistances27& subgridDistances, real3 velocity, real drho,
92 real relaxationFrequency, const real* populations,
93 bool* linkIsCut, real* populationsBouncedBack, uint nodeIndex)
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;
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);
112 const real populationBouncedBack = getInterpolatedDistributionForNoSlipWithPressureBC(
113 subgridDistance, populations[dir], populations[inverseDirection], feq, relaxationFrequency, drho, weight);
115 populationsBouncedBack[inverseDirection] = populationBouncedBack;
119constexpr real3 computeWallMomentumBounceBack(const bool* linkIsCut, const real* populationsBouncedBack,
120 const real* populations)
122 using namespace vf::lbm::dir;
123 real3 wallMomentum {};
124 forEachNonRestDirection([&](auto dir) {
127 const size_t inverseDirection = inverseDir<dir>();
128 const real momentum = populations[dir] + populationsBouncedBack[inverseDirection];
130 wallMomentum.x += momentum * getComponentX<dir>();
131 wallMomentum.y += momentum * getComponentY<dir>();
132 wallMomentum.z += momentum * getComponentZ<dir>();
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)
143 using namespace vf::basics::constant;
145 const real3 wallModelForce = wallShearStress * wallArea;
146 const real3 wallParallelMomentum = wallMomentum - wallNormal * dot(wallMomentum, wallNormal);
148 const real3 force = wallModelForce - wallParallelMomentum;
150 // Compute wall velocity and clip (clipping only necessary for initial boundary layer development)
151 constexpr real clipWallVelo = c2o1;
153 const real3 clipVelocity { std::abs(clipWallVelo * velocityForClipping.x),
154 std::abs(clipWallVelo * velocityForClipping.y),
155 std::abs(clipWallVelo * velocityForClipping.z) };
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) };
162constexpr real3 writeDistributionsBB(const Distributions27& populationReferences, const bool* linkIsCut,
163 const real* populationsBouncedBack, const real3 velocity, const real density,
164 const ListIndices& listIndices)
166 using namespace vf::basics::constant;
167 using namespace vf::lbm::dir;
169 real3 wallMomentumAdded {};
171 forEachNonRestDirection([&](auto dir) {
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>();
182 return wallMomentumAdded;
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)
190 using namespace vf::basics::constant;
191 using namespace vf::lbm::dir;
193 real3 wallMomentumAdded {};
195 forEachNonRestDirection([&](auto dir) {
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);
204 wallMomentumAdded.x += addedMomentum * getComponentX<dir>();
205 wallMomentumAdded.y += addedMomentum * getComponentY<dir>();
206 wallMomentumAdded.z += addedMomentum * getComponentZ<dir>();
208 return wallMomentumAdded;