OpenLB 1.7
Loading...
Searching...
No Matches
adsorptionReaction.h
Go to the documentation of this file.
1/* Lattice Boltzmann sample, written in C++, using the OpenLB
2 * library
3 *
4 * Copyright (C) 2022 Florian Raichle
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#ifndef OLB_APPS_FLORIAN_ADSORPTION3D_ADSORPTIONREACTION_H_
26#define OLB_APPS_FLORIAN_ADSORPTION3D_ADSORPTIONREACTION_H_
27
28#include <vector>
29#include <cmath>
30#include <iostream>
32#include "isotherm.h"
33
34namespace olb {
35
36struct SCALAR2 : public descriptors::FIELD_BASE<1, 0, 0> { };
37
46template<typename T, typename DESCRIPTOR>
48 protected:
49// virtual void boundary(int n, T x[], T fvec[], int &iflag, T args[]) = 0;
52 const Isotherm<T>* isotherm; // needs to be pointer because Isotherm is an abstract class
53
54 public:
55 T k_f{}; // film diffusion mass transfer coefficient (m/s)
56 T D_s{}; // surface diffusion constant (m^2/s)
57 T c_0{}; // initial concentration (mg/L)
58 T r_p{}; // particle radius (m)
59 T q_0{}; // equilibrium surface loading (mg/g)
60 T k_s{}; // surface diffusion mass transfer coefficient (1/s)
61
62// explicit AdsorptionReaction(void(*fcn)(int, T[], T[], int&, T[])): fcn(fcn){}
64 _unitConverter(converter),
66 {
67 // calculate lattice values
68 T conversionFactorLength = _unitConverter.getConversionFactorLength();
69 this->k_f = k_f * _unitConverter.getConversionFactorTime() * 3 / r_p;
70 this->D_s = D_s / (conversionFactorLength*conversionFactorLength) * _unitConverter.getConversionFactorTime();
71 this->c_0 = c_0 / _unitConverter.getConversionFactorDensity();
72 this->r_p = r_p / conversionFactorLength;
73 this->k_s = 15 * this->D_s / (this->r_p * this->r_p);
74 this->q_0 = this->isotherm->getLoading(c_0) / _unitConverter.getConversionFactorParticleDensity();
75 externalMassTransferEnabled = this->k_f > 0.;
76 }
77
84 T getSurfaceLoading(T soluteConcentration) {
85 if (soluteConcentration < 0) return 0; // prevent nan
86 T load = this->isotherm->getLoading(soluteConcentration);
87 if (load < 0) load = 0;
88 return load;
89 }
90
101 T getSurfaceLoading(T soluteConcentration, T particleLoading, T particleConcentration) {
102 if (soluteConcentration < 0) return 0; // prevent nan
103 // using D = double; // because fsolve is hardcoded in double type
104
105 // previous surface concentration as initial guess
106 T surfaceConcentration = soluteConcentration;
107 T args[] = {particleLoading, soluteConcentration, particleConcentration};
108 for(int i = 0; i<100; i++){
109 //ADf<T,1> y0_ad = iniAD(surfaceConcentration);
110 //ADf<T,1> y1_ad = filmDiffBoundary(y0_ad, args);
111 //surfaceConcentration -= filmDiffBoundary(surfaceConcentration, args) / y1_ad.d(0);
112
113 T dCs = surfaceConcentration/1E8;
114 surfaceConcentration -= 2.*dCs*filmDiffBoundary(surfaceConcentration, args)/(filmDiffBoundary(surfaceConcentration + dCs, args) - filmDiffBoundary(surfaceConcentration - dCs, args));
115 }
116 T load = isotherm->getLoading(surfaceConcentration);
117 if (load < 0) load = 0;
118 return load;
119 }
120
126 Vector<T, 2> getReactionRate(T soluteConcentration, T particleLoading, T particleConcentration) {
127 T surfaceLoad;
128 particleConcentration *= _unitConverter.getConversionFactorParticleDensity(); // convert to kg/m^3
129 soluteConcentration *= _unitConverter.getConversionFactorDensity(); // convert to g/m^3
130 particleLoading *= _unitConverter.getConversionFactorParticleDensity(); // convert to g/m^3
132 surfaceLoad = this->getSurfaceLoading(soluteConcentration, particleLoading, particleConcentration);
133 } else {
134 surfaceLoad = this->getSurfaceLoading(soluteConcentration);
135 }
136
137 T reactionRate = this->k_s * (surfaceLoad * particleConcentration - particleLoading);
138 Vector<T, 2> reactionRates(reactionRate / _unitConverter.getConversionFactorDensity(), // solute
139 reactionRate / _unitConverter.getConversionFactorParticleDensity()); // loading
140 return reactionRates;
141 }
142
144 return this->k_f / _unitConverter.getConversionFactorTime();
145 }
147 return this->k_s / _unitConverter.getConversionFactorTime();
148 }
149
151 return this->D_s * _unitConverter.getConversionFactorLength() * _unitConverter.getConversionFactorLength() / _unitConverter.getConversionFactorTime();
152 }
153
154 void print(std::ostream& clout) {
155 clout << "----------------- Reaction information -----------------" << std::endl;
156 clout << "-- Parameters:" << std::endl;
157 clout << "Particle diameter(m): d_p= " << this->r_p*2 * _unitConverter.getConversionFactorLength() << std::endl;
158 clout << "Film diffusion constant(m/s): k_f*= " << getPhysFilmTransferConstant() << std::endl;
159 clout << "Surface diffusion constant(m^2/s): D_s= " << getPhysSurfaceDiffusionConstant() << std::endl;
160 clout << "Initial solute concentration(mg/mL): c_0= " << this->c_0 * _unitConverter.getConversionFactorDensity() << std::endl;
161 clout << "Equilibrium surface loading(mg/g): q_0= " << this->q_0 * _unitConverter.getConversionFactorParticleDensity() << std::endl;
162 clout << "lattice Equilibrium surface loading: q_0= " << this->q_0 << std::endl;
163 clout << "Surface Mass transfer coefficient(m/s): k_s*= " << getPhysSurfaceTransferConstant() << std::endl;
164 clout << "-------------------------------------------------------------" << std::endl;
165 this->isotherm->print(clout);
166 }
167
168 void write(std::string const& fileName) {
169 std::string dataFile = singleton::directories().getLogOutDir() + fileName + ".dat";
170
171 if (singleton::mpi().isMainProcessor()) {
172 std::ofstream fout(dataFile.c_str(), std::ios::app);
173 if (!fout) {
174 std::cout << "error write() function: can not open std::ofstream" << std::endl;
175 }
176 else {
177 this->print( fout );
178 fout.close();
179 }
180 }
181 }
182
184 T filmDiffBoundary(T c_s_, T args[]) {
185 T q = args[0];
186 T c = args[1];
187 T particleConcentration = args[2];
188 auto c_s = c_s_;
189 T q_s = this->isotherm->getLoading(c_s);
190 T equation = this->k_f * (c - c_s) - this->k_s * (particleConcentration * q_s - q);
191 return equation;
192 }
193};
194}
195#endif //OLB_APPS_FLORIAN_ADSORPTION3D_ADSORPTIONREACTION_H_
constexpr T getConversionFactorParticleDensity() const
conversion factor to convert particle density from lattice units to kg/m^3
Describes adsorption reactions in conjunction with a Isotherm class.
void print(std::ostream &clout)
const Isotherm< T > * isotherm
AdsorptionReaction(AdsorptionConverter< T, DESCRIPTOR > const &converter, Isotherm< T > const *isotherm, T k_f, T D_s, T c_0, T r_p)
void write(std::string const &fileName)
T getSurfaceLoading(T soluteConcentration)
Get surface loading without film diffusion.
T getSurfaceLoading(T soluteConcentration, T particleLoading, T particleConcentration)
Get surface loading with film diffusion.
Vector< T, 2 > getReactionRate(T soluteConcentration, T particleLoading, T particleConcentration)
Calculates reaction rate in lattice units.
const AdsorptionConverter< T, DESCRIPTOR > _unitConverter
T filmDiffBoundary(T c_s_, T args[])
equations for surface concentration
Base class for isotherms.
Definition isotherm.h:42
virtual T getLoading(T c) const =0
Equation for isotherm.
void print(std::ostream &clout) const
Definition isotherm.h:69
constexpr T getConversionFactorDensity() const
access (read-only) to private member variable
constexpr T getConversionFactorLength() const
access (read-only) to private member variable
constexpr T getConversionFactorTime() const
access (read-only) to private member variable
Plain old scalar vector.
Definition vector.h:47
std::string getLogOutDir() const
Definition singleton.h:89
MpiManager & mpi()
Directories & directories()
Definition singleton.h:150
Top level namespace for all of OpenLB.
Base of a field whose size is defined by [C,U_1,...,U_N]^T * [1,V_1,...V_N].