3.3.0
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
porousmediumflow/tracer/localresidual.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 *****************************************************************************/
26#ifndef DUMUX_TRACER_LOCAL_RESIDUAL_HH
27#define DUMUX_TRACER_LOCAL_RESIDUAL_HH
28
29#include <dune/common/exceptions.hh>
30
36
37namespace Dumux {
38
44template<class TypeTag>
45class TracerLocalResidual: public GetPropType<TypeTag, Properties::BaseLocalResidual>
46{
51 using FVElementGeometry = typename GridGeometry::LocalView;
52 using SubControlVolume = typename GridGeometry::SubControlVolume;
53 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
54 using Extrusion = Extrusion_t<GridGeometry>;
57 using ElementFluxVariablesCache = typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView;
59 using Element = typename GridView::template Codim<0>::Entity;
60 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
63
64 static constexpr int numComponents = GetPropType<TypeTag, Properties::ModelTraits>::numFluidComponents();
65 static constexpr bool useMoles = getPropValue<TypeTag, Properties::UseMoles>();
66 static constexpr int phaseIdx = 0;
67
68public:
69 using ParentType::ParentType;
70
82 NumEqVector computeStorage(const Problem& problem,
83 const SubControlVolume& scv,
84 const VolumeVariables& volVars) const
85 {
86 NumEqVector storage(0.0);
87
88 // regularize saturation so we don't get singular matrices when the saturation is zero
89 // note that the fluxes will still be zero (zero effective diffusion coefficient),
90 // and we still solve the equation storage = 0 yielding the correct result
91 using std::max;
92 const Scalar saturation = max(1e-8, volVars.saturation(phaseIdx));
93
94 // formulation with mole balances
95 if (useMoles)
96 {
97 for (int compIdx = 0; compIdx < numComponents; ++compIdx)
98 storage[compIdx] += volVars.porosity()
99 * volVars.molarDensity(phaseIdx)
100 * volVars.moleFraction(phaseIdx, compIdx)
101 * saturation;
102 }
103 // formulation with mass balances
104 else
105 {
106 for (int compIdx = 0; compIdx < numComponents; ++compIdx)
107 storage[compIdx] += volVars.porosity()
108 * volVars.density(phaseIdx)
109 * volVars.massFraction(phaseIdx, compIdx)
110 * saturation;
111 }
112
113 return storage;
114 }
115
127 NumEqVector computeFlux(const Problem& problem,
128 const Element& element,
129 const FVElementGeometry& fvGeometry,
130 const ElementVolumeVariables& elemVolVars,
131 const SubControlVolumeFace& scvf,
132 const ElementFluxVariablesCache& elemFluxVarsCache) const
133 {
134 FluxVariables fluxVars;
135 fluxVars.init(problem, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
136
137 NumEqVector flux(0.0);
138 const auto diffusiveFluxes = fluxVars.molecularDiffusionFlux(phaseIdx);
139
140 static constexpr auto referenceSystemFormulation = FluxVariables::MolecularDiffusionType::referenceSystemFormulation();
141 // formulation with mole balances
142 if (useMoles)
143 {
144 for (int compIdx = 0; compIdx < numComponents; ++compIdx)
145 {
146 // the physical quantities for which we perform upwinding
147 auto upwindTerm = [compIdx](const auto& volVars)
148 { return volVars.molarDensity()*volVars.moleFraction(phaseIdx, compIdx); };
149
150 // advective fluxes
151 flux[compIdx] += fluxVars.advectiveFlux(phaseIdx, upwindTerm);
152 // diffusive fluxes
153 if (referenceSystemFormulation == ReferenceSystemFormulation::massAveraged)
154 flux[compIdx] += diffusiveFluxes[compIdx]/FluidSystem::molarMass(compIdx);
155 else if (referenceSystemFormulation == ReferenceSystemFormulation::molarAveraged)
156 flux[compIdx] += diffusiveFluxes[compIdx];
157 else
158 DUNE_THROW(Dune::NotImplemented, "other reference systems than mass and molar averaged are not implemented");
159 }
160 }
161 // formulation with mass balances
162 else
163 {
164 for (int compIdx = 0; compIdx < numComponents; ++compIdx)
165 {
166 // the physical quantities for which we perform upwinding
167 auto upwindTerm = [compIdx](const auto& volVars)
168 { return volVars.density()*volVars.massFraction(phaseIdx, compIdx); };
169
170 // advective fluxes
171 flux[compIdx] += fluxVars.advectiveFlux(phaseIdx, upwindTerm);
172 // diffusive fluxes
173 if (referenceSystemFormulation == ReferenceSystemFormulation::massAveraged)
174 flux[compIdx] += diffusiveFluxes[compIdx];
175 else if (referenceSystemFormulation == ReferenceSystemFormulation::molarAveraged)
176 flux[compIdx] += diffusiveFluxes[compIdx]*FluidSystem::molarMass(compIdx);
177 else
178 DUNE_THROW(Dune::NotImplemented, "other reference systems than mass and molar averaged are not implemented");
179 }
180 }
181
182 return flux;
183 }
184
195 template<class PartialDerivativeMatrix>
196 void addStorageDerivatives(PartialDerivativeMatrix& partialDerivatives,
197 const Problem& problem,
198 const Element& element,
199 const FVElementGeometry& fvGeometry,
200 const VolumeVariables& curVolVars,
201 const SubControlVolume& scv) const
202 {
203 // regularize saturation so we don't get singular matrices when the saturation is zero
204 // note that the fluxes will still be zero (zero effective diffusion coefficient),
205 // and we still solve the equation storage = 0 yielding the correct result
206 using std::max;
207 const auto saturation = max(1e-8, curVolVars.saturation(phaseIdx));
208
209 const auto porosity = curVolVars.porosity();
210 const auto rho = useMoles ? curVolVars.molarDensity() : curVolVars.density();
211 const auto d_storage = Extrusion::volume(scv)*porosity*rho*saturation/this->timeLoop().timeStepSize();
212
213 for (int compIdx = 0; compIdx < numComponents; ++compIdx)
214 partialDerivatives[compIdx][compIdx] += d_storage;
215 }
216
227 template<class PartialDerivativeMatrix>
228 void addSourceDerivatives(PartialDerivativeMatrix& partialDerivatives,
229 const Problem& problem,
230 const Element& element,
231 const FVElementGeometry& fvGeometry,
232 const VolumeVariables& curVolVars,
233 const SubControlVolume& scv) const
234 {
235 // TODO maybe forward to the problem? -> necessary for reaction terms
236 }
237
238 template<class PartialDerivativeMatrices, class T = TypeTag>
239 std::enable_if_t<GetPropType<T, Properties::GridGeometry>::discMethod != DiscretizationMethod::box, void>
240 addFluxDerivatives(PartialDerivativeMatrices& derivativeMatrices,
241 const Problem& problem,
242 const Element& element,
243 const FVElementGeometry& fvGeometry,
244 const ElementVolumeVariables& curElemVolVars,
245 const ElementFluxVariablesCache& elemFluxVarsCache,
246 const SubControlVolumeFace& scvf) const
247 {
248 if constexpr (FVElementGeometry::GridGeometry::discMethod != DiscretizationMethod::cctpfa)
249 DUNE_THROW(Dune::NotImplemented, "Analytic flux differentiation only implemented for tpfa");
250
251 // advective term: we do the same for all tracer components
252 auto rho = [](const VolumeVariables& volVars)
253 { return useMoles ? volVars.molarDensity() : volVars.density(); };
254
255 // the volume flux
256 const auto volFlux = problem.spatialParams().volumeFlux(element, fvGeometry, curElemVolVars, scvf);
257
258 // the upwind weight
259 static const Scalar upwindWeight = getParam<Scalar>("Flux.UpwindWeight");
260
261 // get the inside and outside volvars
262 const auto& insideVolVars = curElemVolVars[scvf.insideScvIdx()];
263 const auto& outsideVolVars = curElemVolVars[scvf.outsideScvIdx()];
264
265 const Scalar insideWeight = std::signbit(volFlux) ? (1.0 - upwindWeight) : upwindWeight;
266 const Scalar outsideWeight = 1.0 - insideWeight;
267 const auto advDerivII = volFlux*rho(insideVolVars)*insideWeight;
268 const auto advDerivIJ = volFlux*rho(outsideVolVars)*outsideWeight;
269
270 // diffusive term
271 static constexpr auto referenceSystemFormulation = FluxVariables::MolecularDiffusionType::referenceSystemFormulation();
272 const auto& fluxCache = elemFluxVarsCache[scvf];
273 const Scalar rhoInside = massOrMolarDensity(insideVolVars, referenceSystemFormulation, phaseIdx);
274 const Scalar rhoOutside = massOrMolarDensity(outsideVolVars, referenceSystemFormulation, phaseIdx);
275 const Scalar massOrMolarDensity = 0.5*(rhoInside + rhoOutside);
276
277 for (int compIdx = 0; compIdx < numComponents; ++compIdx)
278 {
279 // diffusive term
280 Scalar diffDeriv = 0.0;
281 if (referenceSystemFormulation == ReferenceSystemFormulation::massAveraged)
282 {
283 diffDeriv = useMoles ? massOrMolarDensity*fluxCache.diffusionTij(phaseIdx, compIdx)/FluidSystem::molarMass(compIdx)
284 : massOrMolarDensity*fluxCache.diffusionTij(phaseIdx, compIdx);
285 }
286 else if (referenceSystemFormulation == ReferenceSystemFormulation::molarAveraged)
287 {
288 diffDeriv = useMoles ? massOrMolarDensity*fluxCache.diffusionTij(phaseIdx, compIdx)
289 : massOrMolarDensity*fluxCache.diffusionTij(phaseIdx, compIdx)*FluidSystem::molarMass(compIdx);
290 }
291 else
292 DUNE_THROW(Dune::NotImplemented, "other reference systems than mass and molar averaged are not implemented");
293
294 derivativeMatrices[scvf.insideScvIdx()][compIdx][compIdx] += (advDerivII + diffDeriv);
295 if (!scvf.boundary())
296 derivativeMatrices[scvf.outsideScvIdx()][compIdx][compIdx] += (advDerivIJ - diffDeriv);
297 }
298 }
299
300 template<class JacobianMatrix, class T = TypeTag>
301 std::enable_if_t<GetPropType<T, Properties::GridGeometry>::discMethod == DiscretizationMethod::box, void>
302 addFluxDerivatives(JacobianMatrix& A,
303 const Problem& problem,
304 const Element& element,
305 const FVElementGeometry& fvGeometry,
306 const ElementVolumeVariables& curElemVolVars,
307 const ElementFluxVariablesCache& elemFluxVarsCache,
308 const SubControlVolumeFace& scvf) const
309 {
310
311 // advective term: we do the same for all tracer components
312 auto rho = [](const VolumeVariables& volVars)
313 { return useMoles ? volVars.molarDensity() : volVars.density(); };
314
315 // the volume flux
316 const auto volFlux = problem.spatialParams().volumeFlux(element, fvGeometry, curElemVolVars, scvf);
317
318 // the upwind weight
319 static const Scalar upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight");
320
321 // get the inside and outside volvars
322 const auto& insideVolVars = curElemVolVars[scvf.insideScvIdx()];
323 const auto& outsideVolVars = curElemVolVars[scvf.outsideScvIdx()];
324
325 const auto insideWeight = std::signbit(volFlux) ? (1.0 - upwindWeight) : upwindWeight;
326 const auto outsideWeight = 1.0 - insideWeight;
327 const auto advDerivII = volFlux*rho(insideVolVars)*insideWeight;
328 const auto advDerivIJ = volFlux*rho(outsideVolVars)*outsideWeight;
329
330 // diffusive term
331 static constexpr auto referenceSystemFormulation = FluxVariables::MolecularDiffusionType::referenceSystemFormulation();
333 const auto ti = DiffusionType::calculateTransmissibilities(problem,
334 element,
335 fvGeometry,
336 curElemVolVars,
337 scvf,
338 elemFluxVarsCache[scvf],
339 phaseIdx);
340 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
341 const auto& outsideScv = fvGeometry.scv(scvf.outsideScvIdx());
342
343 for (int compIdx = 0; compIdx < numComponents; ++compIdx)
344 {
345 for (const auto& scv : scvs(fvGeometry))
346 {
347 // diffusive term
348 auto diffDeriv = 0.0;
349 if (referenceSystemFormulation == ReferenceSystemFormulation::massAveraged)
350 diffDeriv += useMoles ? ti[compIdx][scv.indexInElement()]/FluidSystem::molarMass(compIdx)
351 : ti[compIdx][scv.indexInElement()];
352 else if (referenceSystemFormulation == ReferenceSystemFormulation::molarAveraged)
353 diffDeriv += useMoles ? ti[compIdx][scv.indexInElement()]
354 : ti[compIdx][scv.indexInElement()]*FluidSystem::molarMass(compIdx);
355 else
356 DUNE_THROW(Dune::NotImplemented, "other reference systems than mass and molar averaged are not implemented");
357 A[insideScv.dofIndex()][scv.dofIndex()][compIdx][compIdx] += diffDeriv;
358 A[outsideScv.dofIndex()][scv.dofIndex()][compIdx][compIdx] -= diffDeriv;
359 }
360
361 A[insideScv.dofIndex()][insideScv.dofIndex()][compIdx][compIdx] += advDerivII;
362 A[insideScv.dofIndex()][outsideScv.dofIndex()][compIdx][compIdx] += advDerivIJ;
363 A[outsideScv.dofIndex()][outsideScv.dofIndex()][compIdx][compIdx] -= advDerivII;
364 A[outsideScv.dofIndex()][insideScv.dofIndex()][compIdx][compIdx] -= advDerivIJ;
365 }
366 }
367
368 template<class PartialDerivativeMatrices>
369 void addCCDirichletFluxDerivatives(PartialDerivativeMatrices& derivativeMatrices,
370 const Problem& problem,
371 const Element& element,
372 const FVElementGeometry& fvGeometry,
373 const ElementVolumeVariables& curElemVolVars,
374 const ElementFluxVariablesCache& elemFluxVarsCache,
375 const SubControlVolumeFace& scvf) const
376 {
377 // do the same as for inner facets
378 addFluxDerivatives(derivativeMatrices, problem, element, fvGeometry,
379 curElemVolVars, elemFluxVarsCache, scvf);
380 }
381
382 template<class PartialDerivativeMatrices>
383 void addRobinFluxDerivatives(PartialDerivativeMatrices& derivativeMatrices,
384 const Problem& problem,
385 const Element& element,
386 const FVElementGeometry& fvGeometry,
387 const ElementVolumeVariables& curElemVolVars,
388 const ElementFluxVariablesCache& elemFluxVarsCache,
389 const SubControlVolumeFace& scvf) const
390 {
391 // TODO maybe forward to the problem?
392 }
393};
394
395} // end namespace Dumux
396
397#endif
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The available discretization methods in Dumux.
Helper classes to compute the integration elements.
The reference frameworks and formulations available for splitting total fluxes into a advective and d...
VolumeVariables::PrimaryVariables::value_type massOrMolarDensity(const VolumeVariables &volVars, ReferenceSystemFormulation referenceSys, const int phaseIdx)
evaluates the density to be used in Fick's law based on the reference system
Definition: referencesystemformulation.hh:55
Definition: adapt.hh:29
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:177
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
std::string saturation(int phaseIdx) noexcept
I/O name of saturation for multiphase systems.
Definition: name.hh:43
std::string porosity() noexcept
I/O name of porosity.
Definition: name.hh:139
Element-wise calculation of the local residual for problems using fully implicit tracer model.
Definition: porousmediumflow/tracer/localresidual.hh:46
NumEqVector computeStorage(const Problem &problem, const SubControlVolume &scv, const VolumeVariables &volVars) const
Evaluates the amount of all conservation quantities (e.g. phase mass) within a sub-control volume.
Definition: porousmediumflow/tracer/localresidual.hh:82
std::enable_if_t< GetPropType< T, Properties::GridGeometry >::discMethod==DiscretizationMethod::box, void > addFluxDerivatives(JacobianMatrix &A, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &curElemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf) const
Definition: porousmediumflow/tracer/localresidual.hh:302
void addRobinFluxDerivatives(PartialDerivativeMatrices &derivativeMatrices, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &curElemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf) const
Definition: porousmediumflow/tracer/localresidual.hh:383
void addSourceDerivatives(PartialDerivativeMatrix &partialDerivatives, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const VolumeVariables &curVolVars, const SubControlVolume &scv) const
TODO docme!
Definition: porousmediumflow/tracer/localresidual.hh:228
void addStorageDerivatives(PartialDerivativeMatrix &partialDerivatives, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const VolumeVariables &curVolVars, const SubControlVolume &scv) const
TODO docme!
Definition: porousmediumflow/tracer/localresidual.hh:196
NumEqVector computeFlux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf, const ElementFluxVariablesCache &elemFluxVarsCache) const
Evaluates the total flux of all conservation quantities over a face of a sub-control volume.
Definition: porousmediumflow/tracer/localresidual.hh:127
std::enable_if_t< GetPropType< T, Properties::GridGeometry >::discMethod !=DiscretizationMethod::box, void > addFluxDerivatives(PartialDerivativeMatrices &derivativeMatrices, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &curElemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf) const
Definition: porousmediumflow/tracer/localresidual.hh:240
void addCCDirichletFluxDerivatives(PartialDerivativeMatrices &derivativeMatrices, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &curElemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf) const
Definition: porousmediumflow/tracer/localresidual.hh:369
Declares all properties used in Dumux.