OpenLB 1.7
Loading...
Searching...
No Matches
navierStokesAdvectionDiffusionCoupling.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2022 Adrian Kummerlaender
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#ifndef NAVIER_STOKES_ADVECTION_DIFFUSION_COUPLING_H
25#define NAVIER_STOKES_ADVECTION_DIFFUSION_COUPLING_H
26
27#include "core/operator.h"
28
29namespace olb {
30
34
35 struct FORCE_PREFACTOR : public descriptors::FIELD_BASE<0,1> { };
36 struct T0 : public descriptors::FIELD_BASE<1> { };
37
38 struct CP_S : public descriptors::FIELD_BASE<1> { };
39 struct CP_L : public descriptors::FIELD_BASE<1> { };
40 struct T_S : public descriptors::FIELD_BASE<1> { };
41 struct T_L : public descriptors::FIELD_BASE<1> { };
42 struct L : public descriptors::FIELD_BASE<1> { };
43 // V H_s = cp_s * T_s;
44 // V H_l = cp_l * T_l + l;
45
46
48
49 template <typename CELLS, typename PARAMETERS>
50 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
51 {
52 using V = typename CELLS::template value_t<names::NavierStokes>::value_t;
53 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
54
55 auto& cellNSE = cells.template get<names::NavierStokes>();
56 auto& cellADE = cells.template get<names::Temperature>();
57
58 V enthalpy = cellADE.computeRho();
59 auto& dynamics = cellADE.getDynamics();
60 /*auto& dynParams = static_cast<ParametersOfDynamicsD<DYNAMICS>&>(
61 tPartner->template getData<OperatorParameters<DYNAMICS>>());*/
62
63 //cellNSE.template setField<descriptors::POROSITY>(
64 //dynamics->template computeLiquidFraction<T>(parameters, enthalpy)
65 //);
66
67 auto temperature = cellADE.template getFieldPointer<descriptors::TEMPERATURE>();
68 //temperature[0] = dynamics->computeTemperature<V, parameters, enthalpy>();
69
70 // computation of the bousinessq force
71 auto force = cellNSE.template getFieldPointer<descriptors::FORCE>();
72 auto forcePrefactor = parameters.template get<FORCE_PREFACTOR>();
73 V temperatureDifference = cellADE.computeRho() - parameters.template get<T0>();
74 for (unsigned iD = 0; iD < DESCRIPTOR::d; ++iD) {
75 force[iD] = forcePrefactor[iD] * temperatureDifference;
76 }
77 // Velocity coupling
78 V u[DESCRIPTOR::d] { };
79 cellNSE.computeU(u);
80 cellADE.template setField<descriptors::VELOCITY>(u);
81 }
82
83};
84
85
86
90
91 struct FORCE_PREFACTOR : public descriptors::FIELD_BASE<0,1> { };
92 struct T0 : public descriptors::FIELD_BASE<1> { };
93
95
96 template <typename CELLS, typename PARAMETERS>
97 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
98 {
99 using V = typename CELLS::template value_t<names::NavierStokes>::value_t;
100 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
101
102 auto& cellNSE = cells.template get<names::NavierStokes>();
103 auto& cellADE = cells.template get<names::Temperature>();
104
105 // computation of the bousinessq force
106 auto force = cellNSE.template getFieldPointer<descriptors::FORCE>();
107 auto forcePrefactor = parameters.template get<FORCE_PREFACTOR>();
108 V temperatureDifference = cellADE.computeRho() - parameters.template get<T0>();
109 for (unsigned iD = 0; iD < DESCRIPTOR::d; ++iD) {
110 force[iD] = forcePrefactor[iD] * temperatureDifference;
111 }
112
113 // Velocity coupling
114 V u[DESCRIPTOR::d] { };
115 cellNSE.computeU(u);
116 cellADE.template setField<descriptors::VELOCITY>(u);
117 }
118};
119
123
125
126 template <typename CELLS, typename PARAMETERS>
127 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
128 {
129 using V = typename CELLS::template value_t<names::NavierStokes>::value_t;
130 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
131
132 auto& cellNSE = cells.template get<names::NavierStokes>();
133 auto& cellADE = cells.template get<names::Concentration0>();
134
135 // Velocity coupling
136 V u[DESCRIPTOR::d] { };
137 cellNSE.computeU(u);
138 cellADE.template setField<descriptors::VELOCITY>(u);
139 }
140};
141
145
146 struct FORCE_PREFACTOR : public descriptors::FIELD_BASE<0,1> { };
148 struct PR_TURB : public descriptors::FIELD_BASE<1> { };
149 struct T0 : public descriptors::FIELD_BASE<1> { };
150 struct OMEGA_NSE : public descriptors::FIELD_BASE<1> { };
151 struct OMEGA_ADE : public descriptors::FIELD_BASE<1> { };
152
154
155 template <typename CELLS, typename PARAMETERS>
156 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
157 {
158 using V = typename CELLS::template value_t<names::NavierStokes>::value_t;
159 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
160 using DESCRIPTOR_ADE = typename CELLS::template value_t<names::Temperature>::descriptor_t;
161
162 auto& cellNSE = cells.template get<names::NavierStokes>();
163 auto& cellADE = cells.template get<names::Temperature>();
164
165 // computation of the bousinessq force
166 auto force = cellNSE.template getFieldPointer<descriptors::FORCE>();
167 auto forcePrefactor = parameters.template get<FORCE_PREFACTOR>();
168 V temperatureDifference = cellADE.computeRho() - parameters.template get<T0>();
169
170 for (unsigned iD=0; iD < DESCRIPTOR::d; ++iD) {
171 force[iD] = forcePrefactor[iD] * temperatureDifference;
172 }
173
174 // Velocity coupling
175 auto u = cellADE.template getField<descriptors::VELOCITY>();
176 // tau coupling
177 auto tauNS = cellNSE.template getFieldPointer<descriptors::TAU_EFF>();
178 auto tauAD = cellADE.template getFieldPointer<descriptors::TAU_EFF>();
179
180 V rho, pi[util::TensorVal<DESCRIPTOR>::n] { };
181 cellNSE.computeAllMomenta(rho, u.data(), pi);
182 cellADE.template setField<descriptors::VELOCITY>(u);
183 V PiNeqNormSqr = pi[0]*pi[0] + 2.0*pi[1]*pi[1] + pi[2]*pi[2];
184 if constexpr (util::TensorVal<DESCRIPTOR>::n == 6) {
185 PiNeqNormSqr += pi[2]*pi[2] + pi[3]*pi[3] + 2*pi[4]*pi[4] +pi[5]*pi[5];
186 }
187 V PiNeqNorm = util::sqrt(PiNeqNormSqr);
189 V tau_mol_NS = V{1} / parameters.template get<OMEGA_NSE>();
190 V tau_mol_AD = V{1} / parameters.template get<OMEGA_ADE>();
192 V smagoPrefactor = parameters.template get<SMAGORINSKY_PREFACTOR>();
193 V tau_turb_NS = V{0.5}*(util::sqrt(tau_mol_NS*tau_mol_NS + smagoPrefactor/rho*PiNeqNorm) - tau_mol_NS);
195 tauNS[0] = tau_mol_NS+tau_turb_NS;
196
197 V prTurb = parameters.template get<PR_TURB>();
198 V tauTurbADPrefactor = descriptors::invCs2<V,DESCRIPTOR_ADE>() / descriptors::invCs2<V,DESCRIPTOR>() / prTurb;
199 V tau_turb_AD = tau_turb_NS * tauTurbADPrefactor;
200 tauAD[0] = tau_mol_AD+tau_turb_AD;
201 }
202
203};
204
205
207template<typename T>
210
212 struct EQUILIBRIUM : public descriptors::FIELD_BASE<1> { };
213
215
216 template <typename CELLS, typename PARAMETERS>
217 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
218 {
219 T forwardConstant = parameters.template get<REACTION_CONSTANT>();
220 T Ceq = parameters.template get<EQUILIBRIUM>();
221
222 auto allow_source = cells.template get<names::Concentration0>().template getField<descriptors::GAMMA>(); //allow source only at surface
223 T concC = cells.template get<names::Concentration0>().computeRho(); //current concentration
224 T source = -forwardConstant*(concC - Ceq); //difference between current Conc and equilibrium concentration determines source
225 cells.template get<names::Concentration0>().template setField<descriptors::SOURCE>(source*allow_source);
226 }
227};
228
229
230
232template<typename T, int numComp>
235
237 struct STOCH_COEFF : public descriptors::FIELD_BASE<numComp> { };
238 struct REACTION_ORDER : public descriptors::FIELD_BASE<numComp> { };
240 struct SCHMIDT : descriptors::FIELD_BASE<numComp> { };
241 struct OMEGA_NSE : public descriptors::FIELD_BASE<1> { };
242 struct OMEGAS_ADE : public descriptors::FIELD_BASE<numComp> { };
243
245
246 template <typename CELLS, typename PARAMETERS>
247 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
248 {
249 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
250 using DESCRIPTOR_ADE = typename CELLS::template value_t<names::Concentration0>::descriptor_t;
251 // Velocity coupling
252 auto u = cells.template get<names::Concentration0>().template getField<descriptors::VELOCITY>();
253 T rho, pi[util::TensorVal<DESCRIPTOR>::n] { };
254 cells.template get<names::NavierStokes>().computeAllMomenta(rho, u.data(), pi);
255 cells.template get<names::Concentration0>().template setField<descriptors::VELOCITY>(u);
256 cells.template get<names::Concentration1>().template setField<descriptors::VELOCITY>(u);
257 cells.template get<names::Concentration2>().template setField<descriptors::VELOCITY>(u);
258 // Stress tensor
259 T PiNeqNormSqr = pi[0]*pi[0] + 2.0*pi[1]*pi[1] + pi[2]*pi[2];
260 if constexpr (util::TensorVal<DESCRIPTOR>::n == 6) {
261 PiNeqNormSqr += pi[2]*pi[2] + pi[3]*pi[3] + 2*pi[4]*pi[4] +pi[5]*pi[5];
262 }
263 T PiNeqNorm = util::sqrt(PiNeqNormSqr);
265 T tau_mol_NS = T{1} / parameters.template get<OMEGA_NSE>();
266 auto omegasAD = parameters.template get<OMEGAS_ADE>();
267 T tau_mol_AD0 = T{1} / omegasAD[0];
268 T tau_mol_AD1 = T{1} / omegasAD[1];
269 T tau_mol_AD2 = T{1} / omegasAD[2];
271 T smagoPrefactor = parameters.template get<SMAGORINSKY_PREFACTOR>();
272 T tau_turb_NS = T{0.5}*(util::sqrt(tau_mol_NS*tau_mol_NS + smagoPrefactor/rho*PiNeqNorm) - tau_mol_NS);
273 // Schmidt number stabilization
274 auto Sc = parameters.template get<SCHMIDT>();
275 T tauTurbADPrefactor0 = descriptors::invCs2<T,DESCRIPTOR_ADE>() / descriptors::invCs2<T,DESCRIPTOR>() / Sc[0];
276 T tauTurbADPrefactor1 = descriptors::invCs2<T,DESCRIPTOR_ADE>() / descriptors::invCs2<T,DESCRIPTOR>() / Sc[1];
277 T tauTurbADPrefactor2 = descriptors::invCs2<T,DESCRIPTOR_ADE>() / descriptors::invCs2<T,DESCRIPTOR>() / Sc[2];
278 T tau_turb_AD0 = tau_turb_NS * tauTurbADPrefactor0;
279 T tau_turb_AD1 = tau_turb_NS * tauTurbADPrefactor1;
280 T tau_turb_AD2 = tau_turb_NS * tauTurbADPrefactor2;
281 cells.template get<names::Concentration0>().template setField<descriptors::OMEGA>(T{1} / (tau_mol_AD0 + tau_turb_AD0));
282 cells.template get<names::Concentration1>().template setField<descriptors::OMEGA>(T{1} / (tau_mol_AD1 + tau_turb_AD1));
283 cells.template get<names::Concentration2>().template setField<descriptors::OMEGA>(T{1} / (tau_mol_AD2 + tau_turb_AD2));
284
285 auto stochCoeff = parameters.template get<STOCH_COEFF>();
286 auto reactionOrder = parameters.template get<REACTION_ORDER>();
287 T source = parameters.template get<LATTICE_REACTION_COEFF>();
288 {
289 T conc = cells.template get<names::Concentration0>().computeRho();
290 source *= util::pow(conc, reactionOrder[0]);
291 }
292 {
293 T conc = cells.template get<names::Concentration1>().computeRho();
294 source *= util::pow(conc, reactionOrder[1]);
295 }
296 {
297 T conc = cells.template get<names::Concentration2>().computeRho();
298 source *= util::pow(conc, reactionOrder[2]);
299 }
300 {
301 cells.template get<names::Concentration0>().template setField<descriptors::SOURCE>(stochCoeff[0]*source);
302 cells.template get<names::Concentration1>().template setField<descriptors::SOURCE>(stochCoeff[1]*source);
303 cells.template get<names::Concentration2>().template setField<descriptors::SOURCE>(stochCoeff[2]*source);
304 }
305 }
306
307};
308
310template<typename T>
313
316 struct OMEGA_NSE : public descriptors::FIELD_BASE<1> { };
317 struct OMEGA_ADE : public descriptors::FIELD_BASE<1> { };
318
320
321 template <typename CELLS, typename PARAMETERS>
322 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
323 {
324 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
325 using DESCRIPTOR_ADE = typename CELLS::template value_t<names::Concentration0>::descriptor_t;
326 // Velocity coupling
327 auto u = cells.template get<names::Concentration0>().template getField<descriptors::VELOCITY>();
328 T rho, pi[util::TensorVal<DESCRIPTOR>::n] { };
329 cells.template get<names::NavierStokes>().computeAllMomenta(rho, u.data(), pi);
330 cells.template get<names::Concentration0>().template setField<descriptors::VELOCITY>(u);
331 // Stress tensor
332 T PiNeqNormSqr = pi[0]*pi[0] + 2.0*pi[1]*pi[1] + pi[2]*pi[2];
333 if constexpr (util::TensorVal<DESCRIPTOR>::n == 6) {
334 PiNeqNormSqr += pi[2]*pi[2] + pi[3]*pi[3] + 2*pi[4]*pi[4] +pi[5]*pi[5];
335 }
336 T PiNeqNorm = util::sqrt(PiNeqNormSqr);
338 T tau_mol_NS = T{1} / parameters.template get<OMEGA_NSE>();
339 T tau_mol_AD = T{1} / parameters.template get<OMEGA_ADE>();
341 T smagoPrefactor = parameters.template get<SMAGORINSKY_PREFACTOR>();
342 T tau_turb_NS = T{0.5}*(util::sqrt(tau_mol_NS*tau_mol_NS + smagoPrefactor/rho*PiNeqNorm) - tau_mol_NS);
343 // Schmidt number stabilization
344 T tauTurbADPrefactor = descriptors::invCs2<T,DESCRIPTOR_ADE>() / descriptors::invCs2<T,DESCRIPTOR>() / parameters.template get<SCHMIDT>();
345 T tau_turb_AD = tau_turb_NS * tauTurbADPrefactor;
346 cells.template get<names::Concentration0>().template setField<descriptors::OMEGA>(T{1} / (tau_mol_AD + tau_turb_AD));
347 }
348
349};
350
352template<typename T>
355
357 struct VISCOSITY : public descriptors::FIELD_BASE<1> { };
358 struct CONV_VEL : public descriptors::FIELD_BASE<1> { };
359 struct CONV_DENS : public descriptors::FIELD_BASE<1> { };
360 struct PART_DENS : public descriptors::FIELD_BASE<1> { };
361 struct DT : public descriptors::FIELD_BASE<1> { };
362 struct CONV_FORCE : public descriptors::FIELD_BASE<1> { };
363 struct CONV_MASS : public descriptors::FIELD_BASE<1> { };
364 struct EARTH_ACC : public descriptors::FIELD_BASE<3> { };
365
367
368 template <typename CELLS, typename PARAMETERS>
369 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
370 {
371 T particleDiam = parameters.template get<PARTICLE_DIAMETER>();
372 T visc = parameters.template get<VISCOSITY>();
373 T convVel = parameters.template get<CONV_VEL>();
374 T convDens = parameters.template get<CONV_DENS>();
375 T convForce = parameters.template get<CONV_FORCE>();
376 T convMass = parameters.template get<CONV_MASS>();
377 T partDens = parameters.template get<PART_DENS>();
378 T dt = parameters.template get<DT>();
379 auto earthAcc = parameters.template get<EARTH_ACC>();
380 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
381 auto& cellNSE = cells.template get<names::NavierStokes>();
382 auto& cellADE = cells.template get<names::Concentration0>();
383
384 auto u_p = cellADE.template getField<descriptors::VELOCITY>();
385 auto u_pXp = cellADE.neighbor({1,0,0}).template getField<descriptors::VELOCITY2>();
386 auto u_pXm = cellADE.neighbor({-1,0,0}).template getField<descriptors::VELOCITY2>();
387 auto u_pYp = cellADE.neighbor({0,1,0}).template getField<descriptors::VELOCITY2>();
388 auto u_pYm = cellADE.neighbor({0,-1,0}).template getField<descriptors::VELOCITY2>();
389 auto u_pZp = cellADE.neighbor({0,0,1}).template getField<descriptors::VELOCITY2>();
390 auto u_pZm = cellADE.neighbor({0,0,-1}).template getField<descriptors::VELOCITY2>();
391 auto u_f = cellADE.template getField<descriptors::VELOCITY>();
392 T por = (1. - cellADE.computeRho());
393 T rho { };
394 cellNSE.computeRhoU(rho, u_f.data());
395
396 T relU[3] = {0.};
397 relU[0] = (u_f[0] - u_p[0]) * convVel;
398 relU[1] = (u_f[1] - u_p[1]) * convVel;
399 relU[2] = (u_f[2] - u_p[2]) * convVel;
400 T norm = util::sqrt(relU[0]*relU[0] + relU[1]*relU[1] + relU[2]*relU[2]);
401 T Re_p = norm * particleDiam / visc;
402 T C_D = 0.;
403 if(Re_p != 0.){
404 if(Re_p <= 1000.){
405 C_D = 24.*(1. + 0.15*util::pow(Re_p,0.687))/Re_p;
406 }else{
407 C_D = 0.44;
408 }}
409 T F_D[3] = {0.};
410 //F_D[0] = C_D * 3./4. * rho * convDens * norm * relU[0] / particleDiam / partDens;
411 //F_D[1] = C_D * 3./4. * rho * convDens * norm * relU[1] / particleDiam / partDens;
412 //F_D[2] = C_D * 3./4. * rho * convDens * norm * relU[2] / particleDiam / partDens;
413 //dragCoeff = (9.*converter_.getPhysViscosity()*converter_.getPhysDensity()*converter_.getConversionFactorTime()) / (2.*pRho_*pRadius_*pRadius_);
414 F_D[0] = 9.*visc*convDens/partDens/particleDiam*relU[0];
415 F_D[1] = 9.*visc*convDens/partDens/particleDiam*relU[1];
416 F_D[2] = 9.*visc*convDens/partDens/particleDiam*relU[2];
417
418 T mass = partDens * 3.14/4. * particleDiam * particleDiam;
419 if(cellADE.computeRho() > 0.001){
420 u_p[0] += dt * (F_D[0]/*mass*/ + earthAcc[0]*(partDens - convDens)/partDens) / convVel - u_p * 0.5 * (u_pXp - u_pXm);
421 u_p[1] += dt * (F_D[1]/*mass*/ + earthAcc[1]*(partDens - convDens)/partDens) / convVel - u_p * 0.5 * (u_pYp - u_pYm);
422 u_p[2] += dt * (F_D[2]/*mass*/ + earthAcc[2]*(partDens - convDens)/partDens) / convVel - u_p * 0.5 * (u_pZp - u_pZm);
423 cellADE.template setField<descriptors::VELOCITY>(u_p);
424 }
425
426 T porPlusX = (1. - cellADE.neighbor({1,0,0}).computeRho());
427 T porMinusX = (1. - cellADE.neighbor({-1,0,0}).computeRho());
428 T porPlusY = (1. - cellADE.neighbor({0,1,0}).computeRho());
429 T porMinusY = (1. - cellADE.neighbor({0,-1,0}).computeRho());
430 T porPlusZ = (1. - cellADE.neighbor({0,0,1}).computeRho());
431 T porMinusZ = (1. - cellADE.neighbor({0,0,-1}).computeRho());
432
433 T porDX2 = porPlusX -2.*por + porMinusX;
434 T porDY2 = porPlusY -2.*por + porMinusY;
435 T porDZ2 = porPlusZ -2.*por + porMinusZ;
436
437 int choice = 0;
438 if( porDX2 != 0.) choice += 1;
439 if( porDY2 != 0.) choice += 1;
440 if( porDZ2 != 0.) choice += 1;
441
442 T coeff = (choice == 1) *1./4. + (choice == 2) * 1./6. + (choice == 3) * 5./36.;
443 T pressCorr = por + coeff * (porDX2 + porDY2 + porDZ2);
444 if(pressCorr < 0.001){ pressCorr = 1.; }
445 cellNSE.template setField<descriptors::PRESSCORR>(pressCorr);
446 T press = rho / pressCorr / descriptors::invCs2<T,DESCRIPTOR>();
447 T pressCorrForce[3] = {0.};
448 pressCorrForce[0] = press * 0.5 * (porPlusX - porMinusX);
449 pressCorrForce[1] = press * 0.5 * (porPlusY - porMinusY);
450 pressCorrForce[2] = press * 0.5 * (porPlusZ - porMinusZ);
451
452 T force[3] = {0.};
453 if(cellADE.computeRho() > 0.001){
454 force[0] = pressCorrForce[0] / rho - (1. - por) * por * F_D[0] / convForce * convMass * partDens / rho + por * earthAcc[0] / convVel * dt;
455 force[1] = pressCorrForce[1] / rho - (1. - por) * por * F_D[1] / convForce * convMass * partDens / rho + por * earthAcc[1] / convVel * dt;
456 force[2] = pressCorrForce[2] / rho - (1. - por) * por * F_D[2] / convForce * convMass * partDens / rho + por * earthAcc[2] / convVel * dt;
457 }
458 cellNSE.template setField<descriptors::FORCE>(force);
459 }
460
461};
462
464template<typename T>
467
469 struct RHO0 : public descriptors::FIELD_BASE<1> { };
470 struct FORCE_PREFACTOR : public descriptors::FIELD_BASE<0,1> { };
471
473
474 template <typename CELLS, typename PARAMETERS>
475 void apply(CELLS& cells, PARAMETERS& parameters) any_platform
476 {
477 using DESCRIPTOR = typename CELLS::template value_t<names::NavierStokes>::descriptor_t;
478 T rho, u[DESCRIPTOR::d], pi[util::TensorVal<DESCRIPTOR>::n] { };
479 cells.template get<names::NavierStokes>().computeAllMomenta(rho, u, pi);
480 // Stress tensor
481 T PiNeqNormSqr = pi[0]*pi[0] + 2.0*pi[1]*pi[1] + pi[2]*pi[2];
482 if constexpr (util::TensorVal<DESCRIPTOR>::n == 6) {
483 PiNeqNormSqr += pi[2]*pi[2] + pi[3]*pi[3] + 2*pi[4]*pi[4] +pi[5]*pi[5];
484 }
485 T PiNeqNorm = util::sqrt(PiNeqNormSqr);
486
487 if(PiNeqNorm != T{0.}){
488 auto omega = cells.template get<names::NavierStokes>().template getFieldPointer<descriptors::OMEGA>();
489 PiNeqNorm /= (-rho/omega[0]/descriptors::invCs2<T,DESCRIPTOR>());
490 T angle = parameters.template get<FRICTION_ANGLE>();
491 T ps = ( T{0.5}*omega[0] - T{1} ) * T{1./3.} * ( pi[0] + pi[3] + pi[5] );
492 T granularTau = ps/rho * util::sin(T{3.14}*angle/T{180}) / PiNeqNorm * descriptors::invCs2<T,DESCRIPTOR>() + T{0.5};
493 omega[0] = T{1} / granularTau;
494 }
495
496 // computation of the bousinessq force
497 auto force = cells.template get<names::NavierStokes>().template getFieldPointer<descriptors::FORCE>();
498 auto forcePrefactor = parameters.template get<FORCE_PREFACTOR>();
499 T densityDifference = (rho - parameters.template get<RHO0>()) / rho;
500 for (unsigned iD = 0; iD < DESCRIPTOR::d; ++iD) {
501 force[iD] = forcePrefactor[iD] * densityDifference;
502 }
503 }
504
505};
506
507
508}
509
510#endif
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
ADf< T, DIM > sin(const ADf< T, DIM > &a)
Definition aDiff.h:569
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.
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
OperatorScope
Block-wide operator application scopes.
Definition operator.h:54
@ PerCellWithParameters
Per-cell application with parameters, i.e. OPERATOR::apply is passed a CELL concept implementation an...
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
LES-ADE coupling with Schmidt number stabilization.
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
static constexpr OperatorScope scope
LES-ADE coupling for multiple reactions.
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Reaction Coupling for the In-Bulk appraoch of lognitudinalMixing3d example.
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Coupling between a Navier-Stokes and an Advection-Diffusion lattice.
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Velocity coupling between Navier-Stokes and an Advection-Diffusion lattice.
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
AD coupling with Boussinesq bouancy for Smagorinsky-LES.
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
TotalEnthalpyPhaseChange between a Navier-Stokes and an Advection-Diffusion lattice.
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
void apply(CELLS &cells, PARAMETERS &parameters) any_platform
Base of a field whose size is defined by [C,U_1,...,U_N]^T * [1,V_1,...V_N].
Plain wrapper for list of types.
Definition meta.h:276
Compute number of elements of a symmetric d-dimensional tensor.
Definition util.h:210