19#ifndef DUMUX_MCWHORTER_ANALYTIC_HH
20#define DUMUX_MCWHORTER_ANALYTIC_HH
42template<
typename TypeTag>
49 using SpatialParams =
typename GET_PROP_TYPE(TypeTag, SpatialParams);
50 using MaterialLaw =
typename SpatialParams::MaterialLaw;
51 using MaterialLawParams =
typename MaterialLaw::Params;
53 using FluidSystem =
typename GET_PROP_TYPE(TypeTag, FluidSystem);
54 using FluidState =
typename GET_PROP_TYPE(TypeTag, FluidState);
56 using SolutionTypes =
typename GET_PROP(TypeTag, SolutionTypes);
57 using PrimaryVariables =
typename SolutionTypes::PrimaryVariables;
59 using Indices =
typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
63 dimworld = GridView::dimensionworld
67 wPhaseIdx = Indices::wPhaseIdx,
68 nPhaseIdx = Indices::nPhaseIdx,
69 saturationIdx = Indices::saturationIdx
72 using BlockVector = Dune::BlockVector<Dune::FieldVector<Scalar, 1> >;
73 using Element =
typename GridView::template Codim<0>::Entity;
74 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
80 void initializeAnalytic()
82 int size = problem_.gridView().size(0);
83 analyticSolution_.resize(size);
85 errorGlobal_.resize(size);
87 errorLocal_.resize(size);
95 Scalar globalVolume = 0;
96 Scalar errorNorm = 0.0;
98 for (
const auto& element : elements(problem_.gridView()))
101 int index = problem_.variables().index(element);
103 Scalar sat = problem_.variables().cellData(index).saturation(wPhaseIdx);
105 Scalar volume = element.geometry().volume();
107 Scalar error = analyticSolution_[index] - sat;
109 errorLocal_[index] = error;
111 if (sat > swr_ + 1e-6)
113 globalVolume += volume;
114 errorNorm += (volume*volume*error*error);
118 if (globalVolume > 0.0 && errorNorm > 0.0)
121 errorNorm = sqrt(errorNorm)/globalVolume;
122 errorGlobal_ = errorNorm;
132 void prepareAnalytic()
134 const auto& dummyElement = *problem_.gridView().template begin<0>();
135 const MaterialLawParams& materialLawParams(problem_.spatialParams().materialLawParams(dummyElement));
137 swr_ = materialLawParams.swr();
138 snr_ = materialLawParams.snr();
139 porosity_ = problem_.spatialParams().porosity(dummyElement);
140 permeability_ = problem_.spatialParams().intrinsicPermeability(dummyElement)[0][0];
141 PrimaryVariables initVec;
142 problem_.initial(initVec, dummyElement);
143 sInit_ = initVec[saturationIdx];
144 Scalar s0 =(1 - snr_ - swr_);
149 h_= (s0)/intervalNum_;
154 for (
int i=1; i<pointNum_; i++)
156 satVec_[i]=satVec_[i-1]+h_;
158 FluidState fluidState;
159 fluidState.setTemperature(problem_.temperature(dummyElement));
160 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(dummyElement));
161 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(dummyElement));
166 for (
int i=0; i<pointNum_; i++)
168 fractionalW_[i] = MaterialLaw::krw(materialLawParams, satVec_[i])/viscosityW;
169 fractionalW_[i] /= (fractionalW_[i] + MaterialLaw::krn(materialLawParams, satVec_[i])/viscosityNW);
175 for (
int i=0; i<pointNum_; i++)
177 dpcdsw_[i] = MaterialLaw::dpc_dsw(materialLawParams, satVec_[i]);
185 fInit_=fractionalW_[0];
193 for (
int i=0; i<pointNum_; i++)
195 fn_[i]= r_ * (fractionalW_[i] - fInit_)/ (1 - r_ * fInit_);
202 for (
int i=0; i<pointNum_; i++)
203 {d_[i] = fractionalW_[i]*(-dpcdsw_[i])*(MaterialLaw::krn(materialLawParams, satVec_[i])/viscosityNW)*permeability_;
213 for (
int i=0; i<pointNum_; i++)
215 gk_[i] = d_[i]/(1-fn_[i]);
227 Scalar time = problem_.timeManager().time() + problem_.timeManager().timeStepSize();
248 while (diff> tolAnalytic_)
254 std::cout<<
"Analytic solution: Too many iterations!"<<std::endl;
260 for (
int i=0; i<intervalNum_; i++)
262 a_[i] = 0.5 * h_ * sInit_ *(gk_[i] + gk_[i+1])+ pow(h_, 2) / 6* ((3* i + 1) * gk_[i]
263 + (3 * i + 2) * gk_[i+1]);
264 b_[i] = 0.5 * h_ * (gk_[i] + gk_[i+1]);
265 I0 += (a_[i] - sInit_ * b_[i]);
270 for (
int i=1; i<pointNum_; i++)
273 for (
int j = i; j<intervalNum_; j++)
274 Ii += (a_[j] - satVec_[i] * b_[j]);
276 gk_[i] = (d_[i] + gk_[i]*fn_[i])/(1 - Ii/I0);
280 Ak = pow((0.5*porosity_/pow((1 - fInit_), 2)*I0), 0.5);
290 for (
int i = 0; i<pointNum_; i++)
292 for (
int j = i; j<intervalNum_; j++)
299 for (
int i = 0; i<pointNum_; i++)
301 xf_[i]= 2 * Ak * (1 - fInit_ * r_)/ porosity_ * fp_[i]* pow(time, 0.5);
307 for (
const auto& element : elements(problem_.gridView()))
310 const GlobalPosition& globalPos = element.geometry().center();
315 int index = problem_.variables().index(element);
319 for (
int i=intervalNum_; i>0; i--)
321 if (globalPos[0] <= xf_[i])
329 if (globalPos[0]> xf_[0])
331 analyticSolution_[index] = sInit_;
335 if (globalPos[0] <= xf_[0])
337 analyticSolution_[index] = satVec_[xnext];
352 initializeAnalytic();
359 return analyticSolution_;
363 template<
class MultiWriter>
366 int size = problem_.gridView().size(0);
367 BlockVector *analyticSolution = writer.allocateManagedBuffer (size);
368 BlockVector *errorGlobal = writer.allocateManagedBuffer (size);
369 BlockVector *errorLocal = writer.allocateManagedBuffer (size);
371 *analyticSolution = analyticSolution_;
372 *errorGlobal = errorGlobal_;
373 *errorLocal = errorLocal_;
375 writer.attachCellData(*analyticSolution,
"saturation (exact solution)");
376 writer.attachCellData(*errorGlobal,
"global error");
377 writer.attachCellData(*errorLocal,
"local error");
385 initializeAnalytic();
390 problem_(problem), analyticSolution_(0), errorGlobal_(0), errorLocal_(0), tolAnalytic_(tolAnalytic)
396 BlockVector analyticSolution_;
397 BlockVector errorGlobal_;
398 BlockVector errorLocal_;
407 Scalar permeability_;
409 { intervalNum_ = 1000, pointNum_ = intervalNum_+1};
410 Dune::FieldVector<Scalar, pointNum_> satVec_;
411 Dune::FieldVector<Scalar,pointNum_> fractionalW_;
412 Dune::FieldVector<Scalar, pointNum_> dpcdsw_;
413 Dune::FieldVector<Scalar, pointNum_> fn_;
414 Dune::FieldVector<Scalar, pointNum_> d_;
415 Dune::FieldVector<Scalar, pointNum_> gk_;
416 Dune::FieldVector<Scalar, pointNum_> xf_;
419 Dune::FieldVector<Scalar,intervalNum_> a_;
420 Dune::FieldVector<Scalar,intervalNum_> b_;
421 Dune::FieldVector<Scalar,pointNum_> fp_;
#define GET_PROP(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:281
#define GET_PROP_TYPE(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:283
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
Analytic solution of the McWhorter problem.
Definition: mcwhorteranalyticsolution.hh:44
BlockVector AnalyticSolution() const
Definition: mcwhorteranalyticsolution.hh:357
McWhorterAnalytic(Problem &problem, Scalar tolAnalytic=1e-14)
Definition: mcwhorteranalyticsolution.hh:389
void addOutputVtkFields(MultiWriter &writer)
Definition: mcwhorteranalyticsolution.hh:364
void calculateAnalyticSolution()
Definition: mcwhorteranalyticsolution.hh:350
void initialize()
Definition: mcwhorteranalyticsolution.hh:383
Defines the properties required for (immiscible) two-phase sequential models.