OpenLB 1.7
Loading...
Searching...
No Matches
smoothingFunctionals3D.hh
Go to the documentation of this file.
1/* Lattice Boltzmann sample, written in C++, using the OpenLB
2 * library
3 *
4 * Copyright (C) 2019 Davide Dapelo
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/* Smoothings functionals for Lagrangian two-way coupling methods -- generic implementation.
26 */
27
28#ifndef LB_SMOOTHING_FUNCTIONALS_3D_HH
29#define LB_SMOOTHING_FUNCTIONALS_3D_HH
30
31namespace olb {
32
34
35template<typename T, typename Lattice>
37 T kernelLength, UnitConverter<T, Lattice>& converter, SuperLattice<T, Lattice>& sLattice, int nVoxelInterpPoints )
38 : _kernelLength(kernelLength),
39 _converter(converter),
40 _sLattice(sLattice),
41 _nVoxelInterpPoints(nVoxelInterpPoints)
42{
43 if (2.0*_kernelLength < converter.getPhysDeltaX()) {
44 throw std::out_of_range("2 * SmoothingFunctional::_kernelLength must be >= converter::getPhysDeltaX().");
45 }
46 if (_nVoxelInterpPoints < 2) {
47 throw std::out_of_range("SmoothingFunctional::_nVoxelInterpPoints must be >=2.");
48 }
49}
50
51template<typename T, typename Lattice>
52bool SmoothingFunctional<T, Lattice>::update(T physPosP[], int globic)
53{
54 // Bottom-left corner of a cube centered at the particle, with side 2*_kernelLength
55 T physPosMin[3] = {T(), T(), T()};
56 physPosMin[0] = physPosP[0] - _kernelLength;
57 physPosMin[1] = physPosP[1] - _kernelLength;
58 physPosMin[2] = physPosP[2] - _kernelLength;
59 int latticePosMin[3] = {0, 0, 0};
60 this->_sLattice.getCuboidGeometry().get(globic).getLatticeR (
61 latticePosMin, physPosMin );
62
63 // Top-right corner of a cube centered at the particle, with side 2*_kernelLength
64 T physPosMax[3] = {T(), T(), T()};
65 physPosMax[0] = physPosP[0] + _kernelLength;
66 physPosMax[1] = physPosP[1] + _kernelLength;
67 physPosMax[2] = physPosP[2] + _kernelLength;
68 int latticePosMax[3] = {0, 0, 0};
69 this->_sLattice.getCuboidGeometry().get(globic).getLatticeR (
70 latticePosMax, physPosMax );
71
72 // Clearing the _latticePosAndWeight list
73 _latticePosAndWeight.clear();
74
75 T normalizer = T();
76 int iLatticePos[3] = {0, 0, 0};
77 // Cycling all the cells on a cube containing a sphee centered in bubble's position and with kernel smoothing length as radius
78 for (iLatticePos[0]=latticePosMin[0]; iLatticePos[0]<=latticePosMax[0]; iLatticePos[0]++) {
79 for (iLatticePos[1]=latticePosMin[1]; iLatticePos[1]<=latticePosMax[1]; iLatticePos[1]++) {
80 for (iLatticePos[2]=latticePosMin[2]; iLatticePos[2]<=latticePosMax[2]; iLatticePos[2]++) {
81
82 T iPhysPos[3] = {T(), T(), T()};
83 this->_sLattice.getCuboidGeometry().get(globic).getPhysR (
84 iPhysPos, iLatticePos );
85
86 // Is the voxel within a smooting kernel length from the bubble's position?
87 if ( util::pow(physPosP[0] - iPhysPos[0], 2) +
88 util::pow(physPosP[1] - iPhysPos[1], 2) +
89 util::pow(physPosP[2] - iPhysPos[2], 2) < util::pow(_kernelLength, 2) ) {
90
91 // Adding the voxel's position (and relative weight) to the _latticePosAndWeight list
93 item.latticePos[0] = iLatticePos[0];
94 item.latticePos[1] = iLatticePos[1];
95 item.latticePos[2] = iLatticePos[2];
96 item.weight = this->compute(physPosP, iPhysPos);
97
98 normalizer += item.weight;
99 _latticePosAndWeight.push_back(item);
100 }
101 }
102 }
103 }
104
105 // If normalizer is zero, then no voxels are within a kernel smoothing length from the bubble's location.
106 // And it is a problem.
107 if (normalizer == T()) {
108 std::cout << "ERROR: SmoothingFunctional::update(...):" << std::endl
109 << "[smoothingFunctional] physPosP: "
110 << physPosP[0] << " "
111 << physPosP[1] << " "
112 << physPosP[2] << std::endl
113 << "[smoothingFunctional] physPosMin: "
114 << physPosMin[0] << " "
115 << physPosMin[1] << " "
116 << physPosMin[2] << std::endl
117 << "[smoothingFunctional] physPosMax: "
118 << latticePosMax[0] << " "
119 << latticePosMax[1] << " "
120 << latticePosMax[2] << std::endl
121 << "[smoothingFunctional] normalizer: "
122 << normalizer << std::endl;
123 return false;
124 }
125
126 // Normalizing to one
127 for (auto&& i : _latticePosAndWeight) {
128 i.weight /= normalizer;
129 }
130 return true;
131}
132
134
135template<typename T, typename Lattice>
137 T kernelLength, UnitConverter<T, Lattice>& converter, SuperLattice<T, Lattice>& sLattice, int nVoxelInterpPoints )
138 : SmoothingFunctional<T, Lattice>(kernelLength, converter, sLattice, nVoxelInterpPoints)
139{}
140
141template<typename T, typename Lattice>
143{
144 return this->smoothingFunction ( util::sqrt (
145 util::pow(physPosP[0] - physPosL[0], 2) +
146 util::pow(physPosP[1] - physPosL[1], 2) +
147 util::pow(physPosP[2] - physPosL[2], 2) ) );
148}
149
150
152
153template<typename T, typename Lattice>
155 T kernelLength, UnitConverter<T, Lattice>& converter, SuperLattice<T, Lattice>& sLattice, int nVoxelInterpPoints )
156 : SmoothingFunctional<T, Lattice>(kernelLength, converter, sLattice, nVoxelInterpPoints)
157{}
158
159template<typename T, typename Lattice>
161{
162 return this->smoothingFunction(physPosP[0] - physPosL[0])
163 * this->smoothingFunction(physPosP[1] - physPosL[1])
164 * this->smoothingFunction(physPosP[2] - physPosL[2]);
165}
166
167
169
170template<typename T, typename Lattice>
172 T kernelLength, UnitConverter<T, Lattice>& converter, SuperLattice<T, Lattice>& sLattice )
173 : LinearAveragingSmoothingFunctional<T, Lattice>(kernelLength, converter, sLattice)
174{}
175
176template<typename T, typename Lattice>
178{
179 return ( util::pow(delta, 4)/util::pow(this->_kernelLength, 5)
180 - 2.*util::pow(delta, 2)/util::pow(this->_kernelLength, 3)
181 + 1./this->_kernelLength
182 );
183}
184
185
187
188template<typename T, typename Lattice>
190 T kernelLength, UnitConverter<T, Lattice>& converter, SuperLattice<T, Lattice>& sLattice, T radius, int nVoxelInterpPoints )
191 : LinearAveragingSmoothingFunctional<T, Lattice>(kernelLength, converter, sLattice, nVoxelInterpPoints),
192 _radius(radius)
193{}
194
195template<typename T, typename Lattice>
197{
198 if ( ! SmoothingFunctional<T, Lattice>::update(physPosP, globic) ) {
199 return false;
200 }
201
202 updateContinuousPhaseFraction(physPosP, globic);
203
204 return true;
205}
206
207template<typename T, typename Lattice>
209{
210 T x = delta / this->_kernelLength;
211 return (4.0 * x + 1.0) * util::pow(1.0 - x, 4);
212}
213
214template<typename T, typename Lattice>
216{
217 for (auto&& i : this->_latticePosAndWeight) {
218 T iPhysPos[3] = {T(), T(), T()};
219 this->_sLattice.getCuboidGeometry().get(globic).getPhysR (
220 iPhysPos, i.latticePos );
221
222 T iExtremaMin[3] = {T(), T(), T()};
223 iExtremaMin[0] = util::max( physPosP[0] - this->_kernelLength, iPhysPos[0] - 0.5 *this->_converter.getPhysDeltaX() );
224 iExtremaMin[1] = util::max( physPosP[1] - this->_kernelLength, iPhysPos[1] - 0.5 *this->_converter.getPhysDeltaX() );
225 iExtremaMin[2] = util::max( physPosP[2] - this->_kernelLength, iPhysPos[2] - 0.5 *this->_converter.getPhysDeltaX() );
226
227 T iExtremaMax[3] = {T(), T(), T()};
228 iExtremaMax[0] = util::min( physPosP[0] + this->_kernelLength, iPhysPos[0] + 0.5 *this->_converter.getPhysDeltaX() );
229 iExtremaMax[1] = util::min( physPosP[1] + this->_kernelLength, iPhysPos[1] + 0.5 *this->_converter.getPhysDeltaX() );
230 iExtremaMax[2] = util::min( physPosP[2] + this->_kernelLength, iPhysPos[2] + 0.5 *this->_converter.getPhysDeltaX() );
231
232 T discretePhaseFraction = T();
233 for (int nx=1; nx<=this->_nVoxelInterpPoints; nx++) {
234 for (int ny=1; ny<=this->_nVoxelInterpPoints; ny++) {
235 for (int nz=1; nz<=this->_nVoxelInterpPoints; nz++) {
236 T physPosNm[3] = {T(), T(), T()};
237 physPosNm[0] = iExtremaMin[0] + nx * (iExtremaMax[0] - iExtremaMin[0]) / ((T) this->_nVoxelInterpPoints + 1.0);
238 physPosNm[1] = iExtremaMin[1] + ny * (iExtremaMax[1] - iExtremaMin[1]) / ((T) this->_nVoxelInterpPoints + 1.0);
239 physPosNm[2] = iExtremaMin[2] + nz * (iExtremaMax[2] - iExtremaMin[2]) / ((T) this->_nVoxelInterpPoints + 1.0);
240
241 discretePhaseFraction += ( util::pow(physPosNm[0] - physPosP[0], 2)
242 + util::pow(physPosNm[1] - physPosP[1], 2)
243 + util::pow(physPosNm[2] - physPosP[2], 2)
244 <= util::pow(this->_radius, 2)
245 ) ? 0.5 : 0.0;
246
247 T physPosNp[3] = {T(), T(), T()};
248 physPosNp[0] = iExtremaMin[0] + (nx - 1.0) * (iExtremaMax[0] - iExtremaMin[0]) / ((T) this->_nVoxelInterpPoints - 1.0);
249 physPosNp[1] = iExtremaMin[1] + (ny - 1.0) * (iExtremaMax[1] - iExtremaMin[1]) / ((T) this->_nVoxelInterpPoints - 1.0);
250 physPosNp[2] = iExtremaMin[2] + (nz - 1.0) * (iExtremaMax[2] - iExtremaMin[2]) / ((T) this->_nVoxelInterpPoints - 1.0);
251
252 discretePhaseFraction += ( util::pow(physPosNp[0] - physPosP[0], 2)
253 + util::pow(physPosNp[1] - physPosP[1], 2)
254 + util::pow(physPosNp[2] - physPosP[2], 2)
255 <= util::pow(this->_radius, 2)
256 ) ? 0.5 : 0.0;
257 }
258 }
259 }
260
261 discretePhaseFraction *= (iExtremaMax[0]-iExtremaMin[0]) * (iExtremaMax[1]-iExtremaMin[1]) * (iExtremaMax[2]-iExtremaMin[2])
262 / util::pow(this->_nVoxelInterpPoints * this->_converter.getPhysDeltaX(), 3);
263
264 i.continuousPhaseFraction = 1.0 - discretePhaseFraction;
265 }
266}
267
268
270
271template<typename T, typename Lattice>
273 T kernelLength, UnitConverter<T, Lattice>& converter, SuperLattice<T, Lattice>& sLattice )
274 : VolumeAveragingSmoothingFunctional<T, Lattice>(kernelLength, converter, sLattice)
275{}
276
277template<typename T, typename Lattice>
282
283
284}
285
286#endif
DeenSmoothingFunctional(T kernelLength, UnitConverter< T, Lattice > &converter, SuperLattice< T, Lattice > &sLattice)
Constructor.
virtual T smoothingFunction(T delta) override
The actual smoothing function.
Abstact class for all the linear-averaging smoothing functionals.
LinearAveragingSmoothingFunctional(T kernelLength, UnitConverter< T, Lattice > &converter, SuperLattice< T, Lattice > &sLattice, int nVoxelInterpPoints=2)
Constructor.
virtual T compute(T physPosP[], T physPosL[]) override
Returns the weight for smoothing.
Abstact class for all the smoothing functionals.
SmoothingFunctional(T kernelLength, UnitConverter< T, Lattice > &converter, SuperLattice< T, Lattice > &sLattice, int nVoxelInterpPoints=2)
Constructor.
virtual bool update(T physPosP[], int globic)
StepSmoothingFunctional(T kernelLength, UnitConverter< T, Lattice > &converter, SuperLattice< T, Lattice > &sLattice)
Constructor.
virtual T smoothingFunction(T delta) override
The actual smoothing function.
Super class maintaining block lattices for a cuboid decomposition.
Conversion between physical and lattice units, as well as discretization.
constexpr T getPhysDeltaX() const
returns grid spacing (voxel length) in m
Abstact class for all the volume-averaging smoothing functionals.
VolumeAveragingSmoothingFunctional(T kernelLength, UnitConverter< T, Lattice > &converter, SuperLattice< T, Lattice > &sLattice, int nVoxelInterpPoints=2)
Constructor.
virtual T compute(T physPosP[], T physPosL[]) override
Returns the weight for smoothing.
void updateContinuousPhaseFraction(T physPosP[], int globic)
Updates _latticePosAndWeight with contribution from continuous phase fraction. To be called AFTER com...
virtual T smoothingFunction(T delta) override
The actual smoothing function.
vanWachemSmoothingFunctional(T kernelLength, UnitConverter< T, Lattice > &converter, SuperLattice< T, Lattice > &sLattice, T radius, int nVoxelInterpPoints)
Constructor.
virtual bool update(T physPosP[], int globic) override
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
cpu::simd::Pack< T > min(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:124
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:130
cpu::simd::Pack< T > pow(cpu::simd::Pack< T > base, cpu::simd::Pack< T > exp)
Definition pack.h:112
Top level namespace for all of OpenLB.
Data structure for smoothing functionals.