355 const Intersection& intersection,
356 const CellData& cellDataI,
360 auto elementI = intersection.inside();
361 int eIdxGlobalI =
problem().variables().index(elementI);
364 const GlobalPosition& globalPos = elementI.geometry().center();
367 Scalar volume = elementI.geometry().volume();
368 Scalar perimeter = cellDataI.perimeter();
372 const GlobalPosition& gravity_ =
problem().gravity();
375 DimMatrix permeabilityI(
problem().spatialParams().intrinsicPermeability(elementI));
378 Scalar fractionalWI=0, fractionalNWI=0;
381 fractionalWI = cellDataI.mobility(wPhaseIdx)
382 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
383 fractionalNWI = cellDataI.mobility(nPhaseIdx)
384 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
388 const GlobalPosition& unitOuterNormal = intersection.centerUnitOuterNormal();
391 Scalar faceArea = intersection.geometry().volume();
394 auto neighbor = intersection.outside();
395 int eIdxGlobalJ =
problem().variables().index(neighbor);
396 CellData& cellDataJ =
problem().variables().cellData(eIdxGlobalJ);
399 const GlobalPosition& globalPosNeighbor = neighbor.geometry().center();
402 GlobalPosition distVec = globalPosNeighbor - globalPos;
405 Scalar dist = distVec.two_norm();
407 GlobalPosition unitDistVec(distVec);
410 DimMatrix permeabilityJ
411 =
problem().spatialParams().intrinsicPermeability(neighbor);
414 DimMatrix meanPermeability(0);
417 Dune::FieldVector<Scalar, dim> permeability(0);
418 meanPermeability.mv(unitDistVec, permeability);
421 Scalar rhoMeanW = 0.5 * (cellDataI.density(wPhaseIdx) + cellDataJ.density(wPhaseIdx));
422 Scalar rhoMeanNW = 0.5 * (cellDataI.density(nPhaseIdx) + cellDataJ.density(nPhaseIdx));
425 Scalar potentialW = 0;
426 Scalar potentialNW = 0;
431 Scalar fractionalWJ = cellDataJ.mobility(wPhaseIdx)
432 / (cellDataJ.mobility(wPhaseIdx)+ cellDataJ.mobility(nPhaseIdx));
433 Scalar fractionalNWJ = cellDataJ.mobility(nPhaseIdx)
434 / (cellDataJ.mobility(wPhaseIdx)+ cellDataJ.mobility(nPhaseIdx));
437 Scalar lambda = (cellDataI.mobility(wPhaseIdx) + cellDataJ.mobility(wPhaseIdx)) * 0.5
438 + (cellDataI.mobility(nPhaseIdx) + cellDataJ.mobility(nPhaseIdx)) * 0.5;
440 entries[0] = fabs(lambda*faceArea*fabs(permeability*unitOuterNormal)/(dist));
442 Scalar factor = (fractionalWI + fractionalWJ) * (rhoMeanW) * 0.5
443 + (fractionalNWI + fractionalNWJ) * (rhoMeanNW) * 0.5;
444 entries[1] = factor * lambda * faceArea * fabs(unitOuterNormal*permeability)
445 * (gravity_ * unitDistVec);
450 if (!cellDataJ.hasVolumeDerivatives())
451 asImp_().volumeDerivatives(globalPosNeighbor, neighbor);
453 Scalar dv_dC1 = (cellDataJ.dv(wPhaseIdx)
454 + cellDataI.dv(wPhaseIdx)) / 2;
455 Scalar dv_dC2 = (cellDataJ.dv(nPhaseIdx)
456 + cellDataI.dv(nPhaseIdx)) / 2;
458 Scalar graddv_dC1 = (cellDataJ.dv(wPhaseIdx)
459 - cellDataI.dv(wPhaseIdx)) / dist;
460 Scalar graddv_dC2 = (cellDataJ.dv(nPhaseIdx)
461 - cellDataI.dv(nPhaseIdx)) / dist;
472 Scalar densityW = rhoMeanW;
473 Scalar densityNW = rhoMeanNW;
475 potentialW = (cellDataI.pressure(wPhaseIdx) - cellDataJ.pressure(wPhaseIdx))/dist;
476 potentialNW = (cellDataI.pressure(nPhaseIdx) - cellDataJ.pressure(nPhaseIdx))/dist;
478 potentialW += densityW * (unitDistVec * gravity_);
479 potentialNW += densityNW * (unitDistVec * gravity_);
482 Scalar lambdaW(0.), lambdaN(0.);
483 Scalar dV_w(0.), dV_n(0.);
484 Scalar gV_w(0.), gV_n(0.);
488 const CellData* upwindWCellData(0);
489 const CellData* upwindNCellData(0);
491 upwindWCellData = &cellDataI;
492 else if (potentialW < 0.)
493 upwindWCellData = &cellDataJ;
496 if(cellDataI.isUpwindCell(intersection.indexInInside(), contiWEqIdx))
497 upwindWCellData = &cellDataI;
498 else if(cellDataJ.isUpwindCell(intersection.indexInOutside(), contiWEqIdx))
499 upwindWCellData = &cellDataJ;
504 if (potentialNW > 0.)
505 upwindNCellData = &cellDataI;
506 else if (potentialNW < 0.)
507 upwindNCellData = &cellDataJ;
510 if(cellDataI.isUpwindCell(intersection.indexInInside(), contiNEqIdx))
511 upwindNCellData = &cellDataI;
512 else if(cellDataJ.isUpwindCell(intersection.indexInOutside(), contiNEqIdx))
513 upwindNCellData = &cellDataJ;
519 if(!upwindWCellData or (cellDataI.wasRefined() && cellDataJ.wasRefined() && elementI.father() == neighbor.father()))
521 if (cellDataI.wasRefined() && cellDataJ.wasRefined())
523 problem().variables().cellData(eIdxGlobalI).setUpwindCell(intersection.indexInInside(), contiWEqIdx,
false);
524 cellDataJ.setUpwindCell(intersection.indexInOutside(), contiWEqIdx,
false);
527 Scalar averagedMassFraction[2];
528 averagedMassFraction[wCompIdx]
529 =
harmonicMean(cellDataI.massFraction(wPhaseIdx, wCompIdx), cellDataJ.massFraction(wPhaseIdx, wCompIdx));
530 averagedMassFraction[nCompIdx]
531 =
harmonicMean(cellDataI.massFraction(wPhaseIdx, nCompIdx), cellDataJ.massFraction(wPhaseIdx, nCompIdx));
532 Scalar averageDensity =
harmonicMean(cellDataI.density(wPhaseIdx), cellDataJ.density(wPhaseIdx));
535 dV_w = dv_dC1 * averagedMassFraction[wCompIdx] + dv_dC2 * averagedMassFraction[nCompIdx];
536 dV_w *= averageDensity;
537 gV_w = graddv_dC1 * averagedMassFraction[wCompIdx] + graddv_dC2 * averagedMassFraction[nCompIdx];
538 gV_w *= averageDensity;
539 lambdaW =
harmonicMean(cellDataI.mobility(wPhaseIdx), cellDataJ.mobility(wPhaseIdx));
543 dV_w = (dv_dC1 * upwindWCellData->massFraction(wPhaseIdx, wCompIdx)
544 + dv_dC2 * upwindWCellData->massFraction(wPhaseIdx, nCompIdx));
545 lambdaW = upwindWCellData->mobility(wPhaseIdx);
546 gV_w = (graddv_dC1 * upwindWCellData->massFraction(wPhaseIdx, wCompIdx)
547 + graddv_dC2 * upwindWCellData->massFraction(wPhaseIdx, nCompIdx));
548 dV_w *= upwindWCellData->density(wPhaseIdx);
549 gV_w *= upwindWCellData->density(wPhaseIdx);
552 if(!upwindNCellData or (cellDataI.wasRefined() && cellDataJ.wasRefined()))
554 if (cellDataI.wasRefined() && cellDataJ.wasRefined())
556 problem().variables().cellData(eIdxGlobalI).setUpwindCell(intersection.indexInInside(), contiNEqIdx,
false);
557 cellDataJ.setUpwindCell(intersection.indexInOutside(), contiNEqIdx,
false);
559 Scalar averagedMassFraction[2];
560 averagedMassFraction[wCompIdx]
561 =
harmonicMean(cellDataI.massFraction(nPhaseIdx, wCompIdx), cellDataJ.massFraction(nPhaseIdx, wCompIdx));
562 averagedMassFraction[nCompIdx]
563 =
harmonicMean(cellDataI.massFraction(nPhaseIdx, nCompIdx), cellDataJ.massFraction(nPhaseIdx, nCompIdx));
564 Scalar averageDensity =
harmonicMean(cellDataI.density(nPhaseIdx), cellDataJ.density(nPhaseIdx));
567 dV_n = dv_dC1 * averagedMassFraction[wCompIdx] + dv_dC2 * averagedMassFraction[nCompIdx];
568 dV_n *= averageDensity;
569 gV_n = graddv_dC1 * averagedMassFraction[wCompIdx] + graddv_dC2 * averagedMassFraction[nCompIdx];
570 gV_n *= averageDensity;
571 lambdaN =
harmonicMean(cellDataI.mobility(nPhaseIdx), cellDataJ.mobility(nPhaseIdx));
575 dV_n = (dv_dC1 * upwindNCellData->massFraction(nPhaseIdx, wCompIdx)
576 + dv_dC2 * upwindNCellData->massFraction(nPhaseIdx, nCompIdx));
577 lambdaN = upwindNCellData->mobility(nPhaseIdx);
578 gV_n = (graddv_dC1 * upwindNCellData->massFraction(nPhaseIdx, wCompIdx)
579 + graddv_dC2 * upwindNCellData->massFraction(nPhaseIdx, nCompIdx));
580 dV_n *= upwindNCellData->density(nPhaseIdx);
581 gV_n *= upwindNCellData->density(nPhaseIdx);
585 entries[matrix] = faceArea * (lambdaW * dV_w + lambdaN * dV_n)
586 * fabs((unitOuterNormal*permeability)/(dist));
588 entries[matrix] -= volume * faceArea / perimeter * (lambdaW * gV_w + lambdaN * gV_n)
589 * ((unitDistVec*permeability)/(dist));
592 entries[rhs] = faceArea * (densityW * lambdaW * dV_w + densityNW * lambdaN * dV_n);
593 entries[rhs] *= fabs(unitOuterNormal * permeability);
595 entries[rhs] -= volume * faceArea / perimeter * (densityW * lambdaW * gV_w + densityNW * lambdaN * gV_n)
596 * (unitDistVec * permeability);
597 entries[rhs] *= (gravity_ * unitDistVec);
600 Scalar pCGradient = (cellDataI.capillaryPressure() - cellDataJ.capillaryPressure()) / dist;
608 entries[rhs] += lambdaN * dV_n * fabs(permeability * unitOuterNormal) * pCGradient * faceArea;
610 entries[rhs]-= lambdaN * gV_n * (permeability * unitDistVec) * pCGradient * volume * faceArea / perimeter;
616 entries[rhs] -= lambdaW * dV_w * fabs(permeability * unitOuterNormal) * pCGradient * faceArea;
618 entries[rhs]+= lambdaW * gV_w * (permeability * unitDistVec) * pCGradient * volume * faceArea / perimeter;
646 const Intersection& intersection,
const CellData& cellDataI,
const bool first)
650 auto elementI = intersection.inside();
651 const GlobalPosition& globalPos = elementI.geometry().center();
654 const GlobalPosition& unitOuterNormal = intersection.centerUnitOuterNormal();
656 Scalar faceArea = intersection.geometry().volume();
659 Scalar dv_dC1 = cellDataI.dv(wCompIdx);
660 Scalar dv_dC2 = cellDataI.dv(nCompIdx);
663 const GlobalPosition& globalPosFace = intersection.geometry().center();
666 GlobalPosition distVec(globalPosFace - globalPos);
667 Scalar dist = distVec.two_norm();
668 GlobalPosition unitDistVec(distVec);
672 BoundaryTypes bcType;
673 problem().boundaryTypes(bcType, intersection);
676 PhaseVector pressBC(0.);
679 const auto fluidMatrixInteraction =
problem().spatialParams().fluidMatrixInteractionAtPos(elementI.geometry().center());
682 if (bcType.isDirichlet(Indices::pressureEqIdx))
685 DimMatrix permeabilityI(
problem().spatialParams().intrinsicPermeability(elementI));
689 int axis = intersection.indexInInside() / 2;
693 const GlobalPosition& gravity_ =
problem().gravity();
696 Dune::FieldVector<Scalar, dim> permeability(0);
697 permeabilityI.mv(unitDistVec, permeability);
700 FluidState BCfluidState;
703 PrimaryVariables primaryVariablesOnBoundary(NAN);
704 problem().dirichlet(primaryVariablesOnBoundary, intersection);
709 Scalar fractionalWI=0, fractionalNWI=0;
710 fractionalWI = cellDataI.mobility(wPhaseIdx)
711 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
712 fractionalNWI = cellDataI.mobility(nPhaseIdx)
713 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
715 Scalar lambda = cellDataI.mobility(wPhaseIdx)+cellDataI.mobility(nPhaseIdx);
716 entries[matrix] += lambda * faceArea * fabs(permeability * unitOuterNormal) / (dist);
717 Scalar pressBoundary = primaryVariablesOnBoundary[Indices::pressureEqIdx];
718 entries[rhs] += lambda * faceArea * pressBoundary * fabs(permeability * unitOuterNormal) / (dist);
719 Scalar rightentry = (fractionalWI * cellDataI.density(wPhaseIdx)
720 + fractionalNWI * cellDataI.density(nPhaseIdx))
721 * lambda * faceArea * fabs(unitOuterNormal * permeability)
722 * ( unitDistVec * gravity_);
723 entries[rhs] -= rightentry;
728 problem().transportModel().evalBoundary(globalPosFace,
732 pcBound = pressBC[nPhaseIdx] - pressBC[wPhaseIdx];
735 Scalar lambdaWBound = 0.;
736 Scalar lambdaNWBound = 0.;
738 Scalar densityWBound =
739 FluidSystem::density(BCfluidState, wPhaseIdx);
740 Scalar densityNWBound =
741 FluidSystem::density(BCfluidState, nPhaseIdx);
742 Scalar viscosityWBound =
743 FluidSystem::viscosity(BCfluidState, wPhaseIdx);
744 Scalar viscosityNWBound =
745 FluidSystem::viscosity(BCfluidState, nPhaseIdx);
750 lambdaWBound = BCfluidState.saturation(wPhaseIdx)
752 lambdaNWBound = BCfluidState.saturation(nPhaseIdx)
758 = fluidMatrixInteraction.krw(BCfluidState.saturation(wPhaseIdx)) / viscosityWBound;
760 = fluidMatrixInteraction.krn(BCfluidState.saturation(wPhaseIdx)) / viscosityNWBound;
763 Scalar rhoMeanW = 0.5 * (cellDataI.density(wPhaseIdx) + densityWBound);
764 Scalar rhoMeanNW = 0.5 * (cellDataI.density(nPhaseIdx) + densityNWBound);
766 Scalar potentialW = 0;
767 Scalar potentialNW = 0;
779 Scalar densityW=rhoMeanW;
780 Scalar densityNW=rhoMeanNW;
783 potentialW = (cellDataI.pressure(wPhaseIdx) - pressBC[wPhaseIdx])/dist;
784 potentialNW = (cellDataI.pressure(nPhaseIdx) - pressBC[nPhaseIdx])/dist;
786 potentialW += densityW * (unitDistVec * gravity_);
787 potentialNW += densityNW * (unitDistVec * gravity_);
791 Scalar lambdaW, lambdaNW;
792 Scalar densityW(0.), densityNW(0.);
796 if (potentialW >= 0.)
798 densityW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialW, 0.0, 1.0e-30)) ? rhoMeanW : cellDataI.density(wPhaseIdx);
799 dV_w = (dv_dC1 * cellDataI.massFraction(wPhaseIdx, wCompIdx)
800 + dv_dC2 * cellDataI.massFraction(wPhaseIdx, nCompIdx));
802 lambdaW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialW, 0.0, 1.0e-30)) ? 0.5 * (cellDataI.mobility(wPhaseIdx) + lambdaWBound)
803 : cellDataI.mobility(wPhaseIdx);
807 densityW = densityWBound;
808 dV_w = (dv_dC1 * BCfluidState.massFraction(wPhaseIdx, wCompIdx)
809 + dv_dC2 * BCfluidState.massFraction(wPhaseIdx, nCompIdx));
811 lambdaW = lambdaWBound;
813 if (potentialNW >= 0.)
815 densityNW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialNW, 0.0, 1.0e-30)) ? rhoMeanNW : cellDataI.density(nPhaseIdx);
816 dV_n = (dv_dC1 * cellDataI.massFraction(nPhaseIdx, wCompIdx)
817 + dv_dC2 * cellDataI.massFraction(nPhaseIdx, nCompIdx));
819 lambdaNW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialNW, 0.0, 1.0e-30)) ? 0.5 * (cellDataI.mobility(nPhaseIdx) + lambdaNWBound)
820 : cellDataI.mobility(nPhaseIdx);
824 densityNW = densityNWBound;
825 dV_n = (dv_dC1 * BCfluidState.massFraction(nPhaseIdx, wCompIdx)
826 + dv_dC2 * BCfluidState.massFraction(nPhaseIdx, nCompIdx));
828 lambdaNW = lambdaNWBound;
832 Scalar entry = (lambdaW * dV_w + lambdaNW * dV_n)
833 * (fabs(unitOuterNormal * permeability) / dist) * faceArea;
836 Scalar rightEntry = (lambdaW * densityW * dV_w + lambdaNW * densityNW * dV_n)
837 * fabs(unitOuterNormal * permeability) * (gravity_ * unitDistVec) * faceArea ;
841 Scalar pCGradient = (cellDataI.capillaryPressure() - pcBound) / dist;
847 rightEntry += lambdaNW * dV_n * pCGradient * fabs(unitOuterNormal * permeability) * faceArea;
853 rightEntry -= lambdaW * dV_w * pCGradient * fabs(unitOuterNormal * permeability) * faceArea;
860 entries[matrix] += entry;
861 entries[rhs] += entry * primaryVariablesOnBoundary[Indices::pressureEqIdx];
862 entries[rhs] -= rightEntry;
869 else if(bcType.isNeumann(Indices::pressureEqIdx))
871 PrimaryVariables J(NAN);
872 problem().neumann(J, intersection);
875 J[contiWEqIdx] /= cellDataI.density(wPhaseIdx);
876 J[contiNEqIdx] /= cellDataI.density(nPhaseIdx);
880 J[contiWEqIdx] *= dv_dC1;
881 J[contiNEqIdx] *= dv_dC2;
884 entries[rhs] -= (J[contiWEqIdx] + J[contiNEqIdx]) * faceArea;
887 DUNE_THROW(Dune::NotImplemented,
"Boundary Condition neither Dirichlet nor Neumann!");
906 GlobalPosition globalPos = element.geometry().center();
909 int eIdxGlobal =
problem().variables().index(element);
910 CellData& cellData =
problem().variables().cellData(eIdxGlobal);
913 FluidState& fluidState = cellData.manipulateFluidState();
915 Scalar temperature_ =
problem().temperatureAtPos(globalPos);
922 Scalar Z0 = cellData.massConcentration(wCompIdx)
923 / (cellData.massConcentration(wCompIdx)
924 + cellData.massConcentration(nCompIdx));
927 if(Z0 < 0. || Z0 > 1.)
929 Dune::dgrave <<
"Feed mass fraction unphysical: Z0 = " << Z0
930 <<
" at global Idx " << eIdxGlobal
931 <<
" , because totalConcentration(wCompIdx) = "
932 << cellData.totalConcentration(wCompIdx)
933 <<
" and totalConcentration(nCompIdx) = "
934 << cellData.totalConcentration(nCompIdx)<< std::endl;
938 cellData.setTotalConcentration(wCompIdx, 0.);
939 problem().transportModel().totalConcentration(wCompIdx, eIdxGlobal) = 0.;
940 Dune::dgrave <<
"Regularize totalConcentration(wCompIdx) = "
941 << cellData.totalConcentration(wCompIdx)<< std::endl;
946 cellData.setTotalConcentration(nCompIdx, 0.);
947 problem().transportModel().totalConcentration(nCompIdx,eIdxGlobal) = 0.;
948 Dune::dgrave <<
"Regularize totalConcentration(eIdxGlobal, nCompIdx) = "
949 << cellData.totalConcentration(nCompIdx)<< std::endl;
956 const auto fluidMatrixInteraction =
problem().spatialParams().fluidMatrixInteractionAtPos(element.geometry().center());
959 unsigned int maxiter = 6;
960 Scalar pc = cellData.capillaryPressure();
962 for (
unsigned int iter = 0; iter < maxiter; iter++)
968 pressure[wPhaseIdx] = asImp_().pressure(eIdxGlobal);
969 pressure[nPhaseIdx] = asImp_().pressure(eIdxGlobal) + pc;
974 pressure[wPhaseIdx] = asImp_().pressure(eIdxGlobal) - pc;
975 pressure[nPhaseIdx] = asImp_().pressure(eIdxGlobal);
985 pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx));
987 if (fabs(oldPc-pc)<10 && iter != 0)
990 if (iter++ == maxiter)
991 Dune::dinfo << iter <<
"times iteration of pc was applied at Idx " << eIdxGlobal
992 <<
", pc delta still " << fabs(oldPc-pc) << std::endl;
997 pressure[wPhaseIdx] =
pressure[nPhaseIdx] = asImp_().pressure()[eIdxGlobal];
1002 cellData.setMobility(wPhaseIdx, fluidMatrixInteraction.krw(fluidState.saturation(wPhaseIdx))
1003 / cellData.viscosity(wPhaseIdx));
1004 cellData.setMobility(nPhaseIdx, fluidMatrixInteraction.krn(fluidState.saturation(wPhaseIdx))
1005 / cellData.viscosity(nPhaseIdx));
1008 Scalar sumConc = (cellData.totalConcentration(wCompIdx)
1009 + cellData.totalConcentration(nCompIdx));
1010 Scalar massw = sumConc * fluidState.phaseMassFraction(wPhaseIdx);
1011 Scalar massn = sumConc * fluidState.phaseMassFraction(nPhaseIdx);
1013 if (Dune::FloatCmp::eq<Scalar>((cellData.density(wPhaseIdx)*cellData.density(nPhaseIdx)), 0))
1014 DUNE_THROW(Dune::MathError,
"Sequential2p2c::postProcessUpdate: try to divide by 0 density");
1015 Scalar vol = massw / cellData.density(wPhaseIdx) + massn / cellData.density(nPhaseIdx);
1016 if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(
problem().timeManager().timeStepSize(), 0.0, 1.0e-30))
1018 cellData.volumeError()=(vol -
problem().spatialParams().porosity(element));
1021 if (isnan(cellData.volumeError()))
1023 DUNE_THROW(Dune::MathError,
"Sequential2p2c::postProcessUpdate:\n"
1024 <<
"volErr[" << eIdxGlobal <<
"] isnan: vol = " << vol
1025 <<
", massw = " << massw <<
", rho_l = " << cellData.density(wPhaseIdx)
1026 <<
", massn = " << massn <<
", rho_g = " << cellData.density(nPhaseIdx)
1027 <<
", poro = " <<
problem().spatialParams().porosity(element)
1028 <<
", dt = " <<
problem().timeManager().timeStepSize());
1032 cellData.volumeError()=0.;