47 using GridView =
typename GridGeometry::GridView;
48 using FVElementGeometry =
typename GridGeometry::LocalView;
49 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
55 using Element =
typename Grid::template Codim<0>::Entity;
56 using ElementSolution = std::decay_t<decltype(elementSolution(std::declval<Element>(),
57 std::declval<SolutionVector>(),
58 std::declval<GridGeometry>()))>;
61 using Indices =
typename ModelTraits::Indices;
65 AdaptedValues() : associatedMass(0.0) {}
68 PrimaryVariables associatedMass;
72 using PersistentContainer = Dune::PersistentContainer<Grid, AdaptedValues>;
74 static constexpr int dim = Grid::dimension;
75 static constexpr int dimWorld = Grid::dimensionworld;
79 enum { saturationIdx = Indices::saturationIdx };
84 phase0Idx = FluidSystem::phase0Idx,
85 phase1Idx = FluidSystem::phase1Idx,
93 static constexpr auto formulation = ModelTraits::priVarFormulation();
96 static_assert(!FluidSystem::isCompressible(phase0Idx)
97 && !FluidSystem::isCompressible(phase1Idx),
98 "This adaption helper is only mass conservative for incompressible fluids!");
101 static_assert(formulation == p0s1 || formulation == p1s0,
"Chosen formulation not known to the TwoPGridDataTransfer");
113 std::shared_ptr<GridGeometry> gridGeometry,
114 std::shared_ptr<const GridVariables> gridVariables,
118 , gridGeometry_(gridGeometry)
119 , gridVariables_(gridVariables)
121 , adaptionMap_(gridGeometry->gridView().grid(), 0)
132 void store(
const Grid& grid)
override
134 adaptionMap_.resize();
136 for (
auto level = grid.maxLevel(); level >= 0; level--)
138 auto fvGeometry =
localView(*gridGeometry_);
139 for (
const auto& element : elements(grid.levelGridView(level)))
142 auto& adaptedValues = adaptionMap_[element];
145 if (element.isLeaf())
147 fvGeometry.bindElement(element);
153 for (
const auto& scv :
scvs(fvGeometry))
155 VolumeVariables volVars;
156 volVars.update(adaptedValues.u, *problem_, element, scv);
158 const auto poreVolume = Extrusion::volume(fvGeometry, scv)*volVars.porosity();
159 adaptedValues.associatedMass[phase1Idx] += poreVolume * volVars.density(phase1Idx) * volVars.saturation(phase1Idx);
160 adaptedValues.associatedMass[phase0Idx] += poreVolume * volVars.density(phase0Idx) * volVars.saturation(phase0Idx);
164 adaptedValues.count = 1;
165 adaptedValues.wasLeaf =
true;
168 if (element.level() > 0)
170 auto& adaptedValuesFather = adaptionMap_[element.father()];
173 if(&adaptedValues != &adaptedValuesFather)
174 storeAdaptionValues(adaptedValues, adaptedValuesFather);
180 if(isBox && !element.isLeaf())
199 gridGeometry_->update(grid.leafGridView());
208 adaptionMap_.resize();
209 sol_.resize(gridGeometry_->numDofs());
215 using VertexMass = Dune::FieldVector<Scalar, 2>;
216 std::vector<VertexMass> vertexMass;
219 vertexMass.assign(gridGeometry_->numDofs(), VertexMass(0.0));
223 auto fvGeometry =
localView(*gridGeometry_);
224 for (
const auto& element : elements(gridGeometry_->gridView(), Dune::Partitions::interior))
226 if (!element.isNew())
228 const auto& adaptedValues = adaptionMap_[element];
229 fvGeometry.bindElement(element);
232 auto elemSol = adaptedValues.u;
234 elemSol[0] /= adaptedValues.count;
237 for (
const auto& scv :
scvs(fvGeometry))
239 VolumeVariables volVars;
240 volVars.update(elemSol, *problem_, element, scv);
243 sol_[scv.dofIndex()] = elemSol[scv.localDofIndex()];
245 const auto dofIdxGlobal = scv.dofIndex();
250 if (!adaptedValues.wasLeaf)
252 if (formulation == p0s1)
254 sol_[dofIdxGlobal][saturationIdx] = adaptedValues.associatedMass[phase1Idx];
255 sol_[dofIdxGlobal][saturationIdx] /= elementVolume * volVars.density(phase1Idx) * volVars.porosity();
257 else if (formulation == p1s0)
259 sol_[dofIdxGlobal][saturationIdx] = adaptedValues.associatedMass[phase0Idx];
260 sol_[dofIdxGlobal][saturationIdx] /= elementVolume * volVars.density(phase0Idx) * volVars.porosity();
268 const auto scvVolume = Extrusion::volume(fvGeometry, scv);
269 if (formulation == p0s1)
271 vertexMass[dofIdxGlobal][0] += scvVolume / elementVolume * adaptedValues.associatedMass[phase1Idx];
272 vertexMass[dofIdxGlobal][1] += scvVolume * volVars.density(phase1Idx) * volVars.porosity();
274 else if (formulation == p1s0)
276 vertexMass[dofIdxGlobal][0] += scvVolume / elementVolume * adaptedValues.associatedMass[phase0Idx];
277 vertexMass[dofIdxGlobal][1] += scvVolume * volVars.density(phase0Idx) * volVars.porosity();
285 assert(
element.hasFather() &&
"new element does not have a father element!");
288 auto fatherElement =
element.father();
289 while (fatherElement.isNew() && fatherElement.level() > 0)
290 fatherElement = fatherElement.father();
294 const auto& adaptedValuesFather = adaptionMap_[fatherElement];
297 Scalar massFather = 0.0;
298 if (formulation == p0s1)
299 massFather = adaptedValuesFather.associatedMass[phase1Idx];
300 else if (formulation == p1s0)
301 massFather = adaptedValuesFather.associatedMass[phase0Idx];
304 auto elemSolSon = adaptedValuesFather.u;
305 elemSolSon[0] /= adaptedValuesFather.count;
307 fvGeometry.bindElement(element);
309 for (
const auto& scv :
scvs(fvGeometry))
311 VolumeVariables volVars;
312 volVars.update(elemSolSon, *problem_, element, scv);
315 sol_[scv.dofIndex()] = elemSolSon[0];
318 Scalar massCoeffSon = 0.0;
319 if (formulation == p0s1)
320 massCoeffSon = Extrusion::volume(fvGeometry, scv) * volVars.density(phase1Idx) * volVars.porosity();
321 else if (formulation == p1s0)
322 massCoeffSon = Extrusion::volume(fvGeometry, scv) * volVars.density(phase0Idx) * volVars.porosity();
323 sol_[scv.dofIndex()][saturationIdx] =
324 ( Extrusion::volume(fvGeometry, scv)/
volume(fatherElement.geometry(), Extrusion{})*massFather )/massCoeffSon;
329 auto& adaptedValuesFather = adaptionMap_[fatherElement];
331 fvGeometry.bindElement(element);
334 ElementSolution elemSolSon(element, sol_, *gridGeometry_);
335 const auto fatherGeometry = fatherElement.geometry();
336 for (
const auto& scv :
scvs(fvGeometry))
338 fatherElement, fatherGeometry, adaptedValuesFather.u, scv.dofPosition()
342 const auto fatherElementVolume =
volume(fatherGeometry, Extrusion{});
343 for (
const auto& scv :
scvs(fvGeometry))
345 VolumeVariables volVars;
346 volVars.update(elemSolSon, *problem_, element, scv);
348 const auto dofIdxGlobal = scv.dofIndex();
349 const auto scvVolume = Extrusion::volume(fvGeometry, scv);
350 if (formulation == p0s1)
352 vertexMass[dofIdxGlobal][0] += scvVolume / fatherElementVolume * adaptedValuesFather.associatedMass[phase1Idx];
353 vertexMass[dofIdxGlobal][1] += scvVolume * volVars.density(phase1Idx) * volVars.porosity();
355 else if (formulation == p1s0)
357 vertexMass[dofIdxGlobal][0] += scvVolume / fatherElementVolume * adaptedValuesFather.associatedMass[phase0Idx];
358 vertexMass[dofIdxGlobal][1] += scvVolume * volVars.density(phase0Idx) * volVars.porosity();
362 sol_[dofIdxGlobal] = elemSolSon[scv.localDofIndex()];
374 if constexpr (Dune::Capabilities::canCommunicate<Grid, dim>::v)
376 const auto& gridView = gridGeometry_->gridView();
377 if (gridView.comm().size() > 1)
379 using VertexMapper = std::decay_t<
decltype(gridGeometry_->vertexMapper())>;
381 gridGeometry_->vertexMapper(), vertexMass
383 gridView.communicate(
384 massHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
391 for(std::size_t dofIdxGlobal = 0; dofIdxGlobal < gridGeometry_->numDofs(); dofIdxGlobal++)
392 if (vertexMass[dofIdxGlobal][1] > 0.0)
393 sol_[dofIdxGlobal][saturationIdx] = vertexMass[dofIdxGlobal][0] / vertexMass[dofIdxGlobal][1];
400 static constexpr int dofCodim = isBox ? dim : 0;
401 if constexpr (Dune::Capabilities::canCommunicate<Grid, dofCodim>::v)
403 const auto& gridView = gridGeometry_->gridView();
404 if (gridView.comm().size() > 1)
406 using DofMapper = std::decay_t<
decltype(gridGeometry_->dofMapper())>;
408 gridGeometry_->dofMapper(), sol_
410 gridView.communicate(
411 dataHandle, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication
418 adaptionMap_.resize(
typename PersistentContainer::Value() );
419 adaptionMap_.shrinkToFit();
420 adaptionMap_.fill(
typename PersistentContainer::Value() );
433 static void storeAdaptionValues(AdaptedValues& adaptedValues,
434 AdaptedValues& adaptedValuesFather)
437 adaptedValuesFather.associatedMass += adaptedValues.associatedMass;
444 auto values = adaptedValues.u[0];
445 values /= adaptedValues.count;
446 adaptedValuesFather.u[0] += values;
449 adaptedValuesFather.count += 1;
452 adaptedValuesFather.wasLeaf =
false;
458 adaptedValuesFather.count = 1;
461 adaptedValuesFather.wasLeaf =
false;
465 std::shared_ptr<const Problem> problem_;
466 std::shared_ptr<GridGeometry> gridGeometry_;
467 std::shared_ptr<const GridVariables> gridVariables_;
468 SolutionVector& sol_;
469 PersistentContainer adaptionMap_;