3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
box/maxwellstefanslaw.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
25#ifndef DUMUX_DISCRETIZATION_BOX_MAXWELL_STEFAN_LAW_HH
26#define DUMUX_DISCRETIZATION_BOX_MAXWELL_STEFAN_LAW_HH
27
28#include <dune/common/float_cmp.hh>
29
30#include <dumux/common/math.hh>
36
37namespace Dumux {
38
39// forward declaration
40template <class TypeTag, DiscretizationMethod discMethod, ReferenceSystemFormulation referenceSystem>
41class MaxwellStefansLawImplementation;
42
47template <class TypeTag, ReferenceSystemFormulation referenceSystem>
49{
54 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
55 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
56 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
57 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
58 using ElementFluxVariablesCache = typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView;
60 using Element = typename GridView::template Codim<0>::Entity;
61
62 static constexpr auto numFluidPhases = GetPropType<TypeTag, Properties::ModelTraits>::numFluidPhases();
63 static constexpr auto numComponents = GetPropType<TypeTag, Properties::ModelTraits>::numFluidComponents();
64
65 using ComponentFluxVector = Dune::FieldVector<Scalar, numComponents>;
66 using ReducedComponentVector = Dune::FieldVector<Scalar, numComponents-1>;
67 using ReducedComponentMatrix = Dune::FieldMatrix<Scalar, numComponents-1, numComponents-1>;
68
69 static_assert(referenceSystem == ReferenceSystemFormulation::massAveraged, "only the mass averaged reference system is supported for the Maxwell-Stefan formulation");
70
71
72public:
73 //return the reference system
75 { return referenceSystem; }
76
77 static ComponentFluxVector flux(const Problem& problem,
78 const Element& element,
79 const FVElementGeometry& fvGeometry,
80 const ElementVolumeVariables& elemVolVars,
81 const SubControlVolumeFace& scvf,
82 const int phaseIdx,
83 const ElementFluxVariablesCache& elemFluxVarsCache)
84 {
85 //this is to calculate the maxwellStefan diffusion in a multicomponent system.
86 //see: Multicomponent Mass Transfer. R. Taylor u. R. Krishna. J. Wiley & Sons, New York 1993
87 ComponentFluxVector componentFlux(0.0);
88 ReducedComponentMatrix reducedDiffusionMatrix(0.0);
89 ReducedComponentVector reducedFlux(0.0);
90 ComponentFluxVector moleFrac(0.0);
91 ReducedComponentVector normalX(0.0);
92
93 // evaluate gradX at integration point and interpolate density
94 const auto& fluxVarsCache = elemFluxVarsCache[scvf];
95 const auto& shapeValues = fluxVarsCache.shapeValues();
96
97 Scalar rho(0.0);
98 Scalar avgMolarMass(0.0);
99 for (auto&& scv : scvs(fvGeometry))
100 {
101 const auto& volVars = elemVolVars[scv];
102
103 // density interpolation
104 rho += volVars.density(phaseIdx)*shapeValues[scv.indexInElement()][0];
105 //average molar mass interpolation
106 avgMolarMass += volVars.averageMolarMass(phaseIdx)*shapeValues[scv.indexInElement()][0];
107 //interpolate the mole fraction for the diffusion matrix
108 for (int compIdx = 0; compIdx < numComponents; compIdx++)
109 {
110 moleFrac[compIdx] += volVars.moleFraction(phaseIdx, compIdx)*shapeValues[scv.indexInElement()][0];
111 }
112 }
113
114 reducedDiffusionMatrix = setupMSMatrix_(problem, element, fvGeometry, elemVolVars, scvf, phaseIdx, moleFrac, avgMolarMass);
115
116 for (int compIdx = 0; compIdx < numComponents-1; compIdx++)
117 {
118 Dune::FieldVector<Scalar, GridView::dimensionworld> gradX(0.0);
119 for (auto&& scv : scvs(fvGeometry))
120 {
121 const auto& volVars = elemVolVars[scv];
122
123 // the mole/mass fraction gradient
124 gradX.axpy(volVars.moleFraction(phaseIdx, compIdx), fluxVarsCache.gradN(scv.indexInElement()));
125 }
126
127 normalX[compIdx] = gradX *scvf.unitOuterNormal();
128 }
129 reducedDiffusionMatrix.solve(reducedFlux,normalX);
130 reducedFlux *= -1.0*rho*scvf.area();
131
132 for (int compIdx = 0; compIdx < numComponents-1; compIdx++)
133 {
134 componentFlux[compIdx] = reducedFlux[compIdx];
135 componentFlux[numComponents-1] -= reducedFlux[compIdx];
136 }
137 return componentFlux ;
138 }
139
140private:
141
142 static ReducedComponentMatrix setupMSMatrix_(const Problem& problem,
143 const Element& element,
144 const FVElementGeometry& fvGeometry,
145 const ElementVolumeVariables& elemVolVars,
146 const SubControlVolumeFace& scvf,
147 const int phaseIdx,
148 const ComponentFluxVector moleFrac,
149 const Scalar avgMolarMass)
150 {
151 ReducedComponentMatrix reducedDiffusionMatrix(0.0);
152
153 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
154 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
155 const auto insideScvIdx = scvf.insideScvIdx();
156 const auto outsideScvIdx = scvf.outsideScvIdx();
157
158 //this is to not devide by 0 if the saturation in 0 and the effectiveDiffusivity becomes zero due to that
159 if(Dune::FloatCmp::eq<Scalar>(insideVolVars.saturation(phaseIdx), 0) || Dune::FloatCmp::eq<Scalar>(outsideVolVars.saturation(phaseIdx), 0))
160 return reducedDiffusionMatrix;
161
162 for (int compIIdx = 0; compIIdx < numComponents-1; compIIdx++)
163 {
164 // effective diffusion tensors
166
167 //calculate diffusivity for i,numComponents
168 const auto xi = moleFrac[compIIdx];
169 const auto Mn = FluidSystem::molarMass(numComponents-1);
170 auto tinInside = getDiffusionCoefficient(phaseIdx, compIIdx, numComponents-1, problem, element, insideVolVars, fvGeometry.scv(insideScvIdx));
171 tinInside = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), tinInside);
172 auto tinOutside = getDiffusionCoefficient(phaseIdx, compIIdx, numComponents-1, problem, element, outsideVolVars, fvGeometry.scv(outsideScvIdx));
173 tinOutside = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), tinOutside);
174
175 // scale by extrusion factor
176 tinInside *= insideVolVars.extrusionFactor();
177 tinOutside *= outsideVolVars.extrusionFactor();
178
179 // the resulting averaged diffusion tensor
180 const auto tin = problem.spatialParams().harmonicMean(tinInside, tinOutside, scvf.unitOuterNormal());
181
182 //begin the entrys of the diffusion matrix of the diagonal
183 reducedDiffusionMatrix[compIIdx][compIIdx] += xi*avgMolarMass/(tin*Mn);
184
185 // now set the rest of the entries (off-diagonal and additional entries for diagonal)
186 for (int compJIdx = 0; compJIdx < numComponents; compJIdx++)
187 {
188 //we don't want to calculate e.g. water in water diffusion
189 if (compIIdx == compJIdx)
190 continue;
191
192 //calculate diffusivity for compIIdx, compJIdx
193 const auto xj = moleFrac[compJIdx];
194 const auto Mi = FluidSystem::molarMass(compIIdx);
195 const auto Mj = FluidSystem::molarMass(compJIdx);
196 auto tijInside = getDiffusionCoefficient(phaseIdx, compIIdx, compJIdx, problem, element, insideVolVars, fvGeometry.scv(insideScvIdx));
197 tijInside = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), tijInside);
198 auto tijOutside = getDiffusionCoefficient(phaseIdx, compIIdx, compJIdx, problem, element, outsideVolVars, fvGeometry.scv(outsideScvIdx));
199 tijOutside = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), tijOutside);
200
201 // scale by extrusion factor
202 tijInside *= insideVolVars.extrusionFactor();
203 tijOutside *= outsideVolVars.extrusionFactor();
204
205 // the resulting averaged diffusion tensor
206 const auto tij = problem.spatialParams().harmonicMean(tijInside, tijOutside, scvf.unitOuterNormal());
207
208 reducedDiffusionMatrix[compIIdx][compIIdx] += xj*avgMolarMass/(tij*Mi);
209 if (compJIdx < numComponents-1)
210 reducedDiffusionMatrix[compIIdx][compJIdx] +=xi*(avgMolarMass/(tin*Mn) - avgMolarMass/(tij*Mj));
211 }
212 }
213 return reducedDiffusionMatrix;
214 }
215
216private:
217 template <class T = TypeTag, typename std::enable_if_t<GetPropType<T, Properties::FluidSystem>::isTracerFluidSystem(), int> =0 >
218 static Scalar getDiffusionCoefficient(const int phaseIdx,
219 const int compIIdx,
220 const int compJIdx,
221 const Problem& problem,
222 const Element& element,
223 const VolumeVariables& volVars,
224 const SubControlVolume& scv)
225 {
226 return FluidSystem::binaryDiffusionCoefficient(compIIdx,
227 compJIdx,
228 problem,
229 element,
230 scv);
231 }
232
233 template <class T = TypeTag, typename std::enable_if_t<!GetPropType<T, Properties::FluidSystem>::isTracerFluidSystem(), int> =0 >
234 static Scalar getDiffusionCoefficient(const int phaseIdx,
235 const int compIIdx,
236 const int compJIdx,
237 const Problem& problem,
238 const Element& element,
239 const VolumeVariables& volVars,
240 const SubControlVolume& scv)
241 {
242 auto fluidState = volVars.fluidState();
243 typename FluidSystem::ParameterCache paramCache;
244 paramCache.updateAll(fluidState);
245 return FluidSystem::binaryDiffusionCoefficient(fluidState,
246 paramCache,
247 phaseIdx,
248 compIIdx,
249 compJIdx);
250 }
251
252};
253} // end namespace Dumux
254
255#endif
Define some often used mathematical functions.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The available discretization methods in Dumux.
Classes related to flux variables caching.
The reference frameworks and formulations available for splitting total fluxes into a advective and d...
DiscretizationMethod
The available discretization methods in Dumux.
Definition: method.hh:37
ReferenceSystemFormulation
The formulations available for Fick's law related to the reference system.
Definition: referencesystemformulation.hh:45
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
Definition: maxwellstefanslaw.hh:37
static constexpr ReferenceSystemFormulation referenceSystemFormulation()
Definition: box/maxwellstefanslaw.hh:74
static ComponentFluxVector flux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf, const int phaseIdx, const ElementFluxVariablesCache &elemFluxVarsCache)
Definition: box/maxwellstefanslaw.hh:77
Declares all properties used in Dumux.