3.3.0
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
2p/incompressiblelocalresidual.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_2P_INCOMPRESSIBLE_TEST_LOCAL_RESIDUAL_HH
27#define DUMUX_2P_INCOMPRESSIBLE_TEST_LOCAL_RESIDUAL_HH
28
29#include <cmath>
30
33
37
40
42
43namespace Dumux {
44
50template<class TypeTag>
52{
57 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
60 using ElementFluxVariablesCache = typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView;
63 using FVElementGeometry = typename GridGeometry::LocalView;
64 using SubControlVolume = typename GridGeometry::SubControlVolume;
65 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
66 using Extrusion = Extrusion_t<GridGeometry>;
68 using Element = typename GridView::template Codim<0>::Entity;
71
72 static constexpr int numPhases = ModelTraits::numFluidPhases();
73 static constexpr int pressureIdx = ModelTraits::Indices::pressureIdx;
74 static constexpr int saturationIdx = ModelTraits::Indices::saturationIdx;
75 static constexpr int conti0EqIdx = ModelTraits::Indices::conti0EqIdx;
76
77public:
78 using ParentType::ParentType;
79
93 template<class PartialDerivativeMatrix>
94 void addStorageDerivatives(PartialDerivativeMatrix& partialDerivatives,
95 const Problem& problem,
96 const Element& element,
97 const FVElementGeometry& fvGeometry,
98 const VolumeVariables& curVolVars,
99 const SubControlVolume& scv) const
100 {
101 static_assert(!FluidSystem::isCompressible(0),
102 "2p/incompressiblelocalresidual.hh: Only incompressible fluids are allowed!");
103 static_assert(!FluidSystem::isCompressible(1),
104 "2p/incompressiblelocalresidual.hh: Only incompressible fluids are allowed!");
105 static_assert(ModelTraits::numFluidPhases() == 2,
106 "2p/incompressiblelocalresidual.hh: Only two-phase models are allowed!");
107 static_assert(ModelTraits::priVarFormulation() == TwoPFormulation::p0s1,
108 "2p/incompressiblelocalresidual.hh: Analytic differentiation has to be checked for p1-s0 formulation!");
109
110 const auto poreVolume = Extrusion::volume(scv)*curVolVars.porosity();
111 const auto dt = this->timeLoop().timeStepSize();
112
113 // partial derivative of the phase storage terms w.r.t. S_n
114 partialDerivatives[conti0EqIdx+0][saturationIdx] -= poreVolume*curVolVars.density(0)/dt;
115 partialDerivatives[conti0EqIdx+1][saturationIdx] += poreVolume*curVolVars.density(1)/dt;
116 }
117
128 template<class PartialDerivativeMatrix>
129 void addSourceDerivatives(PartialDerivativeMatrix& partialDerivatives,
130 const Problem& problem,
131 const Element& element,
132 const FVElementGeometry& fvGeometry,
133 const VolumeVariables& curVolVars,
134 const SubControlVolume& scv) const
135 { /* TODO maybe forward to problem for the user to implement the source derivatives?*/ }
136
151 template<class PartialDerivativeMatrices, class T = TypeTag>
152 std::enable_if_t<GetPropType<T, Properties::GridGeometry>::discMethod == DiscretizationMethod::cctpfa, void>
153 addFluxDerivatives(PartialDerivativeMatrices& derivativeMatrices,
154 const Problem& problem,
155 const Element& element,
156 const FVElementGeometry& fvGeometry,
157 const ElementVolumeVariables& curElemVolVars,
158 const ElementFluxVariablesCache& elemFluxVarsCache,
159 const SubControlVolumeFace& scvf) const
160 {
161 static_assert(!FluidSystem::isCompressible(0),
162 "2p/incompressiblelocalresidual.hh: Only incompressible fluids are allowed!");
163 static_assert(!FluidSystem::isCompressible(1),
164 "2p/incompressiblelocalresidual.hh: Only incompressible fluids are allowed!");
165 static_assert(FluidSystem::viscosityIsConstant(0),
166 "2p/incompressiblelocalresidual.hh: Only fluids with constant viscosities are allowed!");
167 static_assert(FluidSystem::viscosityIsConstant(1),
168 "2p/incompressiblelocalresidual.hh: Only fluids with constant viscosities are allowed!");
169 static_assert(ModelTraits::numFluidPhases() == 2,
170 "2p/incompressiblelocalresidual.hh: Only two-phase models are allowed!");
171 static_assert(ModelTraits::priVarFormulation() == TwoPFormulation::p0s1,
172 "2p/incompressiblelocalresidual.hh: Analytic differentiation has to be checked for p1-s0 formulation!");
173
175
176 // evaluate the current wetting phase Darcy flux and resulting upwind weights
177 static const Scalar upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight");
178 const auto flux_w = AdvectionType::flux(problem, element, fvGeometry, curElemVolVars, scvf, 0, elemFluxVarsCache);
179 const auto flux_n = AdvectionType::flux(problem, element, fvGeometry, curElemVolVars, scvf, 1, elemFluxVarsCache);
180 const auto insideWeight_w = std::signbit(flux_w) ? (1.0 - upwindWeight) : upwindWeight;
181 const auto outsideWeight_w = 1.0 - insideWeight_w;
182 const auto insideWeight_n = std::signbit(flux_n) ? (1.0 - upwindWeight) : upwindWeight;
183 const auto outsideWeight_n = 1.0 - insideWeight_n;
184
185 // get references to the two participating vol vars & parameters
186 const auto insideScvIdx = scvf.insideScvIdx();
187 const auto outsideScvIdx = scvf.outsideScvIdx();
188 const auto outsideElement = fvGeometry.gridGeometry().element(outsideScvIdx);
189 const auto& insideScv = fvGeometry.scv(insideScvIdx);
190 const auto& outsideScv = fvGeometry.scv(outsideScvIdx);
191 const auto& insideVolVars = curElemVolVars[insideScvIdx];
192 const auto& outsideVolVars = curElemVolVars[outsideScvIdx];
193
194 // old material law interface is deprecated: Replace this by
195 // const auto& insidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element,
196 // insideScv,
197 // elementSolution<FVElementGeometry>(insideVolVars.priVars()));
198 // const auto& outsidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(outsideElement,
199 // outsideScv,
200 // elementSolution<FVElementGeometry>(outsideVolVars.priVars()));
201 // after the release of 3.3, when the deprecated interface is no longer supported
202 const auto& insidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(),
203 element,
204 insideScv,
205 elementSolution<FVElementGeometry>(insideVolVars.priVars()));
206 const auto& outsidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(),
207 outsideElement,
208 outsideScv,
209 elementSolution<FVElementGeometry>(outsideVolVars.priVars()));
210
211 // get references to the two participating derivative matrices
212 auto& dI_dI = derivativeMatrices[insideScvIdx];
213 auto& dI_dJ = derivativeMatrices[outsideScvIdx];
214
215 // some quantities to be reused (rho & mu are constant and thus equal for all cells)
216 static const auto rho_w = insideVolVars.density(0);
217 static const auto rho_n = insideVolVars.density(1);
218 static const auto rhow_muw = rho_w/insideVolVars.viscosity(0);
219 static const auto rhon_mun = rho_n/insideVolVars.viscosity(1);
220 const auto rhowKrw_muw_inside = rho_w*insideVolVars.mobility(0);
221 const auto rhonKrn_mun_inside = rho_n*insideVolVars.mobility(1);
222 const auto rhowKrw_muw_outside = rho_w*outsideVolVars.mobility(0);
223 const auto rhonKrn_mun_outside = rho_n*outsideVolVars.mobility(1);
224
225 // derivative w.r.t. to Sn is the negative of the one w.r.t. Sw
226 const auto insideSw = insideVolVars.saturation(0);
227 const auto outsideSw = outsideVolVars.saturation(0);
228 const auto dKrw_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrw_dsw(insideSw);
229 const auto dKrw_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrw_dsw(outsideSw);
230 const auto dKrn_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrn_dsw(insideSw);
231 const auto dKrn_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrn_dsw(outsideSw);
232 const auto dpc_dSn_inside = -1.0*insidefluidMatrixInteraction.dpc_dsw(insideSw);
233 const auto dpc_dSn_outside = -1.0*outsidefluidMatrixInteraction.dpc_dsw(outsideSw);
234
235 const auto tij = elemFluxVarsCache[scvf].advectionTij();
236
237 // precalculate values
238 const auto up_w = rhowKrw_muw_inside*insideWeight_w + rhowKrw_muw_outside*outsideWeight_w;
239 const auto up_n = rhonKrn_mun_inside*insideWeight_n + rhonKrn_mun_outside*outsideWeight_n;
240 const auto rho_mu_flux_w = rhow_muw*flux_w;
241 const auto rho_mu_flux_n = rhon_mun*flux_n;
242 const auto tij_up_w = tij*up_w;
243 const auto tij_up_n = tij*up_n;
244
245 // partial derivative of the wetting phase flux w.r.t. p_w
246 dI_dI[conti0EqIdx+0][pressureIdx] += tij_up_w;
247 dI_dJ[conti0EqIdx+0][pressureIdx] -= tij_up_w;
248
249 // partial derivative of the wetting phase flux w.r.t. S_n
250 dI_dI[conti0EqIdx+0][saturationIdx] += rho_mu_flux_w*dKrw_dSn_inside*insideWeight_w;
251 dI_dJ[conti0EqIdx+0][saturationIdx] += rho_mu_flux_w*dKrw_dSn_outside*outsideWeight_w;
252
253 // partial derivative of the nonwetting phase flux w.r.t. p_w
254 dI_dI[conti0EqIdx+1][pressureIdx] += tij_up_n;
255 dI_dJ[conti0EqIdx+1][pressureIdx] -= tij_up_n;
256
257 // partial derivative of the nonwetting phase flux w.r.t. S_n (relative permeability derivative contribution)
258 dI_dI[conti0EqIdx+1][saturationIdx] += rho_mu_flux_n*dKrn_dSn_inside*insideWeight_n;
259 dI_dJ[conti0EqIdx+1][saturationIdx] += rho_mu_flux_n*dKrn_dSn_outside*outsideWeight_n;
260
261 // partial derivative of the nonwetting phase flux w.r.t. S_n (capillary pressure derivative contribution)
262 dI_dI[conti0EqIdx+1][saturationIdx] += tij_up_n*dpc_dSn_inside;
263 dI_dJ[conti0EqIdx+1][saturationIdx] -= tij_up_n*dpc_dSn_outside;
264 }
265
280 template<class JacobianMatrix, class T = TypeTag>
281 std::enable_if_t<GetPropType<T, Properties::GridGeometry>::discMethod == DiscretizationMethod::box, void>
282 addFluxDerivatives(JacobianMatrix& A,
283 const Problem& problem,
284 const Element& element,
285 const FVElementGeometry& fvGeometry,
286 const ElementVolumeVariables& curElemVolVars,
287 const ElementFluxVariablesCache& elemFluxVarsCache,
288 const SubControlVolumeFace& scvf) const
289 {
290 static_assert(!FluidSystem::isCompressible(0),
291 "2p/incompressiblelocalresidual.hh: Only incompressible fluids are allowed!");
292 static_assert(!FluidSystem::isCompressible(1),
293 "2p/incompressiblelocalresidual.hh: Only incompressible fluids are allowed!");
294 static_assert(FluidSystem::viscosityIsConstant(0),
295 "2p/incompressiblelocalresidual.hh: Only fluids with constant viscosities are allowed!");
296 static_assert(FluidSystem::viscosityIsConstant(1),
297 "2p/incompressiblelocalresidual.hh: Only fluids with constant viscosities are allowed!");
298 static_assert(ModelTraits::numFluidPhases() == 2,
299 "2p/incompressiblelocalresidual.hh: Only two-phase models are allowed!");
300 static_assert(ModelTraits::priVarFormulation() == TwoPFormulation::p0s1,
301 "2p/incompressiblelocalresidual.hh: Analytic differentiation has to be checked for p0-s1 formulation!");
302
304
305 // evaluate the current wetting phase Darcy flux and resulting upwind weights
306 static const Scalar upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight");
307 const auto flux_w = AdvectionType::flux(problem, element, fvGeometry, curElemVolVars, scvf, 0, elemFluxVarsCache);
308 const auto flux_n = AdvectionType::flux(problem, element, fvGeometry, curElemVolVars, scvf, 1, elemFluxVarsCache);
309 const auto insideWeight_w = std::signbit(flux_w) ? (1.0 - upwindWeight) : upwindWeight;
310 const auto outsideWeight_w = 1.0 - insideWeight_w;
311 const auto insideWeight_n = std::signbit(flux_n) ? (1.0 - upwindWeight) : upwindWeight;
312 const auto outsideWeight_n = 1.0 - insideWeight_n;
313
314 // get references to the two participating vol vars & parameters
315 const auto insideScvIdx = scvf.insideScvIdx();
316 const auto outsideScvIdx = scvf.outsideScvIdx();
317 const auto& insideScv = fvGeometry.scv(insideScvIdx);
318 const auto& outsideScv = fvGeometry.scv(outsideScvIdx);
319 const auto& insideVolVars = curElemVolVars[insideScv];
320 const auto& outsideVolVars = curElemVolVars[outsideScv];
321
322 const auto elemSol = elementSolution(element, curElemVolVars, fvGeometry);
323
324 // old material law interface is deprecated: Replace this by
325 // const auto& insidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element,
326 // insideScv,
327 // elemSol);
328 // const auto& outsidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element,
329 // outsideScv,
330 // elemSol);
331 // after the release of 3.3, when the deprecated interface is no longer supported
332 const auto& insidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(),
333 element,
334 insideScv,
335 elemSol);
336 const auto& outsidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(),
337 element,
338 outsideScv,
339 elemSol);
340
341 // some quantities to be reused (rho & mu are constant and thus equal for all cells)
342 static const auto rho_w = insideVolVars.density(0);
343 static const auto rho_n = insideVolVars.density(1);
344 static const auto rhow_muw = rho_w/insideVolVars.viscosity(0);
345 static const auto rhon_mun = rho_n/insideVolVars.viscosity(1);
346 const auto rhowKrw_muw_inside = rho_w*insideVolVars.mobility(0);
347 const auto rhonKrn_mun_inside = rho_n*insideVolVars.mobility(1);
348 const auto rhowKrw_muw_outside = rho_w*outsideVolVars.mobility(0);
349 const auto rhonKrn_mun_outside = rho_n*outsideVolVars.mobility(1);
350
351 // let the Law for the advective fluxes calculate the transmissibilities
352 const auto ti = AdvectionType::calculateTransmissibilities(problem,
353 element,
354 fvGeometry,
355 curElemVolVars,
356 scvf,
357 elemFluxVarsCache[scvf]);
358
359 // get the rows of the jacobian matrix for the inside/outside scv
360 auto& dI_dJ_inside = A[insideScv.dofIndex()];
361 auto& dI_dJ_outside = A[outsideScv.dofIndex()];
362
363 // precalculate values
364 const auto up_w = rhowKrw_muw_inside*insideWeight_w + rhowKrw_muw_outside*outsideWeight_w;
365 const auto up_n = rhonKrn_mun_inside*insideWeight_n + rhonKrn_mun_outside*outsideWeight_n;
366 const auto rho_mu_flux_w = rhow_muw*flux_w;
367 const auto rho_mu_flux_n = rhon_mun*flux_n;
368
369 // add the partial derivatives w.r.t all scvs in the element
370 for (const auto& scvJ : scvs(fvGeometry))
371 {
372 const auto globalJ = scvJ.dofIndex();
373 const auto localJ = scvJ.indexInElement();
374
375 // the transmissibily associated with the scvJ
376 const auto tj = ti[localJ];
377
378 // partial derivative of the wetting phase flux w.r.t. p_w
379 const auto tj_up_w = tj*up_w;
380 dI_dJ_inside[globalJ][conti0EqIdx+0][pressureIdx] += tj_up_w;
381 dI_dJ_outside[globalJ][conti0EqIdx+0][pressureIdx] -= tj_up_w;
382
383 // partial derivative of the nonwetting phase flux w.r.t. p_w
384 const auto tj_up_n = tj*up_n;
385 dI_dJ_inside[globalJ][conti0EqIdx+1][pressureIdx] += tj_up_n;
386 dI_dJ_outside[globalJ][conti0EqIdx+1][pressureIdx] -= tj_up_n;
387
388 // partial derivatives w.r.t. S_n (are the negative of those w.r.t sw)
389 // relative permeability contributions only for inside/outside
390 if (localJ == insideScvIdx)
391 {
392 // partial derivative of the wetting phase flux w.r.t. S_n
393 const auto insideSw = insideVolVars.saturation(0);
394 const auto dKrw_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrw_dsw(insideSw);
395 const auto dFluxW_dSnJ = rho_mu_flux_w*dKrw_dSn_inside*insideWeight_w;
396 dI_dJ_inside[globalJ][conti0EqIdx+0][saturationIdx] += dFluxW_dSnJ;
397 dI_dJ_outside[globalJ][conti0EqIdx+0][saturationIdx] -= dFluxW_dSnJ;
398
399 // partial derivative of the nonwetting phase flux w.r.t. S_n (k_rn contribution)
400 const auto dKrn_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrn_dsw(insideSw);
401 const auto dFluxN_dSnJ_krn = rho_mu_flux_n*dKrn_dSn_inside*insideWeight_n;
402 dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_krn;
403 dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_krn;
404
405 // partial derivative of the nonwetting phase flux w.r.t. S_n (p_c contribution)
406 const auto dFluxN_dSnJ_pc = -1.0*tj_up_n*insidefluidMatrixInteraction.dpc_dsw(insideSw);
407 dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_pc;
408 dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_pc;
409 }
410 else if (localJ == outsideScvIdx)
411 {
412 // see comments for (globalJ == insideScvIdx)
413 const auto outsideSw = outsideVolVars.saturation(0);
414 const auto dKrw_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrw_dsw(outsideSw);
415 const auto dFluxW_dSnJ = rho_mu_flux_w*dKrw_dSn_outside*outsideWeight_w;
416 dI_dJ_inside[globalJ][conti0EqIdx+0][saturationIdx] += dFluxW_dSnJ;
417 dI_dJ_outside[globalJ][conti0EqIdx+0][saturationIdx] -= dFluxW_dSnJ;
418
419 const auto dKrn_dSn_outside = -1.0*outsidefluidMatrixInteraction.dkrn_dsw(outsideSw);
420 const auto dFluxN_dSnJ_krn = rho_mu_flux_n*dKrn_dSn_outside*outsideWeight_n;
421 dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_krn;
422 dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_krn;
423
424 const auto dFluxN_dSnJ_pc = -1.0*tj_up_n*outsidefluidMatrixInteraction.dpc_dsw(outsideSw);
425 dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_pc;
426 dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_pc;
427 }
428 else
429 {
430 // old material law interface is deprecated: Replace this by
431 // const auto& fluidMatrixInteractionJ = problem.spatialParams().fluidMatrixInteraction(element,
432 // scvJ,
433 // elemSol);
434
435 // after the release of 3.3, when the deprecated interface is no longer supported
436 const auto& fluidMatrixInteractionJ = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(),
437 element,
438 scvJ,
439 elemSol);
440 const auto swJ = curElemVolVars[scvJ].saturation(0);
441 const auto dFluxN_dSnJ_pc = tj_up_n*fluidMatrixInteractionJ.dpc_dsw(swJ);
442 dI_dJ_inside[globalJ][conti0EqIdx+1][saturationIdx] -= dFluxN_dSnJ_pc;
443 dI_dJ_outside[globalJ][conti0EqIdx+1][saturationIdx] += dFluxN_dSnJ_pc;
444 }
445 }
446 }
447
462 template<class PartialDerivativeMatrices>
463 void addCCDirichletFluxDerivatives(PartialDerivativeMatrices& derivativeMatrices,
464 const Problem& problem,
465 const Element& element,
466 const FVElementGeometry& fvGeometry,
467 const ElementVolumeVariables& curElemVolVars,
468 const ElementFluxVariablesCache& elemFluxVarsCache,
469 const SubControlVolumeFace& scvf) const
470 {
472
473 // evaluate the current wetting phase Darcy flux and resulting upwind weights
474 static const Scalar upwindWeight = getParamFromGroup<Scalar>(problem.paramGroup(), "Flux.UpwindWeight");
475 const auto flux_w = AdvectionType::flux(problem, element, fvGeometry, curElemVolVars, scvf, 0, elemFluxVarsCache);
476 const auto flux_n = AdvectionType::flux(problem, element, fvGeometry, curElemVolVars, scvf, 1, elemFluxVarsCache);
477 const auto insideWeight_w = std::signbit(flux_w) ? (1.0 - upwindWeight) : upwindWeight;
478 const auto outsideWeight_w = 1.0 - insideWeight_w;
479 const auto insideWeight_n = std::signbit(flux_n) ? (1.0 - upwindWeight) : upwindWeight;
480 const auto outsideWeight_n = 1.0 - insideWeight_n;
481
482 // get references to the two participating vol vars & parameters
483 const auto insideScvIdx = scvf.insideScvIdx();
484 const auto& insideScv = fvGeometry.scv(insideScvIdx);
485 const auto& insideVolVars = curElemVolVars[insideScvIdx];
486 const auto& outsideVolVars = curElemVolVars[scvf.outsideScvIdx()];
487
488 // old material law interface is deprecated: Replace this by
489 // const auto& insidefluidMatrixInteraction = problem.spatialParams().fluidMatrixInteraction(element,
490 // insideScv,
491 // elementSolution<FVElementGeometry>(insideVolVars.priVars()));
492 // after the release of 3.3, when the deprecated interface is no longer supported
493 const auto& insidefluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem.spatialParams(),
494 element,
495 insideScv,
496 elementSolution<FVElementGeometry>(insideVolVars.priVars()));
497
498 // some quantities to be reused (rho & mu are constant and thus equal for all cells)
499 static const auto rho_w = insideVolVars.density(0);
500 static const auto rho_n = insideVolVars.density(1);
501 static const auto rhow_muw = rho_w/insideVolVars.viscosity(0);
502 static const auto rhon_mun = rho_n/insideVolVars.viscosity(1);
503 const auto rhowKrw_muw_inside = rho_w*insideVolVars.mobility(0);
504 const auto rhonKrn_mun_inside = rho_n*insideVolVars.mobility(1);
505 const auto rhowKrw_muw_outside = rho_w*outsideVolVars.mobility(0);
506 const auto rhonKrn_mun_outside = rho_n*outsideVolVars.mobility(1);
507
508 // get reference to the inside derivative matrix
509 auto& dI_dI = derivativeMatrices[insideScvIdx];
510
511 // derivative w.r.t. to Sn is the negative of the one w.r.t. Sw
512 const auto insideSw = insideVolVars.saturation(0);
513 const auto dKrw_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrw_dsw(insideSw);
514 const auto dKrn_dSn_inside = -1.0*insidefluidMatrixInteraction.dkrn_dsw(insideSw);
515 const auto dpc_dSn_inside = -1.0*insidefluidMatrixInteraction.dpc_dsw(insideSw);
516
517 const auto tij = elemFluxVarsCache[scvf].advectionTij();
518 // partial derivative of the wetting phase flux w.r.t. p_w
519 const auto up_w = rhowKrw_muw_inside*insideWeight_w + rhowKrw_muw_outside*outsideWeight_w;
520 dI_dI[conti0EqIdx+0][pressureIdx] += tij*up_w;
521
522 // partial derivative of the wetting phase flux w.r.t. S_n
523 dI_dI[conti0EqIdx+0][saturationIdx] += rhow_muw*flux_w*dKrw_dSn_inside*insideWeight_w;
524
525 // partial derivative of the nonwetting phase flux w.r.t. p_w
526 const auto up_n = rhonKrn_mun_inside*insideWeight_n + rhonKrn_mun_outside*outsideWeight_n;
527 dI_dI[conti0EqIdx+1][pressureIdx] += tij*up_n;
528
529 // partial derivative of the nonwetting phase flux w.r.t. S_n (relative permeability derivative contribution)
530 dI_dI[conti0EqIdx+1][saturationIdx] += rhon_mun*flux_n*dKrn_dSn_inside*insideWeight_n;
531
532 // partial derivative of the nonwetting phase flux w.r.t. S_n (capillary pressure derivative contribution)
533 dI_dI[conti0EqIdx+1][saturationIdx] += tij*dpc_dSn_inside*up_n;
534 }
535
547 template<class PartialDerivativeMatrices>
548 void addRobinFluxDerivatives(PartialDerivativeMatrices& derivativeMatrices,
549 const Problem& problem,
550 const Element& element,
551 const FVElementGeometry& fvGeometry,
552 const ElementVolumeVariables& curElemVolVars,
553 const ElementFluxVariablesCache& elemFluxVarsCache,
554 const SubControlVolumeFace& scvf) const
555 { /* TODO maybe forward to problem for the user to implement the Robin derivatives?*/ }
556};
557
558} // end namespace Dumux
559
560#endif
Helpers for deprecation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Element solution classes and factory functions.
The available discretization methods in Dumux.
Helper classes to compute the integration elements.
Defines an enumeration for the formulations accepted by the two-phase model.
@ p0s1
first phase pressure and second phase saturation as primary variables
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethod::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition: box/elementsolution.hh:115
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
Element-wise calculation of the residual and its derivatives for a two-phase, incompressible test pro...
Definition: 2p/incompressiblelocalresidual.hh:52
void addStorageDerivatives(PartialDerivativeMatrix &partialDerivatives, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const VolumeVariables &curVolVars, const SubControlVolume &scv) const
Adds storage derivatives for wetting and nonwetting phase.
Definition: 2p/incompressiblelocalresidual.hh:94
void addRobinFluxDerivatives(PartialDerivativeMatrices &derivativeMatrices, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &curElemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf) const
Adds Robin flux derivatives for wetting and nonwetting phase.
Definition: 2p/incompressiblelocalresidual.hh:548
void addSourceDerivatives(PartialDerivativeMatrix &partialDerivatives, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const VolumeVariables &curVolVars, const SubControlVolume &scv) const
Adds source derivatives for wetting and nonwetting phase.
Definition: 2p/incompressiblelocalresidual.hh:129
std::enable_if_t< GetPropType< T, Properties::GridGeometry >::discMethod==DiscretizationMethod::cctpfa, void > addFluxDerivatives(PartialDerivativeMatrices &derivativeMatrices, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &curElemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf) const
Adds flux derivatives for wetting and nonwetting phase for cell-centered FVM using TPFA.
Definition: 2p/incompressiblelocalresidual.hh:153
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
Adds flux derivatives for wetting and nonwetting phase for box method.
Definition: 2p/incompressiblelocalresidual.hh:282
void addCCDirichletFluxDerivatives(PartialDerivativeMatrices &derivativeMatrices, const Problem &problem, const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &curElemVolVars, const ElementFluxVariablesCache &elemFluxVarsCache, const SubControlVolumeFace &scvf) const
Adds cell-centered Dirichlet flux derivatives for wetting and nonwetting phase.
Definition: 2p/incompressiblelocalresidual.hh:463
Element-wise calculation of the residual for problems using the n-phase immiscible fully implicit mod...
Definition: porousmediumflow/immiscible/localresidual.hh:39
Declares all properties used in Dumux.
Element-wise calculation of the residual for problems using the n-phase immiscible fully implicit mod...