Line | Branch | Exec | Source |
---|---|---|---|
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 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup ThreePThreeCModel | ||
10 | * \brief Element-wise calculation of the Jacobian matrix for problems | ||
11 | * using the three-phase three-component fully implicit model. | ||
12 | */ | ||
13 | |||
14 | #ifndef DUMUX_3P3C_LOCAL_RESIDUAL_HH | ||
15 | #define DUMUX_3P3C_LOCAL_RESIDUAL_HH | ||
16 | |||
17 | #include <dumux/common/properties.hh> | ||
18 | #include <dumux/common/numeqvector.hh> | ||
19 | #include <dumux/flux/referencesystemformulation.hh> | ||
20 | |||
21 | namespace Dumux | ||
22 | { | ||
23 | /*! | ||
24 | * \ingroup ThreePThreeCModel | ||
25 | * \brief Element-wise calculation of the Jacobian matrix for problems | ||
26 | * using the three-phase three-component fully implicit model. | ||
27 | */ | ||
28 | template<class TypeTag> | ||
29 | class ThreePThreeCLocalResidual : public GetPropType<TypeTag, Properties::BaseLocalResidual> | ||
30 | { | ||
31 | using ParentType = GetPropType<TypeTag, Properties::BaseLocalResidual>; | ||
32 | using Problem = GetPropType<TypeTag, Properties::Problem>; | ||
33 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
34 | using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView; | ||
35 | using SubControlVolume = typename FVElementGeometry::SubControlVolume; | ||
36 | using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; | ||
37 | using NumEqVector = Dumux::NumEqVector<GetPropType<TypeTag, Properties::PrimaryVariables>>; | ||
38 | using FluxVariables = GetPropType<TypeTag, Properties::FluxVariables>; | ||
39 | using ElementFluxVariablesCache = typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView; | ||
40 | using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; | ||
41 | using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView; | ||
42 | using Element = typename GridView::template Codim<0>::Entity; | ||
43 | using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView; | ||
44 | using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>; | ||
45 | using EnergyLocalResidual = GetPropType<TypeTag, Properties::EnergyLocalResidual>; | ||
46 | using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>; | ||
47 | |||
48 | enum { | ||
49 | numPhases = GetPropType<TypeTag, Properties::ModelTraits>::numFluidPhases(), | ||
50 | numComponents = GetPropType<TypeTag, Properties::ModelTraits>::numFluidComponents(), | ||
51 | |||
52 | contiWEqIdx = Indices::conti0EqIdx + FluidSystem::wPhaseIdx,//!< index of the mass conservation equation for the water component | ||
53 | contiNEqIdx = Indices::conti0EqIdx + FluidSystem::nPhaseIdx,//!< index of the mass conservation equation for the contaminant component | ||
54 | contiGEqIdx = Indices::conti0EqIdx + FluidSystem::gPhaseIdx,//!< index of the mass conservation equation for the gas component | ||
55 | |||
56 | wPhaseIdx = FluidSystem::wPhaseIdx, | ||
57 | nPhaseIdx = FluidSystem::nPhaseIdx, | ||
58 | gPhaseIdx = FluidSystem::gPhaseIdx, | ||
59 | |||
60 | wCompIdx = FluidSystem::wCompIdx, | ||
61 | nCompIdx = FluidSystem::nCompIdx, | ||
62 | gCompIdx = FluidSystem::gCompIdx | ||
63 | }; | ||
64 | |||
65 | public: | ||
66 | |||
67 |
2/4✓ Branch 1 taken 134240 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 134240 times.
✗ Branch 5 not taken.
|
268480 | using ParentType::ParentType; |
68 | |||
69 | /*! | ||
70 | * \brief Evaluates the amount of all conservation quantities | ||
71 | * (e.g. phase mass) within a sub-control volume. | ||
72 | * | ||
73 | * The result should be averaged over the volume (e.g. phase mass | ||
74 | * inside a sub control volume divided by the volume) | ||
75 | * | ||
76 | * \param problem The problem | ||
77 | * \param scv The sub control volume | ||
78 | * \param volVars The volume variables | ||
79 | */ | ||
80 | 22236480 | NumEqVector computeStorage(const Problem& problem, | |
81 | const SubControlVolume& scv, | ||
82 | const VolumeVariables& volVars) const | ||
83 | { | ||
84 | 22236480 | NumEqVector storage(0.0); | |
85 | |||
86 | // compute storage term of all components within all phases | ||
87 |
2/2✓ Branch 0 taken 66709440 times.
✓ Branch 1 taken 22236480 times.
|
88945920 | for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) |
88 | { | ||
89 |
2/2✓ Branch 0 taken 200128320 times.
✓ Branch 1 taken 66709440 times.
|
266837760 | for (int compIdx = 0; compIdx < numComponents; ++compIdx) |
90 | { | ||
91 | 200128320 | auto eqIdx = Indices::conti0EqIdx + compIdx; | |
92 | 200128320 | storage[eqIdx] += volVars.porosity() | |
93 | 400256640 | * volVars.saturation(phaseIdx) | |
94 | 200128320 | * volVars.molarDensity(phaseIdx) | |
95 | 400256640 | * volVars.moleFraction(phaseIdx, compIdx); | |
96 | } | ||
97 | |||
98 | // The energy storage in the fluid phase with index phaseIdx | ||
99 | 133418880 | EnergyLocalResidual::fluidPhaseStorage(storage, problem, scv, volVars, phaseIdx); | |
100 | } | ||
101 | |||
102 | // The energy storage in the solid matrix | ||
103 | 44472960 | EnergyLocalResidual::solidPhaseStorage(storage, scv, volVars); | |
104 | |||
105 | 22236480 | return storage; | |
106 | } | ||
107 | |||
108 | /*! | ||
109 | * \brief Evaluates the total flux of all conservation quantities | ||
110 | * over a face of a sub-control volume. | ||
111 | * | ||
112 | * \param problem The problem | ||
113 | * \param element The element | ||
114 | * \param fvGeometry The finite volume element geometry | ||
115 | * \param elemVolVars The element volume variables | ||
116 | * \param scvf The sub control volume face | ||
117 | * \param elemFluxVarsCache The element flux variables cache | ||
118 | */ | ||
119 | 13474215 | NumEqVector computeFlux(const Problem& problem, | |
120 | const Element& element, | ||
121 | const FVElementGeometry& fvGeometry, | ||
122 | const ElementVolumeVariables& elemVolVars, | ||
123 | const SubControlVolumeFace& scvf, | ||
124 | const ElementFluxVariablesCache& elemFluxVarsCache) const | ||
125 | { | ||
126 | 13474215 | FluxVariables fluxVars; | |
127 | 13474215 | fluxVars.init(problem, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache); | |
128 | static constexpr auto referenceSystemFormulation = FluxVariables::MolecularDiffusionType::referenceSystemFormulation(); | ||
129 | |||
130 | // get upwind weights into local scope | ||
131 | 13474215 | NumEqVector flux(0.0); | |
132 | |||
133 | // advective fluxes | ||
134 |
2/2✓ Branch 0 taken 40422645 times.
✓ Branch 1 taken 13474215 times.
|
53896860 | for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) |
135 | { | ||
136 |
2/2✓ Branch 0 taken 121267935 times.
✓ Branch 1 taken 40422645 times.
|
161690580 | for (int compIdx = 0; compIdx < numComponents; ++compIdx) |
137 | { | ||
138 | 848875545 | auto upwindTerm = [phaseIdx, compIdx](const VolumeVariables& volVars) | |
139 | 970143480 | { return volVars.molarDensity(phaseIdx)*volVars.moleFraction(phaseIdx, compIdx)*volVars.mobility(phaseIdx); }; | |
140 | |||
141 | // get equation index | ||
142 | 121267935 | auto eqIdx = Indices::conti0EqIdx + compIdx; | |
143 | 121267935 | flux[eqIdx] += fluxVars.advectiveFlux(phaseIdx, upwindTerm); | |
144 | } | ||
145 | |||
146 | // Add advective phase energy fluxes. For isothermal model the contribution is zero. | ||
147 | 40422645 | EnergyLocalResidual::heatConvectionFlux(flux, fluxVars, phaseIdx); | |
148 | } | ||
149 | |||
150 | // Add diffusive energy fluxes. For isothermal model the contribution is zero. | ||
151 | 13474215 | EnergyLocalResidual::heatConductionFlux(flux, fluxVars); | |
152 | |||
153 | // diffusive fluxes | ||
154 | 13474215 | const auto diffusionFluxesWPhase = fluxVars.molecularDiffusionFlux(wPhaseIdx); | |
155 | 13474215 | Scalar jGW = diffusionFluxesWPhase[gCompIdx]; | |
156 | 13474215 | Scalar jNW = diffusionFluxesWPhase[nCompIdx]; | |
157 | 13474215 | Scalar jWW = -(jGW+jNW); | |
158 | |||
159 | //check for the reference system and adapt units of the diffusive flux accordingly. | ||
160 | if (referenceSystemFormulation == ReferenceSystemFormulation::massAveraged) | ||
161 | { | ||
162 | 13474215 | jGW /= FluidSystem::molarMass(gCompIdx); | |
163 | 13474215 | jNW /= FluidSystem::molarMass(nCompIdx); | |
164 | 13474215 | jWW /= FluidSystem::molarMass(wCompIdx); | |
165 | } | ||
166 | |||
167 | 13474215 | const auto diffusionFluxesGPhase = fluxVars.molecularDiffusionFlux(gPhaseIdx); | |
168 | 13474215 | Scalar jWG = diffusionFluxesGPhase[wCompIdx]; | |
169 | 13474215 | Scalar jNG = diffusionFluxesGPhase[nCompIdx]; | |
170 | 13474215 | Scalar jGG = -(jWG+jNG); | |
171 | |||
172 | //check for the reference system and adapt units of the diffusive flux accordingly. | ||
173 | if (referenceSystemFormulation == ReferenceSystemFormulation::massAveraged) | ||
174 | { | ||
175 | 13474215 | jWG /= FluidSystem::molarMass(wCompIdx); | |
176 | 13474215 | jNG /= FluidSystem::molarMass(nCompIdx); | |
177 | 13474215 | jGG /= FluidSystem::molarMass(gCompIdx); | |
178 | } | ||
179 | |||
180 | // At the moment we do not consider diffusion in the NAPL phase | ||
181 | 13474215 | const Scalar jWN = 0.0; | |
182 | 13474215 | const Scalar jGN = 0.0; | |
183 | 13474215 | const Scalar jNN = 0.0; | |
184 | |||
185 | 26948430 | flux[contiWEqIdx] += jWW+jWG+jWN; | |
186 | 26948430 | flux[contiNEqIdx] += jNW+jNG+jNN; | |
187 | 26948430 | flux[contiGEqIdx] += jGW+jGG+jGN; | |
188 | |||
189 | 13474215 | return flux; | |
190 | } | ||
191 | }; | ||
192 | |||
193 | } // end namespace Dumux | ||
194 | |||
195 | #endif | ||
196 |