OpenLB 1.8.1
Loading...
Searching...
No Matches
momentumExchangeForce.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2021 Nicolas Hafen, Mathias J. Krause
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24
25
26#ifndef MOMENTUM_EXCHANGE_FORCE_H
27#define MOMENTUM_EXCHANGE_FORCE_H
28#ifndef M_PI
29#define M_PI 3.14159265358979323846
30#endif
31
32namespace olb {
33
34namespace particles {
35
36namespace resolved {
37
38
39template<typename T, unsigned D, bool useLadd=false>
41template<typename T>
42//Momentum Exchange Wen2014
44 static constexpr T calculate( T f1, T f2, T c, T pVel, T deltaR )
45 {
46 return (f1*(c-pVel) + f2*(c+pVel))*(1./deltaR) ;
47 }
48};
49template<typename T>
51 static constexpr T calculate( T f1, T f2, T c, T pVel, T deltaR )
52 {
53 return (f1*(c-pVel) + f2*(c+pVel));
54 }
55};
56//Momentum Exchange Ladd1994
57template<typename T>
59 static constexpr T calculate( T f1, T f2, T c, T pVel, T deltaR )
60 {
61 return ((f1 + f2)*c)*(1./deltaR) ;
62 }
63};
64template<typename T>
66 static constexpr T calculate( T f1, T f2, T c, T pVel, T deltaR )
67 {
68 return ((f1 + f2)*c);
69 }
70};
71
72
73
74//Evaluate local momentum exchange contribution and return whether particle and bulk found
75template<typename T, typename DESCRIPTOR, typename PARTICLETYPE>
77 T momentumExchange[],
79 const LatticeR<DESCRIPTOR::d>& latticeRinner,
80 const BlockGeometry<T,DESCRIPTOR::d>& blockGeometry,
81 BlockLattice<T,DESCRIPTOR>& blockLattice,
82 const UnitConverter<T,DESCRIPTOR>& converter,
84 const int bulkMaterial = 1
85)
86{
87
88 using namespace descriptors;
89 constexpr unsigned D = DESCRIPTOR::d;
90 auto position = particles::access::getPosition(particle);
91
92 //Retrieve grid spacing
93 const T deltaR = blockGeometry.getDeltaR();
94 //Get inner phys position
95 T physRinner[D] = { };
96 Vector<T,D> physRV;
97 blockGeometry.getPhysR(physRV, latticeRinner);
98 for (unsigned iD = 0; iD < D; ++iD) {
99 physRinner[iD] = physRV[iD];
100 }
101 //Retrieve inner porosity
102 T porosityInner[1] = { };
103 particles::resolved::evalSolidVolumeFraction(porosityInner, physRinner, particle);
104 //Check whether particle and bulk is existent at location
105 if ( !util::nearZero(porosityInner[0]) && blockGeometry.get(latticeRinner)==bulkMaterial ) {
106 //Loop over distribution functions
107 for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
108 //Calculate outer lattice position (get next cell located in current direction)
110 const LatticeR<D> latticeRouter = latticeRinner + c;
111 //Retrieve outer phys position
112 T physRouter[D] = {0.};
113 Vector<T,D> physRouterV;
114 blockGeometry.getPhysR(physRouterV, latticeRouter);
115 for (unsigned iD = 0; iD < D; ++iD) {
116 physRouter[iD] = physRouterV[iD];
117 }
118 //Retrieve outer porosity
119 T porosityOuter[1] = {0.};
120 particles::resolved::evalSolidVolumeFraction(porosityOuter, physRouter, particle);
121 //if not both cells are in the full solid domain calculate force
122 if ( !(porosityInner[0]==1 && porosityOuter[0]==1) ) {
123 //Momentum Exchange Wen
124 const T f1 = blockLattice.get( latticeRouter )[iPop];
125 const T f2 = blockLattice.get( latticeRinner )[descriptors::opposite<DESCRIPTOR>(iPop)];
126 T pVel[D] = {0.};
127 for (unsigned iDim=0; iDim<D; ++iDim) {
128 pVel[iDim] = converter.getLatticeVelocity(particles::dynamics::calculateLocalVelocity(particle, PhysR<T,D>(physRinner))[iDim]);
129 momentumExchange[iDim] -= converter.getPhysForce(
130 population_momentum_exchange<T,D>::calculate( f1, f2, c[iDim], pVel[iDim], deltaR ) );
131 }
132
133 // Optional correction of the lubrication force
135 auto contact = particle.template getField<NUMERICPROPERTIES,IS_IN_CONTACT>();
136
137 if (contact == 1) {
138 T vn = 0.0;
139 for (unsigned iDim=0; iDim<D; ++iDim) {
140 //std::cout << momentumExchange[iDim];
141 vn = vn + util::pow(momentumExchange[iDim],2);
142 }
143
144 vn = util::sqrt(vn);
145
146 auto cell = blockLattice.get(latticeRinner);
147 Vector<T,DESCRIPTOR::d> localLatticeFluidVelocity;
148 Vector<T,DESCRIPTOR::d> localPhysicalFluidVelocity;
149 cell.computeU(localLatticeFluidVelocity.data());
150
151 for(unsigned iD=0; iD<D; ++iD) {
152 localPhysicalFluidVelocity[iD] = converter.getPhysVelocity(localLatticeFluidVelocity[iD]);
153 }
154
155 T U = 0.0;
156 for (unsigned iDim=0; iDim<D; ++iDim) {
157 U = U + util::pow(pVel[iDim]-localLatticeFluidVelocity[iDim],2.0);
158 }
159 U = util::sqrt(U);
160
161
162 T deltaT = converter.getPhysDeltaT();
163 T deltaTLattice = converter.getLatticeTime(deltaT);
164 T rho_fluid = converter.getPhysDensity();
165
166 T factor = 1.0;
167
168 T maxForce = converter.getPhysForce(U * converter.getLatticeDensity(rho_fluid)/deltaTLattice)*factor;
169
170 if (util::fabs(vn) == 0){
171 vn = 0.5 * maxForce;
172 }
173 if (util::fabs(vn) > util::fabs(maxForce)) {
174 T mp = maxForce/vn;
175 for (unsigned iDim=0; iDim<D; ++iDim) {
176 //Set the force to the maximal force
177 momentumExchange[iDim] *= mp;
178 }
179 }
180 }
181 }
182 }
183
184 }
185 //Calculate lever (necessary for torque calculation)
186 lever = PhysR<T,D>(physRinner)-position;
187 return true;
188 }
189 else {
190 return false;
191 }
192}
193
194
195
196
197
198
199} //namespace resolved
200
201} //namespace particles
202
203} //namespace olb
204
205#endif
Representation of a block geometry.
Vector< T, D > getPhysR(LatticeR< D > latticeR) const
T getDeltaR() const
Read only access to the voxel size given in SI units (meter)
std::enable_if_t< sizeof...(L)==D, int > get(L... latticeR) const
Read-only access to a material number.
Conversion between physical and lattice units, as well as discretization.
constexpr T getPhysDensity() const
return density in physical units
constexpr T getLatticeDensity(T physDensity) const
conversion from physical to lattice density
constexpr size_t getLatticeTime(T physTime) const
conversion from physical to lattice time
constexpr T getPhysVelocity(T latticeVelocity) const
conversion from lattice to physical velocity
constexpr T getLatticeVelocity(T physVelocity) const
conversion from physical to lattice velocity
constexpr T getPhysDeltaT() const
returns time spacing (timestep length) in s
constexpr T getPhysForce(T latticeForce) const
conversion from lattice to physical force
constexpr const T * data() const any_platform
Definition vector.h:172
constexpr int c(unsigned iPop, unsigned iDim) any_platform
Definition functions.h:83
constexpr int opposite(unsigned iPop) any_platform
Definition functions.h:95
constexpr bool providesIsInContact()
Vector< T, PARTICLETYPE::d > getPosition(Particle< T, PARTICLETYPE > particle)
constexpr Vector< T, PARTICLETYPE::d > calculateLocalVelocity(Particle< T, PARTICLETYPE > &particle, const PhysR< T, PARTICLETYPE::d > &input)
bool momentumExchangeAtSurfaceLocation(T momentumExchange[], PhysR< T, DESCRIPTOR::d > &lever, const LatticeR< DESCRIPTOR::d > &latticeRinner, const BlockGeometry< T, DESCRIPTOR::d > &blockGeometry, BlockLattice< T, DESCRIPTOR > &blockLattice, const UnitConverter< T, DESCRIPTOR > &converter, Particle< T, PARTICLETYPE > &particle, const int bulkMaterial=1)
bool evalSolidVolumeFraction(T output[], const S input[], Particle< T, PARTICLETYPE > &particle)
Expr sqrt(Expr x)
Definition expr.cpp:225
Expr pow(Expr base, Expr exp)
Definition expr.cpp:235
Expr fabs(Expr x)
Definition expr.cpp:230
bool nearZero(T a) any_platform
return true if a is close to zero
Definition util.h:402
Top level namespace for all of OpenLB.
Vector< T, D > PhysR
Type for spatial (physical) coordinates.
static constexpr T calculate(T f1, T f2, T c, T pVel, T deltaR)
static constexpr T calculate(T f1, T f2, T c, T pVel, T deltaR)
static constexpr T calculate(T f1, T f2, T c, T pVel, T deltaR)
static constexpr T calculate(T f1, T f2, T c, T pVel, T deltaR)