160 unsigned int size_ =
problem_.gridView().size(0);
162 updateVec[wCompIdx].resize(size_);
163 updateVec[nCompIdx].resize(size_);
164 updateVec[wCompIdx] = 0;
165 updateVec[nCompIdx] = 0;
180 for (
int i = 0; i< problem().gridView().size(0); i++)
182 CellData& cellDataI = problem().variables().cellData(i);
183 for(
int compIdx = 0; compIdx < getPropValue<TypeTag, Properties::NumComponents>(); compIdx++)
186 = cellDataI.totalConcentration(compIdx);
192 int restrictingCell = -1;
194 Dune::FieldVector<Scalar, 2> entries(0.), timestepFlux(0.);
196 for (
const auto& element : elements(problem().gridView()))
199 int globalIdxI = problem().variables().index(element);
200 CellData& cellDataI = problem().variables().cellData(globalIdxI);
203 double sumfactorin = 0;
204 double sumfactorout = 0;
208 LocalTimesteppingData& localData = this->
timeStepData_[globalIdxI];
209 for (
int i = 0; i < 2*dim; i++)
211 if (localData.faceTargetDt[i] < this->accumulatedDt_ + this->dtThreshold_)
213 localData.faceFluxes[i] = 0.0;
219 const auto isEndIt = problem().gridView().iend(element);
220 for (
auto isIt = problem().gridView().ibegin(element); isIt != isEndIt; ++isIt)
222 const auto& intersection = *isIt;
224 int indexInInside = intersection.indexInInside();
227 if (intersection.neighbor())
229 if (
enableMPFA && (intersection.outside().level() != element.level()))
230 getMpfaFlux(entries, timestepFlux, isIt, cellDataI);
232 this->
getFlux(entries, timestepFlux, intersection, cellDataI);
236 if (intersection.boundary())
243 LocalTimesteppingData& localData = this->
timeStepData_[globalIdxI];
245 if (localData.faceTargetDt[indexInInside] < this->accumulatedDt_ + this->dtThreshold_)
247 localData.faceFluxes[indexInInside] += entries;
253 updateVec[wCompIdx][globalIdxI] += entries[wCompIdx];
254 updateVec[nCompIdx][globalIdxI] += entries[nCompIdx];
258 sumfactorin += timestepFlux[0];
259 sumfactorout += timestepFlux[1];
265 LocalTimesteppingData& localData = this->
timeStepData_[globalIdxI];
266 for (
int i=0; i < 2*dim; i++)
268 updateVec[wCompIdx][globalIdxI] += localData.faceFluxes[i][wCompIdx];
269 updateVec[nCompIdx][globalIdxI] += localData.faceFluxes[i][nCompIdx];
274 PrimaryVariables q(NAN);
275 problem().source(q, element);
276 updateVec[wCompIdx][globalIdxI] += q[contiWEqIdx];
277 updateVec[nCompIdx][globalIdxI] += q[contiNEqIdx];
281 sumfactorin = max(sumfactorin,sumfactorout)
282 / problem().spatialParams().porosity(element);
288 if ( 1./sumfactorin < dt)
291 restrictingCell= globalIdxI;
296 if ( 1./sumfactorin < dt)
299 restrictingCell= globalIdxI;
307 using ElementMapper =
typename SolutionTypes::ElementMapper;
308 using DataHandle = VectorExchange<ElementMapper, Dune::BlockVector<Dune::FieldVector<Scalar, 1> > >;
309 for (
int i = 0; i < updateVec.size(); i++)
311 DataHandle dataHandle(
problem_.variables().elementMapper(), updateVec[i]);
312 problem_.gridView().template communicate<DataHandle>(dataHandle,
313 Dune::InteriorBorder_All_Interface,
314 Dune::ForwardCommunication);
316 dt =
problem_.gridView().comm().min(dt);
321 Dune::dinfo <<
"Timestep restricted by CellIdx " << restrictingCell <<
" leads to dt = "
324 Dune::dinfo <<
" Averageing done for " << this->
averagedFaces_ <<
" faces. "<< std::endl;
351 const IntersectionIterator& intersectionIterator, CellData& cellDataI)
356 auto elementI = intersectionIterator->inside();
357 int globalIdxI = problem().variables().index(elementI);
360 const GlobalPosition globalPos = elementI.geometry().center();
361 const GlobalPosition& gravity_ = problem().gravity();
363 Scalar volume = elementI.geometry().volume();
366 Scalar pressI = problem().pressureModel().pressure(globalIdxI);
367 Scalar pcI = cellDataI.capillaryPressure();
369 PhaseVector SmobI(0.);
371 SmobI[wPhaseIdx] = max((cellDataI.saturation(wPhaseIdx)
372 - problem().spatialParams().materialLawParams(elementI).swr())
374 SmobI[nPhaseIdx] = max((cellDataI.saturation(nPhaseIdx)
375 - problem().spatialParams().materialLawParams(elementI).snr())
378 Scalar densityWI (0.), densityNWI(0.);
379 densityWI= cellDataI.density(wPhaseIdx);
380 densityNWI = cellDataI.density(nPhaseIdx);
382 PhaseVector potential(0.);
385 auto neighbor = intersectionIterator->outside();
386 int globalIdxJ = problem().variables().index(neighbor);
387 CellData& cellDataJ = problem().variables().cellData(globalIdxJ);
390 const GlobalPosition& globalPosNeighbor = neighbor.geometry().center();
393 GlobalPosition distVec = globalPosNeighbor - globalPos;
395 Scalar dist = distVec.two_norm();
397 GlobalPosition unitDistVec(distVec);
401 Scalar densityWJ (0.), densityNWJ(0.);
402 densityWJ = cellDataJ.density(wPhaseIdx);
403 densityNWJ = cellDataJ.density(nPhaseIdx);
406 double densityW_mean = (densityWI + densityWJ) * 0.5;
407 double densityNW_mean = (densityNWI + densityNWJ) * 0.5;
409 double pressJ = problem().pressureModel().pressure(globalIdxJ);
410 Scalar pcJ = cellDataJ.capillaryPressure();
414 GlobalPosition globalPos3(0.);
416 TransmissivityMatrix T(0.);
417 IntersectionIterator additionalIsIt = intersectionIterator;
418 TransmissivityMatrix additionalT(0.);
421 = problem().variables().getMpfaData(*intersectionIterator, additionalIsIt, T, additionalT,
422 globalPos3, globalIdx3);
423 if (halfedgesStored == 0)
424 halfedgesStored = problem().pressureModel().computeTransmissibilities(intersectionIterator,additionalIsIt,
425 T,additionalT, globalPos3, globalIdx3 );
428 Scalar press3 = problem().pressureModel().pressure(globalIdx3);
429 CellData& cellData3 = problem().variables().cellData(globalIdx3);
430 Scalar pc3 = cellData3.capillaryPressure();
431 Scalar temp1 = globalPos * gravity_;
432 Scalar temp2 = globalPosNeighbor * gravity_;
433 Scalar temp3 = globalPos3 * gravity_;
436 potential[wPhaseIdx] += (pressI-temp1*densityW_mean) * T[2]
437 +(pressJ-temp2*densityW_mean) * T[0]
438 +(press3- temp3*densityW_mean) * T[1];
439 potential[nPhaseIdx] += (pressI+pcI-temp1*densityNW_mean) * T[2]
440 +(pressJ+pcJ-temp2*densityNW_mean) * T[0]
441 +(press3+pc3- temp3*densityNW_mean) * T[1];
443 if(halfedgesStored == 2)
445 int AdditionalIdx = problem().variables().index(additionalIsIt->outside());
446 CellData& cellDataAdditional = problem().variables().cellData(AdditionalIdx);
447 potential[wPhaseIdx] += (pressI-temp1*densityW_mean) * additionalT[2]
448 +(pressJ-temp2*densityW_mean) * additionalT[0]
449 +(problem().pressureModel().pressure(AdditionalIdx)
450 -(additionalIsIt->outside().geometry().center()*gravity_*densityW_mean)
452 potential[nPhaseIdx] += (pressI+pcI-temp1*densityNW_mean) * additionalT[2]
453 +(pressJ+pcJ-temp2*densityNW_mean) * additionalT[0]
454 +(problem().pressureModel().pressure(AdditionalIdx)
455 + cellDataAdditional.capillaryPressure()
456 -(additionalIsIt->outside().geometry().center()*gravity_*densityNW_mean)
462 potential[wPhaseIdx] += (pressI-pcI-temp1*densityW_mean) * T[2]
463 + (pressJ-pcJ-temp2*densityW_mean) * T[0]
464 + (press3-pc3- temp3*densityW_mean) * T[1];
465 potential[nPhaseIdx] += (pressI-temp1*densityNW_mean) * T[2]
466 + (pressJ-temp2*densityNW_mean) * T[0]
467 + (press3-temp3*densityNW_mean) * T[1];
469 if(halfedgesStored == 2)
471 int AdditionalIdx = problem().variables().index(additionalIsIt->outside());
472 CellData& cellDataAdditional = problem().variables().cellData(AdditionalIdx);
474 potential[wPhaseIdx] += (pressI-pcI-temp1*densityW_mean) * additionalT[2]
475 +(pressJ-pcJ-temp2*densityW_mean) * additionalT[0]
476 +(problem().pressureModel().pressure(AdditionalIdx)
477 - cellDataAdditional.capillaryPressure()
478 -(additionalIsIt->outside().geometry().center()*gravity_*densityW_mean)
480 potential[nPhaseIdx] += (pressI-temp1*densityNW_mean) * additionalT[2]
481 +(pressJ-temp2*densityNW_mean) * additionalT[0]
482 +(problem().pressureModel().pressure(AdditionalIdx)
483 -(additionalIsIt->outside().geometry().center()*gravity_*densityNW_mean))
490 Dune::FieldVector<bool, NumPhases> doUpwinding(
true);
491 PhaseVector lambda(0.);
492 for(
int phaseIdx = 0; phaseIdx < NumPhases; phaseIdx++)
495 if(phaseIdx == wPhaseIdx)
496 contiEqIdx = contiWEqIdx;
498 contiEqIdx = contiNEqIdx;
502 if(potential[phaseIdx] > 0.)
504 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
505 if(elementI.level()>neighbor.level())
506 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx,
true);
508 else if(potential[phaseIdx] < 0.)
510 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
511 if(elementI.level()>neighbor.level())
512 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx,
false);
516 doUpwinding[phaseIdx] =
false;
517 if(elementI.level()>neighbor.level())
518 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx,
false);
520 cellDataJ.setUpwindCell(intersectionIterator->indexInOutside(), contiEqIdx,
false);
525 bool cellIwasUpwindCell;
527 if(elementI.level()>neighbor.level())
528 cellIwasUpwindCell = cellDataI.isUpwindCell(intersectionIterator->indexInInside(), contiEqIdx);
530 cellIwasUpwindCell = !cellDataJ.isUpwindCell(intersectionIterator->indexInOutside(), contiEqIdx);
532 if (potential[phaseIdx] > 0. && cellIwasUpwindCell)
533 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
534 else if (potential[phaseIdx] < 0. && !cellIwasUpwindCell)
535 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
538 doUpwinding[phaseIdx] =
false;
543 if (potential[phaseIdx] > 0. && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(cellDataJ.mobility(phaseIdx), 0.0, 1.0e-30))
544 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
546 else if (potential[phaseIdx] < 0. && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(cellDataI.mobility(phaseIdx), 0.0, 1.0e-30))
547 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
549 doUpwinding[phaseIdx] =
false;
553 if(!doUpwinding[phaseIdx])
556 if(cellDataI.mobility(phaseIdx)+cellDataJ.mobility(phaseIdx)==0.)
558 potential[phaseIdx] = 0;
563 fluxEntries[wCompIdx] -= potential[phaseIdx] / volume
564 *
harmonicMean(cellDataI.massFraction(phaseIdx, wCompIdx) * cellDataI.mobility(phaseIdx) * cellDataI.density(phaseIdx),
565 cellDataJ.massFraction(phaseIdx, wCompIdx) * cellDataJ.mobility(phaseIdx) * cellDataJ.density(phaseIdx));
566 fluxEntries[nCompIdx] -= potential[phaseIdx] / volume
567 *
harmonicMean(cellDataI.massFraction(phaseIdx, nCompIdx) * cellDataI.mobility(phaseIdx) * cellDataI.density(phaseIdx),
568 cellDataJ.massFraction(phaseIdx, nCompIdx) * cellDataJ.mobility(phaseIdx) * cellDataJ.density(phaseIdx));
572 timestepFlux[0] += max(0.,
573 - potential[phaseIdx] / volume
574 *
harmonicMean(cellDataI.mobility(phaseIdx),cellDataJ.mobility(phaseIdx)));
576 timestepFlux[1] += max(0.,
577 potential[phaseIdx] / volume
578 *
harmonicMean(cellDataI.mobility(phaseIdx),cellDataJ.mobility(phaseIdx))/SmobI[phaseIdx]);
582 #if DUNE_MINIMAL_DEBUG_LEVEL < 3
584 if(globalIdxI > globalIdxJ)
585 Dune::dinfo <<
"harmonicMean flux of phase" << phaseIdx <<
" used from cell" << globalIdxI<<
" into " << globalIdxJ
586 <<
" ; TE upwind I = "<< cellDataI.isUpwindCell(intersectionIterator->indexInInside(), contiEqIdx)
587 <<
" but pot = "<< potential[phaseIdx] <<
" \n";
591 potential[phaseIdx] = 0;
598 double velocityJIw = max((-lambda[wPhaseIdx] * potential[wPhaseIdx]) / volume, 0.0);
599 double velocityIJw = max(( lambda[wPhaseIdx] * potential[wPhaseIdx]) / volume, 0.0);
600 double velocityJIn = max((-lambda[nPhaseIdx] * potential[nPhaseIdx]) / volume, 0.0);
601 double velocityIJn = max(( lambda[nPhaseIdx] * potential[nPhaseIdx]) / volume, 0.0);
604 timestepFlux[0] += velocityJIw + velocityJIn;
606 double foutw = velocityIJw/SmobI[wPhaseIdx];
607 double foutn = velocityIJn/SmobI[nPhaseIdx];
610 if (isnan(foutw) || isinf(foutw) || foutw < 0) foutw = 0;
611 if (isnan(foutn) || isinf(foutn) || foutn < 0) foutn = 0;
612 timestepFlux[1] += foutw + foutn;
614 fluxEntries[wCompIdx] +=
615 velocityJIw * cellDataJ.massFraction(wPhaseIdx, wCompIdx) * densityWJ
616 - velocityIJw * cellDataI.massFraction(wPhaseIdx, wCompIdx) * densityWI
617 + velocityJIn * cellDataJ.massFraction(nPhaseIdx, wCompIdx) * densityNWJ
618 - velocityIJn * cellDataI.massFraction(nPhaseIdx, wCompIdx) * densityNWI;
619 fluxEntries[nCompIdx] +=
620 velocityJIw * cellDataJ.massFraction(wPhaseIdx, nCompIdx) * densityWJ
621 - velocityIJw * cellDataI.massFraction(wPhaseIdx, nCompIdx) * densityWI
622 + velocityJIn * cellDataJ.massFraction(nPhaseIdx, nCompIdx) * densityNWJ
623 - velocityIJn * cellDataI.massFraction(nPhaseIdx, nCompIdx) * densityNWI;