version 3.10-dev
cctpfa/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// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
13#ifndef DUMUX_DISCRETIZATION_CC_TPFA_MAXWELL_STEFAN_LAW_HH
14#define DUMUX_DISCRETIZATION_CC_TPFA_MAXWELL_STEFAN_LAW_HH
15
16#include <dune/common/fmatrix.hh>
17#include <dune/common/float_cmp.hh>
18
21
27
28namespace Dumux {
29
30// forward declaration
31template <class TypeTag, class DiscretizationMethod, ReferenceSystemFormulation referenceSystem>
32class MaxwellStefansLawImplementation;
33
38template <class TypeTag, ReferenceSystemFormulation referenceSystem>
39class MaxwellStefansLawImplementation<TypeTag, DiscretizationMethods::CCTpfa, referenceSystem >
40{
44 using FVElementGeometry = typename GridGeometry::LocalView;
45 using SubControlVolume = typename GridGeometry::SubControlVolume;
46 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
47 using Extrusion = Extrusion_t<GridGeometry>;
48 using GridView = typename GridGeometry::GridView;
50 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
51 using Element = typename GridView::template Codim<0>::Entity;
53 using ElementFluxVariablesCache = typename GridFluxVariablesCache::LocalView;
54 using FluxVariablesCache = typename GridFluxVariablesCache::FluxVariablesCache;
56
57 static const int dim = GridView::dimension;
58 static const int dimWorld = GridView::dimensionworld;
61
62 static_assert(referenceSystem == ReferenceSystemFormulation::massAveraged, "only the mass averaged reference system is supported for the Maxwell-Stefan formulation");
63
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
69public:
71 // state the discretization method this implementation belongs to
72 static constexpr DiscretizationMethod discMethod{};
73
74 //return the reference system
76 { return referenceSystem; }
77
79
84
90 static ComponentFluxVector flux(const Problem& problem,
91 const Element& element,
92 const FVElementGeometry& fvGeometry,
93 const ElementVolumeVariables& elemVolVars,
94 const SubControlVolumeFace& scvf,
95 const int phaseIdx,
96 const ElementFluxVariablesCache& elemFluxVarsCache)
97 {
98 //this is to calculate the maxwellStefan diffusion in a multicomponent system.
99 //see: Multicomponent Mass Transfer. R. Taylor u. R. Krishna. J. Wiley & Sons, New York 1993
100 ComponentFluxVector componentFlux(0.0);
101 ReducedComponentVector moleFracInside(0.0);
102 ReducedComponentVector moleFracOutside(0.0);
103 ReducedComponentVector reducedFlux(0.0);
104 ReducedComponentMatrix reducedDiffusionMatrixInside(0.0);
105 ReducedComponentMatrix reducedDiffusionMatrixOutside(0.0);
106
107 // get inside/outside volume variables
108 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
109 const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
110 const auto rhoInside = insideVolVars.density(phaseIdx);
111 const auto rhoOutside = outsideVolVars.density(phaseIdx);
112 //calculate the mole fraction vectors
113 for (int compIdx = 0; compIdx < numComponents-1; compIdx++)
114 {
115 //calculate x_inside
116 const auto xInside = insideVolVars.moleFraction(phaseIdx, compIdx);
117 //calculate outside molefraction with the respective transmissibility
118 const auto xOutside = outsideVolVars.moleFraction(phaseIdx, compIdx);
119
120 moleFracInside[compIdx] = xInside;
121 moleFracOutside[compIdx] = xOutside;
122 }
123
124 //we cannot solve that if the matrix is 0 everywhere
125 if(!(Dune::FloatCmp::eq<Scalar>(insideVolVars.saturation(phaseIdx), 0) || Dune::FloatCmp::eq<Scalar>(outsideVolVars.saturation(phaseIdx), 0)))
126 {
127 const auto insideScvIdx = scvf.insideScvIdx();
128 const auto& insideScv = fvGeometry.scv(insideScvIdx);
129 const Scalar omegai = calculateOmega_(scvf,
130 insideScv,
131 insideVolVars.extrusionFactor());
132
133 //now we have to do the tpfa: J_i = J_j which leads to: tij(xi -xj) = -rho Bi^-1 omegai(x*-xi) with x* = (omegai Bi^-1 + omegaj Bj^-1)^-1 (xi omegai Bi^-1 + xj omegaj Bj^-1) with i inside and j outside
134 reducedDiffusionMatrixInside = setupMSMatrix_(problem, element, fvGeometry, insideVolVars, insideScv, phaseIdx);
135
136 //if on boundary
137 if (scvf.boundary() || scvf.numOutsideScvs() > 1)
138 {
139 moleFracOutside -= moleFracInside;
140 reducedDiffusionMatrixInside.solve(reducedFlux, moleFracOutside);
141 reducedFlux *= omegai*rhoInside;
142 }
143 else //we need outside cells as well if we are not on the boundary
144 {
145 Scalar omegaj;
146 const auto outsideScvIdx = scvf.outsideScvIdx();
147 const auto& outsideScv = fvGeometry.scv(outsideScvIdx);
148
149 reducedDiffusionMatrixOutside = setupMSMatrix_(problem, element, fvGeometry, outsideVolVars, outsideScv, phaseIdx);
150
151 if (dim == dimWorld)
152 // assume the normal vector from outside is anti parallel so we save flipping a vector
153 omegaj = -1.0*calculateOmega_(scvf,
154 outsideScv,
155 outsideVolVars.extrusionFactor());
156 else
157 omegaj = calculateOmega_(fvGeometry.flipScvf(scvf.index()),
158 outsideScv,
159 outsideVolVars.extrusionFactor());
160
161 reducedDiffusionMatrixInside.invert();
162 reducedDiffusionMatrixOutside.invert();
163 reducedDiffusionMatrixInside *= omegai*rhoInside;
164 reducedDiffusionMatrixOutside *= omegaj*rhoOutside;
165
166 //in the helpervector we store the values for x*
167 ReducedComponentVector helperVector(0.0);
168 ReducedComponentVector gradientVectori(0.0);
169 ReducedComponentVector gradientVectorj(0.0);
170
171 reducedDiffusionMatrixInside.mv(moleFracInside, gradientVectori);
172 reducedDiffusionMatrixOutside.mv(moleFracOutside, gradientVectorj);
173
174 auto gradientVectorij = (gradientVectori + gradientVectorj);
175
176 //add the two matrixes to each other
177 reducedDiffusionMatrixOutside += reducedDiffusionMatrixInside;
178
179 reducedDiffusionMatrixOutside.solve(helperVector, gradientVectorij);
180
181 //Bi^-1 omegai rho(x*-xi)
182 helperVector -=moleFracInside;
183 reducedDiffusionMatrixInside.mv(helperVector, reducedFlux);
184 }
185
186 reducedFlux *= -Extrusion::area(fvGeometry, scvf);
187 for (int compIdx = 0; compIdx < numComponents-1; compIdx++)
188 {
189 componentFlux[compIdx] = reducedFlux[compIdx];
190 componentFlux[numComponents-1] -=reducedFlux[compIdx];
191 }
192 }
193 return componentFlux ;
194 }
195
196private:
197 static Scalar calculateOmega_(const SubControlVolumeFace& scvf,
198 const SubControlVolume &scv,
199 const Scalar extrusionFactor)
200 {
201 auto distanceVector = scvf.ipGlobal();
202 distanceVector -= scv.center();
203 distanceVector /= distanceVector.two_norm2();
204
205 Scalar omega = (distanceVector * scvf.unitOuterNormal());
206 omega *= extrusionFactor;
207
208 return omega;
209 }
210
211 static ReducedComponentMatrix setupMSMatrix_(const Problem& problem,
212 const Element& element,
213 const FVElementGeometry& fvGeometry,
214 const VolumeVariables& volVars,
215 const SubControlVolume& scv,
216 const int phaseIdx)
217 {
218 ReducedComponentMatrix reducedDiffusionMatrix(0.0);
219
220 //this is to not divide by 0 if the saturation in 0 and the effectiveDiffusionCoefficient becomes zero due to that
221 if(Dune::FloatCmp::eq<Scalar>(volVars.saturation(phaseIdx), 0))
222 return reducedDiffusionMatrix;
223
224 const auto avgMolarMass = volVars.averageMolarMass(phaseIdx);
225
226 for (int compIIdx = 0; compIIdx < numComponents-1; compIIdx++)
227 {
228 const auto xi = volVars.moleFraction(phaseIdx, compIIdx);
229
230 const auto Mn = FluidSystem::molarMass(numComponents-1);
231 Scalar tin = volVars.effectiveDiffusionCoefficient(phaseIdx, compIIdx, numComponents-1);
232
233 // set the entries of the diffusion matrix of the diagonal
234 reducedDiffusionMatrix[compIIdx][compIIdx] += xi*avgMolarMass/(tin*Mn);
235
236 // now set the rest of the entries (off-diagonal and additional entries for diagonal)
237 for (int compJIdx = 0; compJIdx < numComponents; compJIdx++)
238 {
239 // we don't want to calculate e.g. water in water diffusion
240 if (compJIdx == compIIdx)
241 continue;
242
243 const auto xj = volVars.moleFraction(phaseIdx, compJIdx);
244 const auto Mi = FluidSystem::molarMass(compIIdx);
245 const auto Mj = FluidSystem::molarMass(compJIdx);
246 Scalar tij = volVars.effectiveDiffusionCoefficient(phaseIdx, compIIdx, compJIdx);
247 reducedDiffusionMatrix[compIIdx][compIIdx] += xj*avgMolarMass/(tij*Mi);
248
249 if (compJIdx < numComponents-1)
250 reducedDiffusionMatrix[compIIdx][compJIdx] += xi*(avgMolarMass/(tin*Mn) - avgMolarMass/(tij*Mj));
251 }
252 }
253 return reducedDiffusionMatrix;
254 }
255
256};
257} // end namespace
258
259#endif
Container storing the diffusion coefficients required by the Maxwell- Stefan diffusion law....
Definition: maxwellstefandiffusioncoefficients.hh:33
static constexpr ReferenceSystemFormulation referenceSystemFormulation()
Definition: cctpfa/maxwellstefanslaw.hh:75
static ComponentFluxVector flux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf, const int phaseIdx, const ElementFluxVariablesCache &elemFluxVarsCache)
Returns the diffusive fluxes of all components within a fluid phase across the given sub-control volu...
Definition: cctpfa/maxwellstefanslaw.hh:90
Definition: box/maxwellstefanslaw.hh:33
Defines all properties used in Dumux.
Helper classes to compute the integration elements.
Classes related to flux variables caching.
ReferenceSystemFormulation
The formulations available for Fick's law related to the reference system.
Definition: referencesystemformulation.hh:33
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
Container storing the diffusion coefficients required by the Maxwell- Stefan diffusion law....
The available discretization methods in Dumux.
Definition: adapt.hh:17
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:166
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The reference frameworks and formulations available for splitting total fluxes into a advective and d...
Definition: method.hh:25
The empty filler class corresponding to EmptyCache.
Definition: fluxvariablescaching.hh:20
Definition: fluxvariablescaching.hh:55