OpenLB 1.7
Loading...
Searching...
No Matches
dualDynamics.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2012 Mathias J. Krause
4 * 2024 Julius Jessberger, Shota Ito, Adrian Kummerlaender
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
34#ifndef DUAL_DYNAMICS_H
35#define DUAL_DYNAMICS_H
36
37#include "dualLbHelpers.h"
38
40
41// All OpenLB code is contained in this namespace.
42namespace olb {
43
44namespace collision {
45
48
49 static std::string getName() {
50 return "DualPorousBGK";
51 }
52
53 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
54 struct type {
55 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
56 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
57
58 template <CONCEPT(MinimalCell) CELL, typename PARAMETERS, typename V=typename CELL::value_t>
59 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) any_platform {
60 // Revert for backwards-in-time propagation
61 //cell.revert();
62 for (int iPop=1; iPop <= DESCRIPTOR::q/2; ++iPop) {
63 V cell_iPop = cell[iPop];
64 cell[iPop] = cell[descriptors::opposite<DESCRIPTOR>(iPop)];
65 cell[descriptors::opposite<DESCRIPTOR>(iPop)] = cell_iPop;
66 }
67
68 // Preparation
69 const auto pop_f = cell.template getField<descriptors::F>();
70 const auto dJdF = cell.template getFieldPointer<descriptors::DJDF>();
71 const V d = cell.template getField<descriptors::POROSITY>();
72 const V omega = parameters.template get<descriptors::OMEGA>();
73
74 // Forward density and velocity
75 V rho_f { };
76 V u_f[DESCRIPTOR::d] { };
77 //this->computeRhoU( pop_f.data(), rho_f, u_f);
78 rho_f = V();
79 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
80 u_f[iD] = V();
81 }
82 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
83 rho_f += pop_f[iPop];
84 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
85 u_f[iD] += pop_f[iPop]*descriptors::c<DESCRIPTOR>(iPop,iD);
86 }
87 }
88 rho_f += (V)1;
89 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
90 u_f[iD] /= rho_f;
91 }
92
93 // Adjoint equilibrium
94 V pheq[DESCRIPTOR::q] { };
95 for (int i=0; i < DESCRIPTOR::q; ++i) {
96 pheq[i] = V{0};
97 for (int j=0; j < DESCRIPTOR::q; ++j) {
98 V feq_j = equilibrium<DESCRIPTOR>::secondOrder(j, rho_f, u_f)
99 + descriptors::t<V,DESCRIPTOR>(j);
100 V dot_ij = V();
101 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
102 dot_ij += ( descriptors::c<DESCRIPTOR>(j,iD) - d*u_f[iD] )
103 * ( descriptors::c<DESCRIPTOR>(i,iD) - u_f[iD] );
104 }
105 pheq[i] += cell[j]*feq_j*( V{1} + descriptors::invCs2<V,DESCRIPTOR>()*d*dot_ij );
106 }
107 pheq[i] /= rho_f;
108 }
109
110 // Collision
111 for (int i=0; i < DESCRIPTOR::q; ++i) {
112 cell[i] = cell[i] - omega*( cell[i] - pheq[i] ) + dJdF[i];
113 }
114
115 // Statistics
116 V rho_phi, u_phi[DESCRIPTOR::d];
117 MomentaF().computeRhoU( cell, rho_phi, u_phi );
118 V uSqr_phi = util::normSqr<V,DESCRIPTOR::d>( u_phi );
119
120 // Undo revert
121 //cell.revert();
122 for (int iPop=1; iPop <= DESCRIPTOR::q/2; ++iPop) {
123 V cell_iPop = cell[iPop];
124 cell[iPop] = cell[descriptors::opposite<DESCRIPTOR>(iPop)];
125 cell[descriptors::opposite<DESCRIPTOR>(iPop)] = cell_iPop;
126 }
127 return {rho_phi, uSqr_phi};
128 };
129 };
130};
131
132}
133
134template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
136 T, DESCRIPTOR,
137 MOMENTA,
140>;
141
143namespace opti {
144
145template<typename T> class Controller;
146template<typename T, typename DESCRIPTOR> class DualController;
147
149template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
150class DualForcedBGKdynamics : public legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA> {
151public:
153 DualForcedBGKdynamics(T omega_);
155 virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const;
159 virtual T getOmega() const;
161 virtual void setOmega(T omega_);
163 virtual void defineRho(Cell<T,DESCRIPTOR>& cell, T rho);
164private:
165 T omega;
166};
167
169
173template<typename T, typename DESCRIPTOR, typename MOMENTA>
175 T omega_)
176 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
177 omega(omega_)
178{
179 this->getName() = "DualForcedBGKdynamics";
180 OLB_PRECONDITION( DESCRIPTOR::template provides<descriptors::FORCE>() );
181}
182
183template<typename T, typename DESCRIPTOR, typename MOMENTA>
185{
186 // The meaning of this function is not clear. Please contact Julius.
187 throw std::bad_function_call();
188}
189
190template<typename T, typename DESCRIPTOR, typename MOMENTA>
191T DualForcedBGKdynamics<T,DESCRIPTOR,MOMENTA>::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const
192{
193 return equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u);
194}
195
196template<typename T, typename DESCRIPTOR, typename MOMENTA>
198 Cell<T,DESCRIPTOR>& cell)
199{
200 cell.revert();
201
202 // Preparation
203 auto dJdF = cell.template getFieldPointer<descriptors::DJDF>();
204 auto f = cell.template getField<descriptors::F>();
205 auto force = cell.template getFieldPointer<descriptors::FORCE>();
206 T rho_f;
207 T u_f[DESCRIPTOR::d];
208
210 T eq_phi[DESCRIPTOR::q];
211 T force_phi[DESCRIPTOR::q];
212
213 // Force
214 T F1_phi[DESCRIPTOR::q][DESCRIPTOR::q];
215 T F2_phi[DESCRIPTOR::q][DESCRIPTOR::q];
216 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
217 T f_c = T();
218 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
219 f_c += force[iD]*descriptors::c<DESCRIPTOR>(iPop,iD);
220 }
221 for (int jPop=0; jPop < DESCRIPTOR::q; ++jPop) {
222 T sum = T();
223 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
224 sum += (f_c*descriptors::c<DESCRIPTOR>(iPop,iD)-force[iD]/(T)descriptors::invCs2<T,DESCRIPTOR>())*descriptors::c<DESCRIPTOR>(jPop,iD);
225 }
226 F1_phi[iPop][jPop] = descriptors::t<T,DESCRIPTOR>(iPop)*descriptors::invCs2<T,DESCRIPTOR>()*f_c;
227 F2_phi[iPop][jPop] = descriptors::t<T,DESCRIPTOR>(iPop)*descriptors::invCs2<T,DESCRIPTOR>()*descriptors::invCs2<T,DESCRIPTOR>()*sum;
228 }
229 }
230
231 // Collision preperation
232 for (int jPop=0; jPop < DESCRIPTOR::q; ++jPop) {
233 eq_phi[jPop] = T();
234 force_phi[jPop] = T();
235 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
236 eq_phi[jPop] += cell[iPop]*dualLbHelpers<T,DESCRIPTOR>::equilibrium(iPop, jPop, rho_f, u_f);
237 force_phi[jPop] += cell[iPop]*(F1_phi[iPop][jPop] + (1.-.5*omega)*F2_phi[iPop][jPop]);
238 }
239 }
240
241 // Collision
242 for (int jPop=0; jPop < DESCRIPTOR::q; ++jPop) {
243 cell[jPop] = cell[jPop] - omega*(cell[jPop]-eq_phi[jPop]) + force_phi[jPop] + dJdF[jPop];
244 }
245
246 // Incrementing statistic values for convergence
247 T phi2 = T();
248 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
249 phi2 += cell[iPop]*cell[iPop];
250 }
251 cell.revert();
252
253 return {T(1) + cell[0], phi2};
254}
255
256template<typename T, typename DESCRIPTOR, typename MOMENTA>
258{
259 return omega;
260}
261
262template<typename T, typename DESCRIPTOR, typename MOMENTA>
264{
265 omega = omega_;
266}
267
268
270
272template<typename T, typename DESCRIPTOR, typename MOMENTA=momenta::BulkTuple>
273class DualPorousBGKdynamics : public legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA> {
274public:
275 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
276
278 DualPorousBGKdynamics(T omega_);
280 virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const;
282 virtual void computeRhoU(const T fPop[DESCRIPTOR::q], T& rho, T u[DESCRIPTOR::d]) const;
286 virtual T getOmega() const;
288 virtual void setOmega(T omega_);
290 virtual void defineRho(Cell<T,DESCRIPTOR>& cell, T rho);
291private:
292 T omega;
293};
294
296
300template<typename T, typename DESCRIPTOR, typename MOMENTA>
302 T omega_)
303 : legacy::BasicDynamics<T,DESCRIPTOR,MOMENTA>(),
304 omega(omega_)
305{
306 this->getName() = "DualPorousBGKdynamics";
307 OLB_PRECONDITION( DESCRIPTOR::template provides<descriptors::POROSITY>() );
308}
309
310template<typename T, typename DESCRIPTOR, typename MOMENTA>
312{
313 // The meaning of this function is not clear. Please contact Julius.
314 throw std::bad_function_call();
315}
316
317template<typename T, typename DESCRIPTOR, typename MOMENTA>
319 int iPop, T rho, const T u[DESCRIPTOR::d]) const
320{
321 // Compute equilibrium minus weights
322 // used in iniEquilibrium
323 return equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u);
324}
325
326// ComputeRhoU for array instead of cell
327template<typename T, typename DESCRIPTOR, typename MOMENTA>
329 const T fPop[DESCRIPTOR::q], T& rho_f, T u_f[DESCRIPTOR::d]) const
330{
331 rho_f = T();
332 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
333 u_f[iD] = T();
334 }
335 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
336 rho_f += fPop[iPop];
337 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
338 u_f[iD] += fPop[iPop]*descriptors::c<DESCRIPTOR>(iPop,iD);
339 }
340 }
341 rho_f += (T)1;
342 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
343 u_f[iD] /= rho_f;
344 }
345}
346
347template<typename T, typename DESCRIPTOR, typename MOMENTA>
349 Cell<T,DESCRIPTOR>& cell)
350{
351 // Revert for backwards-in-time propagation
352 cell.revert();
353
354 // Preparation
355 auto pop_f = cell.template getField<descriptors::F>();
356 auto dJdF = cell.template getFieldPointer<descriptors::DJDF>();
357 T d = cell.template getField<descriptors::POROSITY>();
358
359 // Forward density and velocity
360 T rho_f, u_f[DESCRIPTOR::d];
361 this->computeRhoU( pop_f.data(), rho_f, u_f);
362
363 // Adjoint equilibrium
364 T pheq[DESCRIPTOR::q];
365 for (int i=0; i < DESCRIPTOR::q; ++i) {
366 pheq[i] = T{0};
367 for (int j=0; j < DESCRIPTOR::q; ++j) {
368 T feq_j = computeEquilibrium(j, rho_f, u_f)
369 + descriptors::t<T,DESCRIPTOR>(j);
370 T dot_ij = T();
371 for (int iD=0; iD < DESCRIPTOR::d; ++iD) {
372 dot_ij += ( descriptors::c<DESCRIPTOR>(j,iD) - d*u_f[iD] )
373 * ( descriptors::c<DESCRIPTOR>(i,iD) - u_f[iD] );
374 }
375 pheq[i] += cell[j]*feq_j*( T{1} + descriptors::invCs2<T,DESCRIPTOR>()*d*dot_ij );
376 }
377 pheq[i] /= rho_f;
378 }
379
380 // Collision
381 for (int i=0; i < DESCRIPTOR::q; ++i) {
382 cell[i] = cell[i] - omega*( cell[i] - pheq[i] ) + dJdF[i];
383 }
384
385 // Statistics
386 T rho_phi, u_phi[DESCRIPTOR::d];
387 MomentaF().computeRhoU( cell, rho_phi, u_phi );
388 T uSqr_phi = util::normSqr<T,DESCRIPTOR::d>( u_phi );
389
390 // Undo revert
391 cell.revert();
392 return {rho_phi, uSqr_phi};
393}
394
395template<typename T, typename DESCRIPTOR, typename MOMENTA>
397{
398 return omega;
399}
400
401template<typename T, typename DESCRIPTOR, typename MOMENTA>
403{
404 omega = omega_;
405}
406
407} // namespace opti
408
409} // namespace olb
410
411#endif
412
413#include "dualDynamics.cse.h"
Highest-level interface to Cell data.
Definition cell.h:148
void revert()
Revert ("bounce-back") the distribution functions.
Definition cell.hh:190
Implementation of the dual BGK collision step with external force.
virtual void setOmega(T omega_)
Set local relaxation parameter of the dynamics.
virtual void defineRho(Cell< T, DESCRIPTOR > &cell, T rho)
Does nothing.
virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const
Compute equilibrium distribution function.
DualForcedBGKdynamics(T omega_)
Constructor.
virtual CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell)
Collision step.
virtual T getOmega() const
Get local relaxation parameter of the dynamics.
Implementation of the dual BGK collision step with external force.
DualPorousBGKdynamics(T omega_)
Constructor.
virtual void defineRho(Cell< T, DESCRIPTOR > &cell, T rho)
Does nothing.
typename MOMENTA::template type< DESCRIPTOR > MomentaF
virtual T getOmega() const
Get local relaxation parameter of the dynamics.
virtual T computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d]) const
Compute equilibrium distribution function.
virtual void setOmega(T omega_)
Set local relaxation parameter of the dynamics.
virtual CellStatistic< T > collide(Cell< T, DESCRIPTOR > &cell)
Collision step.
virtual void computeRhoU(const T fPop[DESCRIPTOR::q], T &rho, T u[DESCRIPTOR::d]) const
Compute moments.
Helper functions for the implementation of LB dynamics.
Top level namespace for all of OpenLB.
Optimization Code.
#define OLB_PRECONDITION(COND)
Definition olbDebug.h:46
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
Return value of any collision.
Definition interface.h:43
virtual std::string getName() const
Return human-readable name.
Definition interface.h:63
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
typename meta::list< descriptors::OMEGA > parameters
static std::string getName()
Dynamics constructed as a tuple of momenta, equilibrium and collision.
Definition interface.h:182
void computeRhoU(ConstCell< T, DESCRIPTOR > &cell, T &rho, T u[DESCRIPTOR::d]) const override
Compute fluid velocity and particle density.
Definition interface.h:268
static V secondOrder(int iPop, const RHO &rho, const U &u, const USQR &uSqr) any_platform
Computation of equilibrium distribution, second order in u.
Definition lbm.h:51
Plain wrapper for list of types.
Definition meta.h:276
static void computeRhoU(T const *cell, T &rho, T u[DESCRIPTOR::d])
Computation of hydrodynamic variables.
static T equilibrium(int iPop, int jPop, T rho, const T u[DESCRIPTOR::d])