26#ifndef DUMUX_NONEQUILIBRIUM_LOCAL_RESIDUAL_HH
27#define DUMUX_NONEQUILIBRIUM_LOCAL_RESIDUAL_HH
35template<
class TypeTag,
bool enableChemicalNonEquilibrium>
38template <
class TypeTag>
45template<
class TypeTag>
53 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
54 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
58 using Element =
typename GridView::template Codim<0>::Entity;
65 static constexpr int numPhases = ModelTraits::numFluidPhases();
66 static constexpr int numComponents = ModelTraits::numFluidComponents();
67 enum { conti0EqIdx = Indices::conti0EqIdx };
69 using ParentType::ParentType;
87 const Element& element,
88 const FVElementGeometry& fvGeometry,
89 const ElementVolumeVariables& elemVolVars,
90 const SubControlVolumeFace& scvf,
91 const ElementFluxVariablesCache& elemFluxVarsCache)
const
93 FluxVariables fluxVars;
94 fluxVars.init(problem, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
96 NumEqVector flux(0.0);
98 const auto moleDensity = [](
const auto& volVars,
const int phaseIdx)
99 {
return volVars.molarDensity(phaseIdx); };
101 const auto moleFraction= [](
const auto& volVars,
const int phaseIdx,
const int compIdx)
102 {
return volVars.moleFraction(phaseIdx, compIdx); };
105 for (
int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
107 const auto diffusiveFluxes = fluxVars.molecularDiffusionFlux(phaseIdx);
108 for (
int compIdx = 0; compIdx < numComponents; ++compIdx)
111 const auto eqIdx = conti0EqIdx + compIdx;
114 const auto upwindTerm = [&moleDensity, &
moleFraction, phaseIdx, compIdx] (
const auto& volVars)
115 {
return moleDensity(volVars, phaseIdx)*
moleFraction(volVars, phaseIdx, compIdx)*volVars.mobility(phaseIdx); };
117 flux[eqIdx] += fluxVars.advectiveFlux(phaseIdx, upwindTerm);
122 flux[eqIdx] += diffusiveFluxes[compIdx]/FluidSystem::molarMass(compIdx);
124 flux[eqIdx] += diffusiveFluxes[compIdx];
128 EnergyLocalResidual::heatConvectionFlux(flux, fluxVars, phaseIdx);
131 EnergyLocalResidual::heatConductionFlux(flux, fluxVars);
139 const Element& element,
140 const FVElementGeometry& fvGeometry,
141 const ElementVolumeVariables& elemVolVars,
142 const SubControlVolume &scv)
const
144 NumEqVector source(0.0);
147 source += problem.source(element, fvGeometry, elemVolVars, scv);
150 source += problem.scvPointSources(element, fvGeometry, elemVolVars, scv);
153 EnergyLocalResidual::computeSourceEnergy(source,
166template<
class TypeTag>
174 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
175 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
180 using Element =
typename GridView::template Codim<0>::Entity;
190 static constexpr int numPhases = ModelTraits::numFluidPhases();
191 static constexpr int numComponents = ModelTraits::numFluidComponents();
192 static constexpr bool useMoles = getPropValue<TypeTag, Properties::UseMoles>();
194 static constexpr auto conti0EqIdx = Indices::conti0EqIdx;
195 static constexpr auto comp1Idx = FluidSystem::comp1Idx;
196 static constexpr auto comp0Idx = FluidSystem::comp0Idx;
197 static constexpr auto phase0Idx = FluidSystem::phase0Idx;
198 static constexpr auto phase1Idx = FluidSystem::phase1Idx;
200 static_assert(numPhases == numComponents,
201 "currently chemical non-equilibrium is only available when numPhases equals numComponents");
202 static_assert(useMoles ==
true,
203 "chemical nonequilibrium can only be calculated based on mole fractions not mass fractions");
206 using ParentType::ParentType;
215 const SubControlVolume& scv,
216 const VolumeVariables& volVars)
const
218 NumEqVector storage(0.0);
221 for (
int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
223 for (
int compIdx = 0; compIdx < numComponents; ++compIdx)
225 auto eqIdx = conti0EqIdx + phaseIdx*numComponents + compIdx;
226 storage[eqIdx] += volVars.porosity()
227 * volVars.saturation(phaseIdx)
228 * volVars.molarDensity(phaseIdx)
229 * volVars.moleFraction(phaseIdx, compIdx);
232 EnergyLocalResidual::fluidPhaseStorage(storage, scv, volVars, phaseIdx);
235 EnergyLocalResidual::solidPhaseStorage(storage, scv, volVars);
250 const Element& element,
251 const FVElementGeometry& fvGeometry,
252 const ElementVolumeVariables& elemVolVars,
253 const SubControlVolumeFace& scvf,
254 const ElementFluxVariablesCache& elemFluxVarsCache)
const
256 FluxVariables fluxVars;
257 fluxVars.init(problem, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
259 NumEqVector flux(0.0);
262 for (
int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
264 const auto diffusiveFluxes = fluxVars.molecularDiffusionFlux(phaseIdx);
265 for (
int compIdx = 0; compIdx < numComponents; ++compIdx)
268 const auto eqIdx = conti0EqIdx + phaseIdx*numComponents + compIdx;
271 const auto upwindTerm = [phaseIdx, compIdx] (
const auto& volVars)
272 {
return volVars.molarDensity(phaseIdx)*volVars.moleFraction(phaseIdx, compIdx)*volVars.mobility(phaseIdx); };
274 flux[eqIdx] += fluxVars.advectiveFlux(phaseIdx, upwindTerm);
277 if (compIdx == phaseIdx)
281 flux[eqIdx] += diffusiveFluxes[compIdx]/FluidSystem::molarMass(compIdx);
283 flux[eqIdx] += diffusiveFluxes[compIdx];
286 EnergyLocalResidual::heatConvectionFlux(flux, fluxVars, phaseIdx);
290 EnergyLocalResidual::heatConductionFlux(flux, fluxVars);
305 const Element& element,
306 const FVElementGeometry& fvGeometry,
307 const ElementVolumeVariables& elemVolVars,
308 const SubControlVolume &scv)
const
310 NumEqVector source(0.0);
314 const auto& volVars = elemVolVars[scv];
315 std::array<std::array<Scalar, numComponents>, numPhases> componentIntoPhaseMassTransfer = {{{0.0},{0.0}}};
318 const Scalar characteristicLength = volVars.characteristicLength() ;
319 const Scalar factorMassTransfer = volVars.factorMassTransfer() ;
321 const Scalar awn = volVars.interfacialArea(phase0Idx, phase1Idx);
323 for(
int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
325 const Scalar sherwoodNumber = volVars.sherwoodNumber(phaseIdx);
327 for (
int compIdx = 0; compIdx < numComponents; ++compIdx)
329 if (compIdx <= numPhases)
332 if (phaseIdx == compIdx)
335 const Scalar xNonEquil = volVars.moleFraction(phaseIdx, compIdx);
338 const Scalar xEquil = volVars.xEquil(phaseIdx, compIdx);
340 const Scalar diffCoeff = volVars.diffusionCoefficient(phaseIdx, compIdx);
343 const Scalar compFluxIntoOtherPhase = factorMassTransfer * (xEquil-xNonEquil)/characteristicLength * awn * volVars.molarDensity(phaseIdx) * diffCoeff * sherwoodNumber;
345 componentIntoPhaseMassTransfer[phaseIdx][compIdx] += compFluxIntoOtherPhase;
346 componentIntoPhaseMassTransfer[compIdx][compIdx] += -compFluxIntoOtherPhase;
353 for (
int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
355 for (
int compIdx = 0; compIdx < numComponents; ++compIdx)
357 const unsigned int eqIdx = conti0EqIdx + compIdx + phaseIdx*numComponents;
358 source[eqIdx] += componentIntoPhaseMassTransfer[phaseIdx][compIdx];
361 if (!isfinite(source[eqIdx]))
366 if (ModelTraits::enableThermalNonEquilibrium())
370 EnergyLocalResidual::computeSourceEnergy(source,
378 source += problem.source(element, fvGeometry, elemVolVars, scv);
381 source += problem.scvPointSources(element, fvGeometry, elemVolVars, scv);
bool CheckDefined(const T &value)
Make valgrind complain if the object occupied by an object is undefined.
Definition: valgrind.hh:72
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
Property tag Indices
Definition: porousmediumflow/sequential/properties.hh:59
std::string moleFraction(int phaseIdx, int compIdx) noexcept
I/O name of mole fraction.
Definition: name.hh:110
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:39
Definition: porousmediumflow/nonequilibrium/localresidual.hh:36
NumEqVector computeSource(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolume &scv) const
Definition: porousmediumflow/nonequilibrium/localresidual.hh:138
NumEqVector computeFlux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf, const ElementFluxVariablesCache &elemFluxVarsCache) const
Calculates the source term of the equation.
Definition: porousmediumflow/nonequilibrium/localresidual.hh:86
NumEqVector computeSource(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolume &scv) const
Calculates the source term of the equation.
Definition: porousmediumflow/nonequilibrium/localresidual.hh:304
NumEqVector computeStorage(const Problem &problem, const SubControlVolume &scv, const VolumeVariables &volVars) const
Calculates the storage for all mass balance equations.
Definition: porousmediumflow/nonequilibrium/localresidual.hh:214
NumEqVector computeFlux(const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolumeFace &scvf, const ElementFluxVariablesCache &elemFluxVarsCache) const
Calculates the flux for all mass balance equations.
Definition: porousmediumflow/nonequilibrium/localresidual.hh:249
Declares all properties used in Dumux.
This file contains the parts of the local residual to calculate the heat conservation in the thermal ...