356 const Intersection& intersection,
357 const CellData& cellDataI,
361 auto elementI = intersection.inside();
362 int eIdxGlobalI =
problem().variables().index(elementI);
365 const GlobalPosition& globalPos = elementI.geometry().center();
368 Scalar volume = elementI.geometry().volume();
369 Scalar perimeter = cellDataI.perimeter();
373 const GlobalPosition& gravity_ =
problem().gravity();
376 DimMatrix permeabilityI(
problem().spatialParams().intrinsicPermeability(elementI));
379 Scalar fractionalWI=0, fractionalNWI=0;
382 fractionalWI = cellDataI.mobility(wPhaseIdx)
383 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
384 fractionalNWI = cellDataI.mobility(nPhaseIdx)
385 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
389 const GlobalPosition& unitOuterNormal = intersection.centerUnitOuterNormal();
392 Scalar faceArea = intersection.geometry().volume();
395 auto neighbor = intersection.outside();
396 int eIdxGlobalJ =
problem().variables().index(neighbor);
397 CellData& cellDataJ =
problem().variables().cellData(eIdxGlobalJ);
400 const GlobalPosition& globalPosNeighbor = neighbor.geometry().center();
403 GlobalPosition distVec = globalPosNeighbor - globalPos;
406 Scalar dist = distVec.two_norm();
408 GlobalPosition unitDistVec(distVec);
411 DimMatrix permeabilityJ
412 =
problem().spatialParams().intrinsicPermeability(neighbor);
415 DimMatrix meanPermeability(0);
418 Dune::FieldVector<Scalar, dim> permeability(0);
419 meanPermeability.mv(unitDistVec, permeability);
422 Scalar rhoMeanW = 0.5 * (cellDataI.density(wPhaseIdx) + cellDataJ.density(wPhaseIdx));
423 Scalar rhoMeanNW = 0.5 * (cellDataI.density(nPhaseIdx) + cellDataJ.density(nPhaseIdx));
426 Scalar potentialW = 0;
427 Scalar potentialNW = 0;
432 Scalar fractionalWJ = cellDataJ.mobility(wPhaseIdx)
433 / (cellDataJ.mobility(wPhaseIdx)+ cellDataJ.mobility(nPhaseIdx));
434 Scalar fractionalNWJ = cellDataJ.mobility(nPhaseIdx)
435 / (cellDataJ.mobility(wPhaseIdx)+ cellDataJ.mobility(nPhaseIdx));
438 Scalar lambda = (cellDataI.mobility(wPhaseIdx) + cellDataJ.mobility(wPhaseIdx)) * 0.5
439 + (cellDataI.mobility(nPhaseIdx) + cellDataJ.mobility(nPhaseIdx)) * 0.5;
441 entries[0] = fabs(lambda*faceArea*fabs(permeability*unitOuterNormal)/(dist));
443 Scalar factor = (fractionalWI + fractionalWJ) * (rhoMeanW) * 0.5
444 + (fractionalNWI + fractionalNWJ) * (rhoMeanNW) * 0.5;
445 entries[1] = factor * lambda * faceArea * fabs(unitOuterNormal*permeability)
446 * (gravity_ * unitDistVec);
451 if (!cellDataJ.hasVolumeDerivatives())
452 asImp_().volumeDerivatives(globalPosNeighbor, neighbor);
454 Scalar dv_dC1 = (cellDataJ.dv(wPhaseIdx)
455 + cellDataI.dv(wPhaseIdx)) / 2;
456 Scalar dv_dC2 = (cellDataJ.dv(nPhaseIdx)
457 + cellDataI.dv(nPhaseIdx)) / 2;
459 Scalar graddv_dC1 = (cellDataJ.dv(wPhaseIdx)
460 - cellDataI.dv(wPhaseIdx)) / dist;
461 Scalar graddv_dC2 = (cellDataJ.dv(nPhaseIdx)
462 - cellDataI.dv(nPhaseIdx)) / dist;
473 Scalar densityW = rhoMeanW;
474 Scalar densityNW = rhoMeanNW;
476 potentialW = (cellDataI.pressure(wPhaseIdx) - cellDataJ.pressure(wPhaseIdx))/dist;
477 potentialNW = (cellDataI.pressure(nPhaseIdx) - cellDataJ.pressure(nPhaseIdx))/dist;
479 potentialW += densityW * (unitDistVec * gravity_);
480 potentialNW += densityNW * (unitDistVec * gravity_);
483 Scalar lambdaW(0.), lambdaN(0.);
484 Scalar dV_w(0.), dV_n(0.);
485 Scalar gV_w(0.), gV_n(0.);
489 const CellData* upwindWCellData(0);
490 const CellData* upwindNCellData(0);
492 upwindWCellData = &cellDataI;
493 else if (potentialW < 0.)
494 upwindWCellData = &cellDataJ;
497 if(cellDataI.isUpwindCell(intersection.indexInInside(), contiWEqIdx))
498 upwindWCellData = &cellDataI;
499 else if(cellDataJ.isUpwindCell(intersection.indexInOutside(), contiWEqIdx))
500 upwindWCellData = &cellDataJ;
505 if (potentialNW > 0.)
506 upwindNCellData = &cellDataI;
507 else if (potentialNW < 0.)
508 upwindNCellData = &cellDataJ;
511 if(cellDataI.isUpwindCell(intersection.indexInInside(), contiNEqIdx))
512 upwindNCellData = &cellDataI;
513 else if(cellDataJ.isUpwindCell(intersection.indexInOutside(), contiNEqIdx))
514 upwindNCellData = &cellDataJ;
520 if(!upwindWCellData or (cellDataI.wasRefined() && cellDataJ.wasRefined() && elementI.father() == neighbor.father()))
522 if (cellDataI.wasRefined() && cellDataJ.wasRefined())
524 problem().variables().cellData(eIdxGlobalI).setUpwindCell(intersection.indexInInside(), contiWEqIdx,
false);
525 cellDataJ.setUpwindCell(intersection.indexInOutside(), contiWEqIdx,
false);
528 Scalar averagedMassFraction[2];
529 averagedMassFraction[wCompIdx]
530 =
harmonicMean(cellDataI.massFraction(wPhaseIdx, wCompIdx), cellDataJ.massFraction(wPhaseIdx, wCompIdx));
531 averagedMassFraction[nCompIdx]
532 =
harmonicMean(cellDataI.massFraction(wPhaseIdx, nCompIdx), cellDataJ.massFraction(wPhaseIdx, nCompIdx));
533 Scalar averageDensity =
harmonicMean(cellDataI.density(wPhaseIdx), cellDataJ.density(wPhaseIdx));
536 dV_w = dv_dC1 * averagedMassFraction[wCompIdx] + dv_dC2 * averagedMassFraction[nCompIdx];
537 dV_w *= averageDensity;
538 gV_w = graddv_dC1 * averagedMassFraction[wCompIdx] + graddv_dC2 * averagedMassFraction[nCompIdx];
539 gV_w *= averageDensity;
540 lambdaW =
harmonicMean(cellDataI.mobility(wPhaseIdx), cellDataJ.mobility(wPhaseIdx));
544 dV_w = (dv_dC1 * upwindWCellData->massFraction(wPhaseIdx, wCompIdx)
545 + dv_dC2 * upwindWCellData->massFraction(wPhaseIdx, nCompIdx));
546 lambdaW = upwindWCellData->mobility(wPhaseIdx);
547 gV_w = (graddv_dC1 * upwindWCellData->massFraction(wPhaseIdx, wCompIdx)
548 + graddv_dC2 * upwindWCellData->massFraction(wPhaseIdx, nCompIdx));
549 dV_w *= upwindWCellData->density(wPhaseIdx);
550 gV_w *= upwindWCellData->density(wPhaseIdx);
553 if(!upwindNCellData or (cellDataI.wasRefined() && cellDataJ.wasRefined()))
555 if (cellDataI.wasRefined() && cellDataJ.wasRefined())
557 problem().variables().cellData(eIdxGlobalI).setUpwindCell(intersection.indexInInside(), contiNEqIdx,
false);
558 cellDataJ.setUpwindCell(intersection.indexInOutside(), contiNEqIdx,
false);
560 Scalar averagedMassFraction[2];
561 averagedMassFraction[wCompIdx]
562 =
harmonicMean(cellDataI.massFraction(nPhaseIdx, wCompIdx), cellDataJ.massFraction(nPhaseIdx, wCompIdx));
563 averagedMassFraction[nCompIdx]
564 =
harmonicMean(cellDataI.massFraction(nPhaseIdx, nCompIdx), cellDataJ.massFraction(nPhaseIdx, nCompIdx));
565 Scalar averageDensity =
harmonicMean(cellDataI.density(nPhaseIdx), cellDataJ.density(nPhaseIdx));
568 dV_n = dv_dC1 * averagedMassFraction[wCompIdx] + dv_dC2 * averagedMassFraction[nCompIdx];
569 dV_n *= averageDensity;
570 gV_n = graddv_dC1 * averagedMassFraction[wCompIdx] + graddv_dC2 * averagedMassFraction[nCompIdx];
571 gV_n *= averageDensity;
572 lambdaN =
harmonicMean(cellDataI.mobility(nPhaseIdx), cellDataJ.mobility(nPhaseIdx));
576 dV_n = (dv_dC1 * upwindNCellData->massFraction(nPhaseIdx, wCompIdx)
577 + dv_dC2 * upwindNCellData->massFraction(nPhaseIdx, nCompIdx));
578 lambdaN = upwindNCellData->mobility(nPhaseIdx);
579 gV_n = (graddv_dC1 * upwindNCellData->massFraction(nPhaseIdx, wCompIdx)
580 + graddv_dC2 * upwindNCellData->massFraction(nPhaseIdx, nCompIdx));
581 dV_n *= upwindNCellData->density(nPhaseIdx);
582 gV_n *= upwindNCellData->density(nPhaseIdx);
586 entries[matrix] = faceArea * (lambdaW * dV_w + lambdaN * dV_n)
587 * fabs((unitOuterNormal*permeability)/(dist));
589 entries[matrix] -= volume * faceArea / perimeter * (lambdaW * gV_w + lambdaN * gV_n)
590 * ((unitDistVec*permeability)/(dist));
593 entries[rhs] = faceArea * (densityW * lambdaW * dV_w + densityNW * lambdaN * dV_n);
594 entries[rhs] *= fabs(unitOuterNormal * permeability);
596 entries[rhs] -= volume * faceArea / perimeter * (densityW * lambdaW * gV_w + densityNW * lambdaN * gV_n)
597 * (unitDistVec * permeability);
598 entries[rhs] *= (gravity_ * unitDistVec);
601 Scalar pCGradient = (cellDataI.capillaryPressure() - cellDataJ.capillaryPressure()) / dist;
609 entries[rhs] += lambdaN * dV_n * fabs(permeability * unitOuterNormal) * pCGradient * faceArea;
611 entries[rhs]-= lambdaN * gV_n * (permeability * unitDistVec) * pCGradient * volume * faceArea / perimeter;
617 entries[rhs] -= lambdaW * dV_w * fabs(permeability * unitOuterNormal) * pCGradient * faceArea;
619 entries[rhs]+= lambdaW * gV_w * (permeability * unitDistVec) * pCGradient * volume * faceArea / perimeter;
647 const Intersection& intersection,
const CellData& cellDataI,
const bool first)
651 auto elementI = intersection.inside();
652 const GlobalPosition& globalPos = elementI.geometry().center();
655 const GlobalPosition& unitOuterNormal = intersection.centerUnitOuterNormal();
657 Scalar faceArea = intersection.geometry().volume();
660 Scalar dv_dC1 = cellDataI.dv(wCompIdx);
661 Scalar dv_dC2 = cellDataI.dv(nCompIdx);
664 const GlobalPosition& globalPosFace = intersection.geometry().center();
667 GlobalPosition distVec(globalPosFace - globalPos);
668 Scalar dist = distVec.two_norm();
669 GlobalPosition unitDistVec(distVec);
673 BoundaryTypes bcType;
674 problem().boundaryTypes(bcType, intersection);
677 PhaseVector pressBC(0.);
681 if (bcType.isDirichlet(Indices::pressureEqIdx))
684 DimMatrix permeabilityI(
problem().spatialParams().intrinsicPermeability(elementI));
688 int axis = intersection.indexInInside() / 2;
692 const GlobalPosition& gravity_ =
problem().gravity();
695 Dune::FieldVector<Scalar, dim> permeability(0);
696 permeabilityI.mv(unitDistVec, permeability);
699 FluidState BCfluidState;
702 PrimaryVariables primaryVariablesOnBoundary(NAN);
703 problem().dirichlet(primaryVariablesOnBoundary, intersection);
708 Scalar fractionalWI=0, fractionalNWI=0;
709 fractionalWI = cellDataI.mobility(wPhaseIdx)
710 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
711 fractionalNWI = cellDataI.mobility(nPhaseIdx)
712 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
714 Scalar lambda = cellDataI.mobility(wPhaseIdx)+cellDataI.mobility(nPhaseIdx);
715 entries[matrix] += lambda * faceArea * fabs(permeability * unitOuterNormal) / (dist);
716 Scalar pressBoundary = primaryVariablesOnBoundary[Indices::pressureEqIdx];
717 entries[rhs] += lambda * faceArea * pressBoundary * fabs(permeability * unitOuterNormal) / (dist);
718 Scalar rightentry = (fractionalWI * cellDataI.density(wPhaseIdx)
719 + fractionalNWI * cellDataI.density(nPhaseIdx))
720 * lambda * faceArea * fabs(unitOuterNormal * permeability)
721 * ( unitDistVec * gravity_);
722 entries[rhs] -= rightentry;
727 problem().transportModel().evalBoundary(globalPosFace,
731 pcBound = pressBC[nPhaseIdx] - pressBC[wPhaseIdx];
734 Scalar lambdaWBound = 0.;
735 Scalar lambdaNWBound = 0.;
737 Scalar densityWBound =
738 FluidSystem::density(BCfluidState, wPhaseIdx);
739 Scalar densityNWBound =
740 FluidSystem::density(BCfluidState, nPhaseIdx);
741 Scalar viscosityWBound =
742 FluidSystem::viscosity(BCfluidState, wPhaseIdx);
743 Scalar viscosityNWBound =
744 FluidSystem::viscosity(BCfluidState, nPhaseIdx);
749 lambdaWBound = BCfluidState.saturation(wPhaseIdx)
751 lambdaNWBound = BCfluidState.saturation(nPhaseIdx)
757 = MaterialLaw::krw(
problem().spatialParams().materialLawParams(elementI),
758 BCfluidState.saturation(wPhaseIdx)) / viscosityWBound;
760 = MaterialLaw::krn(
problem().spatialParams().materialLawParams(elementI),
761 BCfluidState.saturation(wPhaseIdx)) / viscosityNWBound;
764 Scalar rhoMeanW = 0.5 * (cellDataI.density(wPhaseIdx) + densityWBound);
765 Scalar rhoMeanNW = 0.5 * (cellDataI.density(nPhaseIdx) + densityNWBound);
767 Scalar potentialW = 0;
768 Scalar potentialNW = 0;
780 Scalar densityW=rhoMeanW;
781 Scalar densityNW=rhoMeanNW;
784 potentialW = (cellDataI.pressure(wPhaseIdx) - pressBC[wPhaseIdx])/dist;
785 potentialNW = (cellDataI.pressure(nPhaseIdx) - pressBC[nPhaseIdx])/dist;
787 potentialW += densityW * (unitDistVec * gravity_);
788 potentialNW += densityNW * (unitDistVec * gravity_);
792 Scalar lambdaW, lambdaNW;
793 Scalar densityW(0.), densityNW(0.);
797 if (potentialW >= 0.)
799 densityW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialW, 0.0, 1.0e-30)) ? rhoMeanW : cellDataI.density(wPhaseIdx);
800 dV_w = (dv_dC1 * cellDataI.massFraction(wPhaseIdx, wCompIdx)
801 + dv_dC2 * cellDataI.massFraction(wPhaseIdx, nCompIdx));
803 lambdaW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialW, 0.0, 1.0e-30)) ? 0.5 * (cellDataI.mobility(wPhaseIdx) + lambdaWBound)
804 : cellDataI.mobility(wPhaseIdx);
808 densityW = densityWBound;
809 dV_w = (dv_dC1 * BCfluidState.massFraction(wPhaseIdx, wCompIdx)
810 + dv_dC2 * BCfluidState.massFraction(wPhaseIdx, nCompIdx));
812 lambdaW = lambdaWBound;
814 if (potentialNW >= 0.)
816 densityNW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialNW, 0.0, 1.0e-30)) ? rhoMeanNW : cellDataI.density(nPhaseIdx);
817 dV_n = (dv_dC1 * cellDataI.massFraction(nPhaseIdx, wCompIdx)
818 + dv_dC2 * cellDataI.massFraction(nPhaseIdx, nCompIdx));
820 lambdaNW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialNW, 0.0, 1.0e-30)) ? 0.5 * (cellDataI.mobility(nPhaseIdx) + lambdaNWBound)
821 : cellDataI.mobility(nPhaseIdx);
825 densityNW = densityNWBound;
826 dV_n = (dv_dC1 * BCfluidState.massFraction(nPhaseIdx, wCompIdx)
827 + dv_dC2 * BCfluidState.massFraction(nPhaseIdx, nCompIdx));
829 lambdaNW = lambdaNWBound;
833 Scalar entry = (lambdaW * dV_w + lambdaNW * dV_n)
834 * (fabs(unitOuterNormal * permeability) / dist) * faceArea;
837 Scalar rightEntry = (lambdaW * densityW * dV_w + lambdaNW * densityNW * dV_n)
838 * fabs(unitOuterNormal * permeability) * (gravity_ * unitDistVec) * faceArea ;
842 Scalar pCGradient = (cellDataI.capillaryPressure() - pcBound) / dist;
848 rightEntry += lambdaNW * dV_n * pCGradient * fabs(unitOuterNormal * permeability) * faceArea;
854 rightEntry -= lambdaW * dV_w * pCGradient * fabs(unitOuterNormal * permeability) * faceArea;
861 entries[matrix] += entry;
862 entries[rhs] += entry * primaryVariablesOnBoundary[Indices::pressureEqIdx];
863 entries[rhs] -= rightEntry;
870 else if(bcType.isNeumann(Indices::pressureEqIdx))
872 PrimaryVariables J(NAN);
873 problem().neumann(J, intersection);
876 J[contiWEqIdx] /= cellDataI.density(wPhaseIdx);
877 J[contiNEqIdx] /= cellDataI.density(nPhaseIdx);
881 J[contiWEqIdx] *= dv_dC1;
882 J[contiNEqIdx] *= dv_dC2;
885 entries[rhs] -= (J[contiWEqIdx] + J[contiNEqIdx]) * faceArea;
888 DUNE_THROW(Dune::NotImplemented,
"Boundary Condition neither Dirichlet nor Neumann!");
907 GlobalPosition globalPos = element.geometry().center();
910 int eIdxGlobal =
problem().variables().index(element);
911 CellData& cellData =
problem().variables().cellData(eIdxGlobal);
914 FluidState& fluidState = cellData.manipulateFluidState();
916 Scalar temperature_ =
problem().temperatureAtPos(globalPos);
923 Scalar Z0 = cellData.massConcentration(wCompIdx)
924 / (cellData.massConcentration(wCompIdx)
925 + cellData.massConcentration(nCompIdx));
928 if(Z0 < 0. || Z0 > 1.)
930 Dune::dgrave <<
"Feed mass fraction unphysical: Z0 = " << Z0
931 <<
" at global Idx " << eIdxGlobal
932 <<
" , because totalConcentration(wCompIdx) = "
933 << cellData.totalConcentration(wCompIdx)
934 <<
" and totalConcentration(nCompIdx) = "
935 << cellData.totalConcentration(nCompIdx)<< std::endl;
939 cellData.setTotalConcentration(wCompIdx, 0.);
940 problem().transportModel().totalConcentration(wCompIdx, eIdxGlobal) = 0.;
941 Dune::dgrave <<
"Regularize totalConcentration(wCompIdx) = "
942 << cellData.totalConcentration(wCompIdx)<< std::endl;
947 cellData.setTotalConcentration(nCompIdx, 0.);
948 problem().transportModel().totalConcentration(nCompIdx,eIdxGlobal) = 0.;
949 Dune::dgrave <<
"Regularize totalConcentration(eIdxGlobal, nCompIdx) = "
950 << cellData.totalConcentration(nCompIdx)<< std::endl;
958 unsigned int maxiter = 6;
959 Scalar pc = cellData.capillaryPressure();
961 for (
unsigned int iter = 0; iter < maxiter; iter++)
967 pressure[wPhaseIdx] = asImp_().pressure(eIdxGlobal);
968 pressure[nPhaseIdx] = asImp_().pressure(eIdxGlobal) + pc;
973 pressure[wPhaseIdx] = asImp_().pressure(eIdxGlobal) - pc;
974 pressure[nPhaseIdx] = asImp_().pressure(eIdxGlobal);
981 problem().spatialParams().porosity(element), temperature_);
985 pc = MaterialLaw::pc(
problem().spatialParams().materialLawParams(element),
986 fluidState.saturation(wPhaseIdx));
988 if (fabs(oldPc-pc)<10 && iter != 0)
991 if (iter++ == maxiter)
992 Dune::dinfo << iter <<
"times iteration of pc was applied at Idx " << eIdxGlobal
993 <<
", pc delta still " << fabs(oldPc-pc) << std::endl;
998 pressure[wPhaseIdx] =
pressure[nPhaseIdx] = asImp_().pressure()[eIdxGlobal];
1000 problem().spatialParams().porosity(element), temperature_);
1004 cellData.setMobility(wPhaseIdx, MaterialLaw::krw(
problem().spatialParams().materialLawParams(element),
1005 fluidState.saturation(wPhaseIdx))
1006 / cellData.viscosity(wPhaseIdx));
1007 cellData.setMobility(nPhaseIdx, MaterialLaw::krn(
problem().spatialParams().materialLawParams(element),
1008 fluidState.saturation(wPhaseIdx))
1009 / cellData.viscosity(nPhaseIdx));
1012 Scalar sumConc = (cellData.totalConcentration(wCompIdx)
1013 + cellData.totalConcentration(nCompIdx));
1014 Scalar massw = sumConc * fluidState.phaseMassFraction(wPhaseIdx);
1015 Scalar massn = sumConc * fluidState.phaseMassFraction(nPhaseIdx);
1017 if (Dune::FloatCmp::eq<Scalar>((cellData.density(wPhaseIdx)*cellData.density(nPhaseIdx)), 0))
1018 DUNE_THROW(Dune::MathError,
"Sequential2p2c::postProcessUpdate: try to divide by 0 density");
1019 Scalar vol = massw / cellData.density(wPhaseIdx) + massn / cellData.density(nPhaseIdx);
1020 if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(
problem().timeManager().timeStepSize(), 0.0, 1.0e-30))
1022 cellData.volumeError()=(vol -
problem().spatialParams().porosity(element));
1025 if (isnan(cellData.volumeError()))
1027 DUNE_THROW(Dune::MathError,
"Sequential2p2c::postProcessUpdate:\n"
1028 <<
"volErr[" << eIdxGlobal <<
"] isnan: vol = " << vol
1029 <<
", massw = " << massw <<
", rho_l = " << cellData.density(wPhaseIdx)
1030 <<
", massn = " << massn <<
", rho_g = " << cellData.density(nPhaseIdx)
1031 <<
", poro = " <<
problem().spatialParams().porosity(element)
1032 <<
", dt = " <<
problem().timeManager().timeStepSize());
1036 cellData.volumeError()=0.;