23#ifndef DUMUX_BUCKLEYLEVERETT_ANALYTICAL_HH
24#define DUMUX_BUCKLEYLEVERETT_ANALYTICAL_HH
39template<
typename Scalar,
typename Law>
48template<
typename Scalar>
57template<
typename Scalar>
76 using SpatialParams =
typename GET_PROP_TYPE(TypeTag, SpatialParams);
77 using MaterialLaw =
typename SpatialParams::MaterialLaw;
78 using MaterialLawParams =
typename MaterialLaw::Params;
80 using FluidSystem =
typename GET_PROP_TYPE(TypeTag, FluidSystem);
81 using FluidState =
typename GET_PROP_TYPE(TypeTag, FluidState);
83 using Indices =
typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
87 dimworld = GridView::dimensionworld
91 wPhaseIdx = Indices::wPhaseIdx,
92 nPhaseIdx = Indices::nPhaseIdx
95 using BlockVector = Dune::BlockVector<Dune::FieldVector<Scalar, 1> >;
96 using Element =
typename GridView::template Codim<0>::Entity;
97 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
103 void initializeAnalytic()
105 int size = problem_.gridView().size(0);
106 analyticSolution_.resize(size);
107 analyticSolution_ = 0;
108 errorGlobal_.resize(size);
110 errorLocal_.resize(size);
119 void prepareAnalytic()
121 const auto& dummyElement = *problem_.gridView().template begin<0>();
122 const MaterialLawParams& materialLawParams(problem_.spatialParams().materialLawParams(dummyElement));
124 swr_ = materialLawParams.swr();
125 snr_ = materialLawParams.snr();
126 Scalar
porosity = problem_.spatialParams().porosity(dummyElement);
128 FluidState fluidState;
129 fluidState.setTemperature(problem_.temperature(dummyElement));
130 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(dummyElement));
131 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(dummyElement));
138 std::pair<Scalar, Scalar> entry;
139 entry.first = 1 - snr_;
141 entry.second = vTot_ / (
porosity * (1 - swr_ - snr_));
143 frontParams_.push_back(entry);
148 Scalar fw0 = MaterialLaw::krw(materialLawParams, sw0)/viscosityW;
149 fw0 /= (fw0 + MaterialLaw::krn(materialLawParams, sw0)/viscosityNW);
150 Scalar sw1 = sw0 + deltaS_;
151 Scalar fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW;
152 fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW);
153 Scalar tangentSlopeOld = (fw1 - fw0)/(sw1 - sw0);
155 fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW;
156 fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW);
157 Scalar tangentSlopeNew = (fw1 - fw0)/(sw1 - sw0);
159 while (tangentSlopeNew >= tangentSlopeOld && sw1 < (1.0 - snr_))
161 tangentSlopeOld = tangentSlopeNew;
163 fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW;
164 fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW);
165 tangentSlopeNew = (fw1 - fw0)/(sw1 - sw0);
169 fw0 = MaterialLaw::krw(materialLawParams, sw0)/viscosityW;
170 fw0 /= (fw0 + MaterialLaw::krn(materialLawParams, sw0)/viscosityNW);
171 Scalar sw2 = sw1 + deltaS_;
172 Scalar fw2 = MaterialLaw::krw(materialLawParams, sw2)/viscosityW;
173 fw2 /= (fw2 + MaterialLaw::krn(materialLawParams, sw2)/viscosityNW);
174 while (sw1 <= (1.0 - snr_))
176 std::pair<Scalar, Scalar> entry;
179 Scalar dfwdsw = (fw2 - fw0)/(sw2 - sw0);
181 entry.second = vTot_ /
porosity * dfwdsw;
183 frontParams_.push_back(entry);
191 fw2 = MaterialLaw::krw(materialLawParams, sw2)/viscosityW;
192 fw2 /= (fw2 + MaterialLaw::krn(materialLawParams, sw2)/viscosityNW);
201 Scalar globalVolume = 0;
202 Scalar errorNorm = 0.0;
204 for (
const auto& element : elements(problem_.gridView()))
207 int index = problem_.variables().index(element);
209 Scalar sat = problem_.variables().cellData(index).saturation(wPhaseIdx);
211 Scalar volume = element.geometry().volume();
213 Scalar error = analyticSolution_[index] - sat;
215 errorLocal_[index] = error;
217 if (sat > swr_ + 1e-6)
219 globalVolume += volume;
220 errorNorm += (volume*volume*error*error);
224 if (globalVolume > 0.0 && errorNorm > 0.0)
227 errorNorm = sqrt(errorNorm)/globalVolume;
228 errorGlobal_ = errorNorm;
240 Scalar time = problem_.timeManager().time() + problem_.timeManager().timeStepSize();
244 Scalar xMax = frontParams_[0].second * time;
247 for (
const auto& element : elements(problem_.gridView()))
250 GlobalPosition globalPos = element.geometry().center();
252 int index = problem_.variables().index(element);
254 if (globalPos[0] > xMax)
255 analyticSolution_[index] = swr_;
258 int size = frontParams_.size();
261 analyticSolution_[index] = frontParams_[0].first;
266 for (
int i = 0; i < size-1; i++)
268 Scalar x = frontParams_[i].second * time;
269 Scalar xMinus = frontParams_[i+1].second * time;
270 if (globalPos[0] <= x && globalPos[0] > xMinus)
272 analyticSolution_[index] = frontParams_[i].first
273 - (frontParams_[i].first - frontParams_[i+1].first)
274 / (x - xMinus) * (x - globalPos[0]);
292 initializeAnalytic();
299 return analyticSolution_;
303 template<
class MultiWriter>
306 int size = problem_.gridView().size(0);
307 BlockVector *analyticSolution = writer.allocateManagedBuffer (size);
308 BlockVector *errorGlobal = writer.allocateManagedBuffer (size);
309 BlockVector *errorLocal = writer.allocateManagedBuffer (size);
311 *analyticSolution = analyticSolution_;
312 *errorGlobal = errorGlobal_;
313 *errorLocal = errorLocal_;
315 writer.attachCellData(*analyticSolution,
"saturation (exact solution)");
316 writer.attachCellData(*errorGlobal,
"global error");
317 writer.attachCellData(*errorLocal,
"local error");
324 problem_(problem), analyticSolution_(0), errorGlobal_(0), errorLocal_(0), frontParams_(0), deltaS_(1e-3)
330 initializeAnalytic();
338 BlockVector analyticSolution_;
339 BlockVector errorGlobal_;
340 BlockVector errorLocal_;
342 std::vector<std::pair<Scalar, Scalar> > frontParams_;
343 const Scalar deltaS_;
#define GET_PROP_TYPE(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:283
Linear capillary pressure and relative permeability <-> saturation relations.
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
std::string viscosity(int phaseIdx) noexcept
I/O name of viscosity for multiphase systems.
Definition: name.hh:74
std::string porosity() noexcept
I/O name of porosity.
Definition: name.hh:139
This material law takes a material law defined for effective saturations and converts it to a materia...
Definition: 2p/efftoabslaw.hh:60
Linear capillary pressure and relative permeability <-> saturation relations.
Definition: linearmaterial.hh:48
IMplicit Pressure Explicit Saturation (IMPES) scheme for the solution of the Buckley-Leverett problem...
Definition: buckleyleverettanalyticsolution.hh:41
static bool isLinear()
Definition: buckleyleverettanalyticsolution.hh:42
static bool isLinear()
Definition: buckleyleverettanalyticsolution.hh:51
static bool isLinear()
Definition: buckleyleverettanalyticsolution.hh:60
Definition: buckleyleverettanalyticsolution.hh:71
void initialize(Scalar vTot)
Definition: buckleyleverettanalyticsolution.hh:327
void addOutputVtkFields(MultiWriter &writer)
Definition: buckleyleverettanalyticsolution.hh:304
BuckleyLeverettAnalytic(Problem &problem)
Construct an IMPES object.
Definition: buckleyleverettanalyticsolution.hh:323
void calculateAnalyticSolution()
Definition: buckleyleverettanalyticsolution.hh:290
BlockVector AnalyticSolution() const
Definition: buckleyleverettanalyticsolution.hh:297
Defines the properties required for (immiscible) two-phase sequential models.
This material law takes a material law defined for effective saturations and converts it to a materia...