OpenLB 1.7
Loading...
Searching...
No Matches
freeEnergyDynamics.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2018 Robin Trunk, Sam Avis
4 * 2021 Adrian Kummerlaender
5 * OpenLB 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#ifndef FREE_ENERGY_DYNAMICS_H
26#define FREE_ENERGY_DYNAMICS_H
27
28#include "lbm.h"
29#include "interface.h"
30#include "momenta/aliases.h"
31
37namespace olb {
38
39namespace equilibria {
40
41struct FreeEnergy {
43
44 static std::string getName() {
45 return "FreeEnergy";
46 }
47
48 template <typename DESCRIPTOR, typename MOMENTA>
49 struct type {
50 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
51
52 template <typename RHO, typename U, typename V=RHO>
53 auto compute(int iPop, const RHO& rho, const U& u) any_platform {
54 V eq = equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u);
55 if (iPop == 0) {
56 eq += (V{1} - descriptors::t<V,DESCRIPTOR>(0)) * rho;
57 } else {
58 eq -= descriptors::t<V,DESCRIPTOR>(iPop) * rho;
59 }
60 return eq;
61 }
62
63 template <typename CELL, typename PARAMETERS, typename FEQ, typename V=typename CELL::value_t>
64 CellStatistic<V> compute(CELL& cell, PARAMETERS& parameters, FEQ& fEq) any_platform {
65 auto u = cell.template getField<descriptors::FORCE>();
66 V rho = MomentaF().computeRho(cell);
67 const V uSqr = util::normSqr<V,DESCRIPTOR::d>(u);
68 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
69 fEq[iPop] = equilibrium<DESCRIPTOR>::secondOrder(iPop, rho, u, uSqr);
70 }
71 return {rho, uSqr};
72 };
73 };
74};
75
76}
77
78namespace collision {
79
80struct FreeEnergy {
81 struct GAMMA : public descriptors::FIELD_BASE<1> { };
82
84
85 static std::string getName() {
86 return "FreeEnergy";
87 }
88
89 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
90 struct type {
91 using EquilibriumF = typename EQUILIBRIUM::template type<DESCRIPTOR,MOMENTA>;
92
93 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
94 CellStatistic<V> apply(CELL& cell, PARAMETERS& parameters) any_platform {
95 V fEq[DESCRIPTOR::q] { };
96 const auto statistic = EquilibriumF().compute(cell, parameters, fEq);
97 const V omega = parameters.template get<descriptors::OMEGA>();
98 const V gamma = parameters.template get<GAMMA>();
99 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
100 cell[iPop] *= V{1} - omega;
101 cell[iPop] += omega * fEq[iPop];
102 }
103 const V tmp = gamma * descriptors::invCs2<V,DESCRIPTOR>()
104 * cell.template getField<descriptors::CHEM_POTENTIAL>();
105 for (int iPop=1; iPop < DESCRIPTOR::q; ++iPop) {
106 cell[iPop] -= omega * descriptors::t<V,DESCRIPTOR>(iPop) * (statistic.rho - tmp);
107 }
108 cell[0] += omega * (V{1} - descriptors::t<V,DESCRIPTOR>(0)) * (statistic.rho - tmp);
109 return statistic;
110 };
111 };
112};
113
114template <int direction, int orientation>
117
118 static std::string getName() {
119 return "FreeEnergyInletOutlet<"
120 + std::to_string(direction) + "," + std::to_string(orientation) +
121 ">";
122 }
123
124 template <typename DESCRIPTOR, typename MOMENTA, typename EQUILIBRIUM>
125 struct type {
126 using MomentaF = typename MOMENTA::template type<DESCRIPTOR>;
127
128 template <typename CELL, typename PARAMETERS, typename V=typename CELL::value_t>
130 // Do a standard collision neglecting the chemical potential term.
131 V rho, u[DESCRIPTOR::d];
132 MomentaF().computeRhoU(cell, rho, u);
133 const V omega = parameters.template get<descriptors::OMEGA>();
134 V uSqr = lbm<DESCRIPTOR>::bgkCollision(cell, rho, u, omega);
135 for (int iPop=1; iPop < DESCRIPTOR::q; ++iPop) {
136 cell[iPop] -= omega * descriptors::t<V,DESCRIPTOR>(iPop) * rho;
137 }
138 cell[0] += omega * (V{1} - descriptors::t<V,DESCRIPTOR>(0)) * rho;
139 // Distribute the missing density to the unknown distribution functions.
140 constexpr auto missingIndices = util::subIndexOutgoing<DESCRIPTOR,direction,orientation>();
141 V missingRho = rho - V{1};
142 V missingWeightSum = 0;
143 for (int iPop=0; iPop < DESCRIPTOR::q; ++iPop) {
144
145 // std::find can conflict with CUDA
146 /*if (std::find(missingIndices.begin(), missingIndices.end(), iPop) != missingIndices.end()) {
147 missingWeightSum += descriptors::t<V,DESCRIPTOR>(iPop);
148 } else {
149 missingRho -= cell[iPop];
150 }*/
151
152 bool contains = false;
153 for(long unsigned int i=0; i < missingIndices.size(); i++){
154 if(missingIndices[i] == (long unsigned int)iPop){
155 contains = true;
156 }
157 }
158
159 if(contains){
160 missingWeightSum += descriptors::t<V,DESCRIPTOR>(iPop);
161 } else {
162 missingRho -= cell[iPop];
163 }
164
165 }
166
167 for (unsigned iPop=0; iPop < missingIndices.size(); ++iPop) {
168 cell[missingIndices[iPop]] = missingRho * descriptors::t<V,DESCRIPTOR>(missingIndices[iPop]) / missingWeightSum;
169 }
170 return {rho, uSqr};
171 };
172 };
173};
174
175}
176
177template <typename T, typename DESCRIPTOR, typename MOMENTA=momenta::FreeEnergyBulkTuple>
179 T, DESCRIPTOR,
180 MOMENTA,
183>;
184
185template <typename T, typename DESCRIPTOR>
187 T, DESCRIPTOR,
193 >,
196>;
197
198template <typename T, typename DESCRIPTOR, int direction, int orientation>
200 T, DESCRIPTOR,
206 >,
209>;
210
211}
212
213#endif
214
Instantiation of Momenta tuples which define the computation and definition of momenta in a specific ...
Top level namespace for all of OpenLB.
#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
typename MOMENTA::template type< DESCRIPTOR > MomentaF
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
typename meta::list< descriptors::OMEGA > parameters
CellStatistic< V > apply(CELL &cell, PARAMETERS &parameters) any_platform
typename EQUILIBRIUM::template type< DESCRIPTOR, MOMENTA > EquilibriumF
static std::string getName()
typename meta::list< descriptors::OMEGA, GAMMA > parameters
Base of a field whose size is defined by [C,U_1,...,U_N]^T * [1,V_1,...V_N].
Dynamics constructed as a tuple of momenta, equilibrium and collision.
Definition interface.h:182
auto compute(int iPop, const RHO &rho, const U &u) any_platform
CellStatistic< V > compute(CELL &cell, PARAMETERS &parameters, FEQ &fEq) any_platform
typename MOMENTA::template type< DESCRIPTOR > MomentaF
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
static V bgkCollision(CELL &cell, const RHO &rho, const VELOCITY &u, const OMEGA &omega) any_platform
BGK collision step.
Definition lbm.h:290
Plain wrapper for list of types.
Definition meta.h:276
Standard computation for density in the bulk as zeroth moment of the population.
Definition elements.h:132
The momenta are defined one after the other.
The density is stored in descriptors::FORCE[0] (TODO: absurd, to be changed)
Definition elements.h:212
Computation of the stress tensor for regularized boundary nodes.
Definition elements.h:1245
Momentum is zero at solid material.
Definition elements.h:1049
The stress is always zero.
Definition elements.h:1355