diff --git a/test/decoupled/2p/buckleyleverettanalyticsolution.hh b/test/decoupled/2p/buckleyleverettanalyticsolution.hh new file mode 100644 index 0000000000000000000000000000000000000000..8d8dfb7b0ee869f74c8e71e393030b9397ead5da --- /dev/null +++ b/test/decoupled/2p/buckleyleverettanalyticsolution.hh @@ -0,0 +1,353 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef DUMUX_BUCKLEYLEVERETT_ANALYTICAL_HH +#define DUMUX_BUCKLEYLEVERETT_ANALYTICAL_HH + +#include <dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh> + +/** + * @file + * @brief Analytical solution of the buckley-leverett problem + * @author Markus Wolff + */ + +namespace Dumux +{ +/** + * \ingroup fracflow + * @brief IMplicit Pressure Explicit Saturation (IMPES) scheme for the solution of + * the Buckley-Leverett problem + */ + +template<typename Scalar, typename Law> +struct CheckMaterialLaw +{ + static bool isLinear() + { + return false; + } +}; + +template<typename Scalar> +struct CheckMaterialLaw<Scalar, LinearMaterial<Scalar> > +{ + static bool isLinear() + { + return true; + } +}; + +template<typename Scalar> +struct CheckMaterialLaw<Scalar, EffToAbsLaw< LinearMaterial<Scalar> > > +{ + static bool isLinear() + { + return true; + } +}; + +template<class TypeTag> class BuckleyLeverettAnalytic +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; + typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams; + typedef typename SpatialParams::MaterialLaw MaterialLaw; + typedef typename MaterialLaw::Params MaterialLawParams; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData; + + enum + { + dim = GridView::dimension, dimworld = GridView::dimensionworld + }; + enum + { + wPhaseIdx = Indices::wPhaseIdx, + nPhaseIdx = Indices::nPhaseIdx, + satEqIdx = Indices::satEqIdx, + }; + + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > BlockVector; + typedef typename GridView::Traits::template Codim<0>::Entity Element; + typedef typename GridView::Traits::template Codim<0>::EntityPointer ElementPointer; + typedef typename GridView::template Codim<0>::Iterator ElementIterator; + typedef Dune::FieldVector<Scalar, dimworld> GlobalPosition; + +private: + + // functions needed for analytical solution + + void initializeAnalytic() + { + int size = problem_.gridView().size(0); + analyticSolution_.resize(size); + analyticSolution_ = 0; + errorGlobal_.resize(size); + errorGlobal_ = 0; + errorLocal_.resize(size); + errorLocal_ = 0; + + return; + } + /*! + * \brief DOC ME! + * \param materialLawParams DOC ME! + */ + void prepareAnalytic() + { + ElementIterator dummyElement = problem_.gridView().template begin<0>(); + const MaterialLawParams& materialLawParams(problem_.spatialParams().materialLawParams(*dummyElement)); + + swr_ = materialLawParams.Swr(); + snr_ = materialLawParams.Snr(); + Scalar porosity = problem_.spatialParams().porosity(*dummyElement); + + FluidState fluidState; + fluidState.setTemperature(problem_.temperature(*dummyElement)); + fluidState.setPressure(wPhaseIdx, problem_.referencePressure(*dummyElement)); + fluidState.setPressure(nPhaseIdx, problem_.referencePressure(*dummyElement)); + Scalar viscosityW = FluidSystem::viscosity(fluidState, wPhaseIdx); + Scalar viscosityNW = FluidSystem::viscosity(fluidState, nPhaseIdx); + + + if (CheckMaterialLaw<Scalar, MaterialLaw>::isLinear() && viscosityW == viscosityNW) + { + std::pair<Scalar, Scalar> entry; + entry.first = 1 - snr_; + + entry.second = vTot_ / porosity; + + frontParams_.push_back(entry); + } + else + { + Scalar sw0 = swr_; + Scalar fw0 = MaterialLaw::krw(materialLawParams, sw0)/viscosityW; + fw0 /= (fw0 + MaterialLaw::krn(materialLawParams, sw0)/viscosityNW); + Scalar sw1 = sw0 + deltaS_; + Scalar fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW; + fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW); + Scalar tangentSlopeOld = (fw1 - fw0)/(sw1 - sw0); + sw1 += deltaS_; + fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW; + fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW); + Scalar tangentSlopeNew = (fw1 - fw0)/(sw1 - sw0); + + while (tangentSlopeNew >= tangentSlopeOld && sw1 < (1.0 - snr_)) + { + tangentSlopeOld = tangentSlopeNew; + sw1 += deltaS_; + fw1 = MaterialLaw::krw(materialLawParams, sw1)/viscosityW; + fw1 /= (fw1 + MaterialLaw::krn(materialLawParams, sw1)/viscosityNW); + tangentSlopeNew = (fw1 - fw0)/(sw1 - sw0); + } + + sw0 = sw1 - deltaS_; + fw0 = MaterialLaw::krw(materialLawParams, sw0)/viscosityW; + fw0 /= (fw0 + MaterialLaw::krn(materialLawParams, sw0)/viscosityNW); + Scalar sw2 = sw1 + deltaS_; + Scalar fw2 = MaterialLaw::krw(materialLawParams, sw2)/viscosityW; + fw2 /= (fw2 + MaterialLaw::krn(materialLawParams, sw2)/viscosityNW); + while (sw1 <= (1.0 - snr_)) + { + std::pair<Scalar, Scalar> entry; + entry.first = sw1; + + Scalar dfwdsw = (fw2 - fw0)/(sw2 - sw0); + + entry.second = vTot_ / porosity * dfwdsw; + + frontParams_.push_back(entry); + + sw0 = sw1; + sw1 = sw2; + fw0 = fw1; + fw1 = fw2; + + sw2 += deltaS_; + fw2 = MaterialLaw::krw(materialLawParams, sw2)/viscosityW; + fw2 /= (fw2 + MaterialLaw::krn(materialLawParams, sw2)/viscosityNW); + } + } + + return; + } + + void calcSatError() + { + Scalar globalVolume = 0; + Scalar errorNorm = 0.0; + + ElementIterator eItEnd = problem_.gridView().template end<0> (); + for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) + { + // get entity + ElementPointer element = *eIt; + int index = problem_.variables().index(*element); + + Scalar sat = problem_.variables().cellData(index).saturation(wPhaseIdx); + + Scalar volume = element->geometry().volume(); + + Scalar error = analyticSolution_[index] - sat; + + errorLocal_[index] = error; + + if (sat > swr_ + 1e-6) + { + globalVolume += volume; + errorNorm += (volume*volume*error*error); + } + } + + if (globalVolume > 0.0 && errorNorm > 0.0) + { + errorNorm = std::sqrt(errorNorm)/globalVolume; + errorGlobal_ = errorNorm; + } + else + { + errorGlobal_ = 0; + } + + return; + } + + void updateExSol() + { + Scalar time = problem_.timeManager().time() + problem_.timeManager().timeStepSize(); + + // position of the fluid front + + Scalar xMax = frontParams_[0].second * time; + + // iterate over vertices and get analytic saturation solution + ElementIterator eItEnd = problem_.gridView().template end<0> (); + for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) + { + // get global coordinate of cell center + GlobalPosition globalPos = eIt->geometry().center(); + + int index = problem_.variables().index(*eIt); + + if (globalPos[0] > xMax) + analyticSolution_[index] = swr_; + else + { + int size = frontParams_.size(); + if (size == 1) + { + analyticSolution_[index] = frontParams_[0].first; + } + else + { + // find x_f next to global coordinate of the vertex + int xnext = 0; + for (int i = 0; i < size-1; i++) + { + Scalar x = frontParams_[i].second * time; + Scalar xMinus = frontParams_[i+1].second * time; + if (globalPos[0] <= x && globalPos[0] > xMinus) + { + analyticSolution_[index] = frontParams_[i].first - (frontParams_[i].first - frontParams_[i+1].first)/(x - xMinus) * (x - globalPos[0]); + break; + } + } + + } + } + } + + // call function to calculate the saturation error + calcSatError(); + + return; + } + +public: + void calculateAnalyticSolution() + { + initializeAnalytic(); + + updateExSol(); + } + + BlockVector AnalyticSolution() const + { + return analyticSolution_; + } + + //Write saturation and pressure into file + template<class MultiWriter> + void addOutputVtkFields(MultiWriter &writer) + { + int size = problem_.gridView().size(0); + BlockVector *analyticSolution = writer.allocateManagedBuffer (size); + BlockVector *errorGlobal = writer.allocateManagedBuffer (size); + BlockVector *errorLocal = writer.allocateManagedBuffer (size); + + *analyticSolution = analyticSolution_; + *errorGlobal = errorGlobal_; + *errorLocal = errorLocal_; + + writer.attachCellData(*analyticSolution, "saturation (exact solution)"); + writer.attachCellData(*errorGlobal, "global error"); + writer.attachCellData(*errorLocal, "local error"); + + return; + } + + //! Construct an IMPES object. + BuckleyLeverettAnalytic(Problem& problem) : + problem_(problem), analyticSolution_(0), errorGlobal_(0), errorLocal_(0), frontParams_(0), deltaS_(1e-3) + {} + + void initialize(Scalar vTot) + { + vTot_ = vTot; + initializeAnalytic(); + prepareAnalytic(); + } + + +private: + Problem& problem_; + + BlockVector analyticSolution_; + BlockVector errorGlobal_; + BlockVector errorLocal_; + + std::vector<std::pair<Scalar, Scalar> > frontParams_; + const Scalar deltaS_; + + Scalar swr_; + Scalar snr_; + Scalar vTot_; + + + + int tangentIdx_; +}; +} +#endif diff --git a/test/decoupled/2p/grids/test_mpfa2p.dgf b/test/decoupled/2p/grids/test_mpfa2p.dgf new file mode 100644 index 0000000000000000000000000000000000000000..3ec5a022cdd2bc1193484c6922ec6320d0459f93 --- /dev/null +++ b/test/decoupled/2p/grids/test_mpfa2p.dgf @@ -0,0 +1,461 @@ +DGF +Vertex +0 0 +0 3 +11.25 0 +17.25 3 +12.75 0 +18.75 3 +30 0 +30 3 +0 0.3 +0 0.6 +0 0.9 +0 1.2 +0 1.5 +0 1.8 +0 2.1 +0 2.4 +0 2.7 +1.725 3 +3.45 3 +5.175 3 +6.9 3 +8.625 3 +10.35 3 +12.075 3 +13.8 3 +15.525 3 +16.65 2.7 +16.05 2.4 +15.45 2.1 +14.85 1.8 +14.25 1.5 +13.65 1.2 +13.05 0.9 +12.45 0.6 +11.85 0.3 +10.125 0 +9 0 +7.875 0 +6.75 0 +5.625 0 +4.5 0 +3.375 0 +2.25 0 +1.125 0 +18.15 2.7 +17.55 2.4 +16.95 2.1 +16.35 1.8 +15.75 1.5 +15.15 1.2 +14.55 0.9 +13.95 0.6 +13.35 0.3 +19.875 3 +21 3 +22.125 3 +23.25 3 +24.375 3 +25.5 3 +26.625 3 +27.75 3 +28.875 3 +30 2.7 +30 2.4 +30 2.1 +30 1.8 +30 1.5 +30 1.2 +30 0.9 +30 0.6 +30 0.3 +28.275 0 +26.55 0 +24.825 0 +23.1 0 +21.375 0 +19.65 0 +17.925 0 +16.2 0 +14.475 0 +14.985 2.7 +13.32 2.7 +11.655 2.7 +9.99 2.7 +8.325 2.7 +6.66 2.7 +4.995 2.7 +3.33 2.7 +1.665 2.7 +14.445 2.4 +12.84 2.4 +11.235 2.4 +9.63 2.4 +8.025 2.4 +6.42 2.4 +4.815 2.4 +3.21 2.4 +1.605 2.4 +13.905 2.1 +12.36 2.1 +10.815 2.1 +9.27 2.1 +7.725 2.1 +6.18 2.1 +4.635 2.1 +3.09 2.1 +1.545 2.1 +13.365 1.8 +11.88 1.8 +10.395 1.8 +8.91 1.8 +7.425 1.8 +5.94 1.8 +4.455 1.8 +2.97 1.8 +1.485 1.8 +12.825 1.5 +11.4 1.5 +9.975 1.5 +8.55 1.5 +7.125 1.5 +5.7 1.5 +4.275 1.5 +2.85 1.5 +1.425 1.5 +12.285 1.2 +10.92 1.2 +9.555 1.2 +8.19 1.2 +6.825 1.2 +5.46 1.2 +4.095 1.2 +2.73 1.2 +1.365 1.2 +11.745 0.9 +10.44 0.9 +9.135 0.9 +7.83 0.9 +6.525 0.9 +5.22 0.9 +3.915 0.9 +2.61 0.9 +1.305 0.9 +11.205 0.6 +9.96 0.6 +8.715 0.6 +7.47 0.6 +6.225 0.6 +4.98 0.6 +3.735 0.6 +2.49 0.6 +1.245 0.6 +10.665 0.3 +9.48 0.3 +8.295 0.3 +7.11 0.3 +5.925 0.3 +4.74 0.3 +3.555 0.3 +2.37 0.3 +1.185 0.3 +28.815 2.7 +27.63 2.7 +26.445 2.7 +25.26 2.7 +24.075 2.7 +22.89 2.7 +21.705 2.7 +20.52 2.7 +19.335 2.7 +28.755 2.4 +27.51 2.4 +26.265 2.4 +25.02 2.4 +23.775 2.4 +22.53 2.4 +21.285 2.4 +20.04 2.4 +18.795 2.4 +28.695 2.1 +27.39 2.1 +26.085 2.1 +24.78 2.1 +23.475 2.1 +22.17 2.1 +20.865 2.1 +19.56 2.1 +18.255 2.1 +28.635 1.8 +27.27 1.8 +25.905 1.8 +24.54 1.8 +23.175 1.8 +21.81 1.8 +20.445 1.8 +19.08 1.8 +17.715 1.8 +28.575 1.5 +27.15 1.5 +25.725 1.5 +24.3 1.5 +22.875 1.5 +21.45 1.5 +20.025 1.5 +18.6 1.5 +17.175 1.5 +28.515 1.2 +27.03 1.2 +25.545 1.2 +24.06 1.2 +22.575 1.2 +21.09 1.2 +19.605 1.2 +18.12 1.2 +16.635 1.2 +28.455 0.9 +26.91 0.9 +25.365 0.9 +23.82 0.9 +22.275 0.9 +20.73 0.9 +19.185 0.9 +17.64 0.9 +16.095 0.9 +28.395 0.6 +26.79 0.6 +25.185 0.6 +23.58 0.6 +21.975 0.6 +20.37 0.6 +18.765 0.6 +17.16 0.6 +15.555 0.6 +28.335 0.3 +26.67 0.3 +25.005 0.3 +23.34 0.3 +21.675 0.3 +20.01 0.3 +18.345 0.3 +16.68 0.3 +15.015 0.3 +# +Cube +map 1 3 2 0 +25 3 26 80 +24 25 80 81 +23 24 81 82 +22 23 82 83 +21 22 83 84 +20 21 84 85 +19 20 85 86 +18 19 86 87 +17 18 87 88 +1 17 88 16 +80 26 27 89 +81 80 89 90 +82 81 90 91 +83 82 91 92 +84 83 92 93 +85 84 93 94 +86 85 94 95 +87 86 95 96 +88 87 96 97 +16 88 97 15 +89 27 28 98 +90 89 98 99 +91 90 99 100 +92 91 100 101 +93 92 101 102 +94 93 102 103 +95 94 103 104 +96 95 104 105 +97 96 105 106 +15 97 106 14 +98 28 29 107 +99 98 107 108 +100 99 108 109 +101 100 109 110 +102 101 110 111 +103 102 111 112 +104 103 112 113 +105 104 113 114 +106 105 114 115 +14 106 115 13 +107 29 30 116 +108 107 116 117 +109 108 117 118 +110 109 118 119 +111 110 119 120 +112 111 120 121 +113 112 121 122 +114 113 122 123 +115 114 123 124 +13 115 124 12 +116 30 31 125 +117 116 125 126 +118 117 126 127 +119 118 127 128 +120 119 128 129 +121 120 129 130 +122 121 130 131 +123 122 131 132 +124 123 132 133 +12 124 133 11 +125 31 32 134 +126 125 134 135 +127 126 135 136 +128 127 136 137 +129 128 137 138 +130 129 138 139 +131 130 139 140 +132 131 140 141 +133 132 141 142 +11 133 142 10 +134 32 33 143 +135 134 143 144 +136 135 144 145 +137 136 145 146 +138 137 146 147 +139 138 147 148 +140 139 148 149 +141 140 149 150 +142 141 150 151 +10 142 151 9 +143 33 34 152 +144 143 152 153 +145 144 153 154 +146 145 154 155 +147 146 155 156 +148 147 156 157 +149 148 157 158 +150 149 158 159 +151 150 159 160 +9 151 160 8 +152 34 2 35 +153 152 35 36 +154 153 36 37 +155 154 37 38 +156 155 38 39 +157 156 39 40 +158 157 40 41 +159 158 41 42 +160 159 42 43 +8 160 43 0 +3 5 44 26 +26 44 45 27 +27 45 46 28 +28 46 47 29 +29 47 48 30 +30 48 49 31 +31 49 50 32 +32 50 51 33 +33 51 52 34 +34 52 4 2 +61 7 62 161 +60 61 161 162 +59 60 162 163 +58 59 163 164 +57 58 164 165 +56 57 165 166 +55 56 166 167 +54 55 167 168 +53 54 168 169 +5 53 169 44 +161 62 63 170 +162 161 170 171 +163 162 171 172 +164 163 172 173 +165 164 173 174 +166 165 174 175 +167 166 175 176 +168 167 176 177 +169 168 177 178 +44 169 178 45 +170 63 64 179 +171 170 179 180 +172 171 180 181 +173 172 181 182 +174 173 182 183 +175 174 183 184 +176 175 184 185 +177 176 185 186 +178 177 186 187 +45 178 187 46 +179 64 65 188 +180 179 188 189 +181 180 189 190 +182 181 190 191 +183 182 191 192 +184 183 192 193 +185 184 193 194 +186 185 194 195 +187 186 195 196 +46 187 196 47 +188 65 66 197 +189 188 197 198 +190 189 198 199 +191 190 199 200 +192 191 200 201 +193 192 201 202 +194 193 202 203 +195 194 203 204 +196 195 204 205 +47 196 205 48 +197 66 67 206 +198 197 206 207 +199 198 207 208 +200 199 208 209 +201 200 209 210 +202 201 210 211 +203 202 211 212 +204 203 212 213 +205 204 213 214 +48 205 214 49 +206 67 68 215 +207 206 215 216 +208 207 216 217 +209 208 217 218 +210 209 218 219 +211 210 219 220 +212 211 220 221 +213 212 221 222 +214 213 222 223 +49 214 223 50 +215 68 69 224 +216 215 224 225 +217 216 225 226 +218 217 226 227 +219 218 227 228 +220 219 228 229 +221 220 229 230 +222 221 230 231 +223 222 231 232 +50 223 232 51 +224 69 70 233 +225 224 233 234 +226 225 234 235 +227 226 235 236 +228 227 236 237 +229 228 237 238 +230 229 238 239 +231 230 239 240 +232 231 240 241 +51 232 241 52 +233 70 6 71 +234 233 71 72 +235 234 72 73 +236 235 73 74 +237 236 74 75 +238 237 75 76 +239 238 76 77 +240 239 77 78 +241 240 78 79 +52 241 79 4 +# +Boundarydomain +default 1 +# diff --git a/test/decoupled/2p/mcwhorteranalyticsolution.hh b/test/decoupled/2p/mcwhorteranalyticsolution.hh new file mode 100644 index 0000000000000000000000000000000000000000..91278161fcf3e9163cac4f1b3dc30a649086099a --- /dev/null +++ b/test/decoupled/2p/mcwhorteranalyticsolution.hh @@ -0,0 +1,427 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef DUMUX_MCWHORTER_ANALYTIC_HH +#define DUMUX_MCWHORTER_ANALYTIC_HH + +/** + * @file + * @brief Analytic solution of + * the McWhorter problem + * @author Markus Wolff, Anneli Schöniger + */ + +namespace Dumux +{ +/** + * @brief Analytic solution of + * the McWhorter problem + * + * for naming of variables see "An Improved Semi-Analytical Solution for Verification + * of Numerical Models of Two-Phase Flow in Porous Media" + * (R. Fucik, J. Mikyska, M. Benes, T. H. Illangasekare; 2007) + */ + +template<typename TypeTag> +class McWhorterAnalytic +{ + typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; +// typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + + typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams; + typedef typename SpatialParams::MaterialLaw MaterialLaw; + typedef typename MaterialLaw::Params MaterialLawParams; + + typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; + typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState; + + typedef typename GET_PROP(TypeTag, SolutionTypes)::PrimaryVariables PrimaryVariables; + + typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices; + + enum + { + dimworld = GridView::dimensionworld //dim = GridView::dimension, + }; + enum + { + wPhaseIdx = Indices::wPhaseIdx, + nPhaseIdx = Indices::nPhaseIdx, +// pressureIdx = Indices::pressureIdx, + saturationIdx = Indices::saturationIdx//, +// pressEqIdx = Indices::pressEqIdx, +// satEqIdx = Indices::satEqIdx + }; + + typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > BlockVector; + typedef typename GridView::Traits::template Codim<0>::Entity Element; + typedef typename GridView::Traits::template Codim<0>::EntityPointer ElementPointer; + typedef typename GridView::template Codim<0>::Iterator ElementIterator; + typedef Dune::FieldVector<Scalar, dimworld> GlobalPosition; + +private: + + // functions needed for analytical solution + + void initializeAnalytic() + { + int size = problem_.gridView().size(0); + analyticSolution_.resize(size); + analyticSolution_=0; + errorGlobal_.resize(size); + errorGlobal_ = 0; + errorLocal_.resize(size); + errorLocal_ = 0; + + return; + } + + void calcSatError() + { + Scalar globalVolume = 0; + Scalar errorNorm = 0.0; + + ElementIterator eItEnd = problem_.gridView().template end<0> (); + for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt != eItEnd; ++eIt) + { + // get entity + ElementPointer element = *eIt; + int index = problem_.variables().index(*element); + + Scalar sat = problem_.variables().cellData(index).saturation(wPhaseIdx); + + Scalar volume = element->geometry().volume(); + + Scalar error = analyticSolution_[index] - sat; + + errorLocal_[index] = error; + + if (sat > swr_ + 1e-6) + { + globalVolume += volume; + errorNorm += (volume*volume*error*error); + } + } + + if (globalVolume > 0.0 && errorNorm > 0.0) + { + errorNorm = std::sqrt(errorNorm)/globalVolume; + errorGlobal_ = errorNorm; + } + else + { + errorGlobal_ = 0; + } + + return; + } + + void prepareAnalytic() + { + ElementIterator dummyElement = problem_.gridView().template begin<0>(); + const MaterialLawParams& materialLawParams(problem_.spatialParams().materialLawParams(*dummyElement)); + + swr_ = materialLawParams.Swr(); + snr_ = materialLawParams.Snr(); + porosity_ = problem_.spatialParams().porosity(*dummyElement); + permeability_ = problem_.spatialParams().intrinsicPermeability(*dummyElement)[0][0]; + PrimaryVariables initVec; + problem_.initial(initVec, *dummyElement); + sInit_ = initVec[saturationIdx]; + Scalar s0 =(1 - snr_ - swr_); +// std::cerr<<"\n Swr, Snr: "<< swr_ << snr_ << "\n"; +// std::cerr<<"\n sInit "<< sInit_<< "\n"; + + // h_= (s0 - sInit_)/intervalNum_; + h_= (s0)/intervalNum_; +// std::cout<<"h_= "<<h_<<std::endl; + + // define saturation range for analytic solution + satVec_= swr_; + for (int i=1; i<pointNum_; i++) + { + satVec_[i]=satVec_[i-1]+h_; + } + FluidState fluidState; + fluidState.setTemperature(problem_.temperature(*dummyElement)); + fluidState.setPressure(wPhaseIdx, problem_.referencePressure(*dummyElement)); + fluidState.setPressure(nPhaseIdx, problem_.referencePressure(*dummyElement)); + Scalar viscosityW = FluidSystem::viscosity(fluidState, wPhaseIdx); + Scalar viscosityNW = FluidSystem::viscosity(fluidState, nPhaseIdx); + + // get fractional flow function vector + for (int i=0; i<pointNum_; i++) + { + fractionalW_[i] = MaterialLaw::krw(materialLawParams, satVec_[i])/viscosityW; + fractionalW_[i] /= (fractionalW_[i] + MaterialLaw::krn(materialLawParams, satVec_[i])/viscosityNW); + } + + // get capillary pressure derivatives + dpcdsw_=0; + + for (int i=0; i<pointNum_; i++) + { + dpcdsw_[i] = MaterialLaw::dpC_dSw(materialLawParams, satVec_[i]); + } +// std::cout<<"dpcdsw = "<<dpcdsw_<<std::endl; + + // set initial fW + if (sInit_ == 0) + fInit_=0; + else + fInit_=fractionalW_[0]; + + fractionalW_[0]=0; + + // normalize fW + // with r_ = qt/q0 + // qt: total volume flux, q0: displacing phase flux at boundary + // --> r_ = 1 for unidirectional displacement; r_ = 0 for impermeable boundary + for (int i=0; i<pointNum_; i++) + { + fn_[i]= r_ * (fractionalW_[i] - fInit_)/ (1 - r_ * fInit_); + } + + // std::cout<<"r_ = "<<r_<<std::endl; + // std::cout<<"fn_ = "<<fn_<<std::endl; + + // diffusivity function + for (int i=0; i<pointNum_; i++) + {d_[i] = fractionalW_[i]*(-dpcdsw_[i])*(MaterialLaw::krn(materialLawParams, satVec_[i])/viscosityNW)*permeability_; + } + + // std::cout<<"fractionalW_ = "<<fractionalW_<<std::endl; + // std::cout<<"permeability_ = "<<permeability_<<std::endl; + // std::cout<<"d_ = "<<d_<<std::endl; + + + // gk_: part of fractional flow function + // initial guess for gk_ + for (int i=0; i<pointNum_; i++) + { + gk_[i] = d_[i]/(1-fn_[i]); + } + + gk_[0] = 0; + +// std::cout<<"gk_ = "<<gk_<<std::endl; + + return; + } + + void updateExSol() + { + Scalar time = problem_.timeManager().time() + problem_.timeManager().timeStepSize(); + + // with displacing phase flux at boundary q0 = A * 1/sqrt(t) + // Akm1, Ak: successive approximations of A + double Ak = 0; + double Akm1 = 0; + double diff = 1e100; + + // partial numerical integrals a_, b_ + a_=0, b_=0; + fp_=0; + + // approximation of integral I + double I0 = 0; + double Ii = 0; + + int k = 0; + + while (diff> tolAnalytic_) + { + k++; +// std::cout<<" k = "<<k<<std::endl; + if (k> 50000) + { + std::cout<<"Analytic solution: Too many iterations!"<<std::endl; + break; + } + + Akm1=Ak; + I0=0; + for (int i=0; i<intervalNum_; i++) + { + a_[i] = 0.5 * h_ * sInit_ *(gk_[i] + gk_[i+1])+ pow(h_, 2) / 6* ((3* i + 1) * gk_[i] + + (3 * i + 2) * gk_[i+1]); + b_[i] = 0.5 * h_ * (gk_[i] + gk_[i+1]); + I0 += (a_[i] - sInit_ * b_[i]); + } + // std::cout<<" I0 = "<<I0<<std::endl; + + gk_[0]=0; + for (int i=1; i<pointNum_; i++) + { + Ii=0; + for (int j = i; j<intervalNum_; j++) + Ii += (a_[j] - satVec_[i] * b_[j]); + //gk_[i] = d_[i] + gk_[i]*(fn_[i] + Ii/I0); // method A + gk_[i] = (d_[i] + gk_[i]*fn_[i])/(1 - Ii/I0); // method B + } + + // with f(sInit) = 0: relationship between A and sInit + Ak = pow((0.5*porosity_/pow((1 - fInit_), 2)*I0), 0.5); + diff=fabs(Ak - Akm1); + // std::cout<<"diff = "<<diff<<std::endl; + } + + // std::cout<<" b_ = "<<b_<<std::endl; + // std::cout<<" Ak = "<<Ak<<std::endl; + + + // fp_: first derivative of f + for (int i = 0; i<pointNum_; i++) + { + for (int j = i; j<intervalNum_; j++) + fp_[i] += b_[j]/I0; + } + + // std::cout<<" fp_ = "<<fp_<<std::endl; + // std::cout<<fInit_<<std::endl; + + for (int i = 0; i<pointNum_; i++) + { + xf_[i]= 2 * Ak * (1 - fInit_ * r_)/ porosity_ * fp_[i]* pow(time, 0.5); + } + +// std::cout<<" xf_ = "<<xf_<<std::endl; + + // iterate over vertices and get analytical saturation solution + ElementIterator eItEnd = problem_.gridView().template end<0> (); + for (ElementIterator eIt = problem_.gridView().template begin<0> (); eIt!= eItEnd; ++eIt) + { + // get global coordinate of cell center + const GlobalPosition& globalPos = eIt->geometry().center(); + +// std::cout<<"globalPos = "<<globalPos[0]<<", x0 = "<<xf_[0]<<"\n"; + + // find index of current vertex + int index = problem_.variables().index(*eIt); + + // find x_f next to global coordinate of the vertex + int xnext = 0; + for (int i=intervalNum_; i>0; i--) + { + if (globalPos[0] <= xf_[i]) + { + xnext = i; + break; + } + } + + // account for the area not yet reached by the front + if (globalPos[0]> xf_[0]) + { + analyticSolution_[index] = sInit_; + continue; + } + + if (globalPos[0] <= xf_[0]) + { + analyticSolution_[index] = satVec_[xnext]; + continue; + } + +// std::cout<<"Analytical = "<<satVec_[xnext]<<std::endl; + } + + // call function to calculate the saturation error + calcSatError(); + return; + } + +public: + void calculateAnalyticSolution() + { + initializeAnalytic(); + + updateExSol(); + } + + BlockVector AnalyticSolution() const + { + return analyticSolution_; + } + + //Write saturation and pressure into file + template<class MultiWriter> + void addOutputVtkFields(MultiWriter &writer) + { + int size = problem_.gridView().size(0); + BlockVector *analyticSolution = writer.allocateManagedBuffer (size); + BlockVector *errorGlobal = writer.allocateManagedBuffer (size); + BlockVector *errorLocal = writer.allocateManagedBuffer (size); + + *analyticSolution = analyticSolution_; + *errorGlobal = errorGlobal_; + *errorLocal = errorLocal_; + + writer.attachCellData(*analyticSolution, "saturation (exact solution)"); + writer.attachCellData(*errorGlobal, "global error"); + writer.attachCellData(*errorLocal, "local error"); + + return; + } + + + void initialize() + { + initializeAnalytic(); + prepareAnalytic(); + } + + McWhorterAnalytic(Problem& problem, Scalar tolAnalytic = 1e-14) : + problem_(problem), analyticSolution_(0), errorGlobal_(0), errorLocal_(0), tolAnalytic_(tolAnalytic) + {} + +private: + Problem& problem_; + + BlockVector analyticSolution_; + BlockVector errorGlobal_; + BlockVector errorLocal_; + + Scalar tolAnalytic_; + Scalar r_; + + Scalar swr_; + Scalar snr_; + Scalar porosity_; + Scalar sInit_; + Scalar permeability_; + enum + { intervalNum_ = 1000, pointNum_ = intervalNum_+1}; + Dune::FieldVector<Scalar, pointNum_> satVec_; + Dune::FieldVector<Scalar,pointNum_> fractionalW_; + Dune::FieldVector<Scalar, pointNum_> dpcdsw_; + Dune::FieldVector<Scalar, pointNum_> fn_; + Dune::FieldVector<Scalar, pointNum_> d_; + Dune::FieldVector<Scalar, pointNum_> gk_; + Dune::FieldVector<Scalar, pointNum_> xf_; + Scalar fInit_; + Scalar h_; + Dune::FieldVector<Scalar,intervalNum_> a_; + Dune::FieldVector<Scalar,intervalNum_> b_; + Dune::FieldVector<Scalar,pointNum_> fp_; + +}; +} +#endif diff --git a/test/decoupled/2p/test_mpfa2p.cc b/test/decoupled/2p/test_mpfa2p.cc index 3dbf94340a48fb95aa9464b87caffffe2c003712..d18ca5f77e49f779aacd6b0bd2fb2580af4210b8 100644 --- a/test/decoupled/2p/test_mpfa2p.cc +++ b/test/decoupled/2p/test_mpfa2p.cc @@ -19,7 +19,7 @@ * * \brief Test for the sequential 2p models */ -#define STRUCTUREDGRID 1 +#define PROBLEM 2 // 0 = Buckley-Leverett, 1 = McWhorter, 2 = 2D Lense problem #include "config.h" diff --git a/test/decoupled/2p/test_mpfa2p.input b/test/decoupled/2p/test_mpfa2p.input index 1cfca93af00637adc000feee1a93f776d21a853c..72e6fc708308ab1dcbd9690fb832a3a3b9966ec8 100644 --- a/test/decoupled/2p/test_mpfa2p.input +++ b/test/decoupled/2p/test_mpfa2p.input @@ -9,10 +9,13 @@ ############################################################ [TimeManager] TEnd = 5e4# [s] -DtInitial = 0# [s] +DtInitial = 5e5# [s] +SubTimestepVerbosity = 0 [Grid] -#For nine-spot problem +#File = grids/test_mpfa2p.dgf#grid for buckley-leverett or mcwhorter problem + +#For 2d-lense-problem NumberOfCellsX = 10# [-] level 0 resolution in x-direction NumberOfCellsY = 10# [-] level 0 resolution in y-direction @@ -23,18 +26,21 @@ UpperRightY = 10# [m] dimension of the grid # 2D # Optional arguments ############################################################ [Problem] -EnableGravity = true OutputInterval =0 OutputTimeInterval = 1e4 +#For 2d-lense-problem InletWidth = 2 InjectionFlux = 0.1 -#OutputfileName = +[Impet] +#CFLFactor = 10.0 # Use larger time steps and +#SubCFLFactor = 0.95 # enable local time-stepping [Vtk] -#OutputLevel = 1 # 0 -> only primary variables (default), 1 -> also secondary variables +OutputLevel = 1 # 0 -> only primary variables (default), 1 -> also secondary variables +#For 2d-lense-problem [SpatialParams] BackgroundPermeabilityXX = 1e-10 BackgroundPermeabilityXY = 0 @@ -72,4 +78,4 @@ CoarsenTolerance = 0.01 # threshold for coarsening criterion EnableInitializationIndicator = true# RefineAtDirichletBC = false RefineAtFluxBC = true -RefineAtSource = false \ No newline at end of file +RefineAtSource = false diff --git a/test/decoupled/2p/test_mpfa2pproblem.hh b/test/decoupled/2p/test_mpfa2pproblem.hh index 8b69b31499a693cf2528072d0cd95f67f44800ed..19b645b28876ecf324da356c4d684a8e72727a9d 100644 --- a/test/decoupled/2p/test_mpfa2pproblem.hh +++ b/test/decoupled/2p/test_mpfa2pproblem.hh @@ -47,6 +47,8 @@ #include<dumux/decoupled/2p/impes/gridadaptionindicator2plocal.hh> #include "test_mpfa2pspatialparams.hh" +#include "buckleyleverettanalyticsolution.hh" +#include "mcwhorteranalyticsolution.hh" namespace Dumux { @@ -68,8 +70,10 @@ SET_PROP(MPFATwoPTestProblem, Grid) typedef Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming> type; }; -// set the GridCreator property +#if PROBLEM == 2 +//set the GridCreator property SET_TYPE_PROP(MPFATwoPTestProblem, GridCreator, CubeGridCreator<TypeTag>); +#endif // Set the problem property @@ -88,6 +92,7 @@ public: typedef Dumux::LiquidPhase<Scalar, Dumux::SimpleH2O<Scalar> > type; }; +#if PROBLEM == 2 // Set the non-wetting phase SET_PROP(MPFATwoPTestProblem, NonwettingPhase) { @@ -96,14 +101,34 @@ private: public: typedef Dumux::LiquidPhase<Scalar, Dumux::DNAPL<Scalar> > type; }; +#else +// Set the non-wetting phase +SET_PROP(MPFATwoPTestProblem, NonwettingPhase) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; +public: + typedef Dumux::LiquidPhase<Scalar, Dumux::SimpleH2O<Scalar> > type; +}; +#endif + +#if PROBLEM == 1 +SET_INT_PROP(MPFATwoPTestProblem, Formulation, DecoupledTwoPCommonIndices::pnSw); +#endif +#if PROBLEM == 2 // Enable gravity SET_BOOL_PROP(MPFATwoPTestProblem, ProblemEnableGravity, true); +#else +SET_BOOL_PROP(MPFATwoPTestProblem, ProblemEnableGravity, false); +#endif SET_TYPE_PROP(MPFATwoPTestProblem, EvalCflFluxFunction, Dumux::EvalCflFluxCoats<TypeTag>); SET_SCALAR_PROP(MPFATwoPTestProblem, ImpetCFLFactor, 1.0); SET_TYPE_PROP(MPFATwoPTestProblem, AdaptionIndicator, Dumux::GridAdaptionIndicator2PLocal<TypeTag>); +SET_TYPE_PROP(MPFATwoPTestProblem, LinearSolver, Dumux::SuperLUBackend<TypeTag>); + NEW_TYPE_TAG(FVTwoPTestProblem, INHERITS_FROM(FVPressureTwoP, FVTransportTwoP, IMPESTwoP, MPFATwoPTestProblem)); NEW_TYPE_TAG(FVAdaptiveTwoPTestProblem, INHERITS_FROM(FVPressureTwoPAdaptive, FVTransportTwoP, IMPESTwoPAdaptive, MPFATwoPTestProblem)); NEW_TYPE_TAG(MPFAOTwoPTestProblem, INHERITS_FROM(FVMPFAOPressureTwoP, FVTransportTwoP, IMPESTwoP, MPFATwoPTestProblem)); @@ -167,7 +192,11 @@ enum { wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx, +#if PROBLEM == 1 + pNIdx = Indices::pnIdx, +#else pWIdx = Indices::pwIdx, +#endif SwIdx = Indices::SwIdx, eqIdxPress = Indices::pressEqIdx, eqIdxSat = Indices::satEqIdx @@ -184,9 +213,20 @@ typedef Dune::FieldVector<Scalar, dim> LocalPosition; public: MPFATwoPTestProblem(TimeManager &timeManager,const GridView &gridView) : ParentType(timeManager, gridView) +#if PROBLEM != 2 +, analyticSolution_(*this) +#endif { this->setGrid(GridCreator::grid()); + int refinementFactor = 0; + if (ParameterTree::tree().hasKey("Grid.RefinementFactor")) + { + refinementFactor = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, RefinementFactor); + } + + this->grid().globalRefine(refinementFactor); + Scalar inletWidth = 1.0; if (ParameterTree::tree().hasKey("Problem.InletWidth")) { @@ -221,6 +261,29 @@ ParentType(timeManager, gridView) this->setOutputTimeInterval(outputTimeInterval); } +#if PROBLEM != 2 +void init() +{ + ParentType::init(); + +#if PROBLEM == 0 + Scalar vTot = 3e-6; + analyticSolution_.initialize(vTot); +#endif +#if PROBLEM == 1 + analyticSolution_.initialize(); +#endif +} + +void addOutputVtkFields() +{ + analyticSolution_.calculateAnalyticSolution(); + + ParentType::addOutputVtkFields(); + analyticSolution_.addOutputVtkFields(this->resultWriter()); +} +#endif + /*! * \name Problem parameters */ @@ -282,6 +345,7 @@ void source(PrimaryVariables &values,const Element& element) const */ void boundaryTypesAtPos(BoundaryTypes &bcTypes, const GlobalPosition& globalPos) const { +#if PROBLEM == 2 if (isInlet(globalPos)) { bcTypes.setNeumann(eqIdxPress); @@ -296,11 +360,37 @@ void boundaryTypesAtPos(BoundaryTypes &bcTypes, const GlobalPosition& globalPos) bcTypes.setDirichlet(eqIdxPress); bcTypes.setOutflow(eqIdxSat); } +#elif PROBLEM == 0 + if (globalPos[0] < eps_) + { + bcTypes.setAllDirichlet(); + } + else if (globalPos[0] > this->bboxMax()[0] - eps_) + { + bcTypes.setNeumann(eqIdxPress); + bcTypes.setOutflow(eqIdxSat); + } + else + { + bcTypes.setAllNeumann(); + } +#else + if (globalPos[0] < eps_) + { + bcTypes.setAllDirichlet(); + } + else + { + bcTypes.setAllNeumann(); + } +#endif } //! set dirichlet condition (pressure [Pa], saturation [-]) void dirichletAtPos(PrimaryVariables &values, const GlobalPosition& globalPos) const { + values = 0; +#if PROBLEM == 2 Scalar pRef = referencePressureAtPos(globalPos); Scalar temp = temperatureAtPos(globalPos); @@ -311,25 +401,52 @@ void dirichletAtPos(PrimaryVariables &values, const GlobalPosition& globalPos) c { values[SwIdx] = 0.0; } +#elif PROBLEM == 0 + if (globalPos[0] < eps_) + { + values[SwIdx] = 0.8; + values[pWIdx] = 1; + } +#else + if (globalPos[0] < eps_) + { + values[SwIdx] = 1.0; + values[pNIdx] = 1e5; + } +#endif } //! set neumann condition for phases (flux, [kg/(m^2 s)]) void neumannAtPos(PrimaryVariables &values, const GlobalPosition& globalPos) const { values = 0; +#if PROBLEM == 2 if (isInlet(globalPos)) { values[nPhaseIdx] = -inFlux_; } - +#elif PROBLEM == 0 + if (globalPos[0] > this->bboxMax()[0] - eps_) + { + values[nPhaseIdx] = 3e-3; + } +#endif } //! return initial solution -> only saturation values have to be given! void initialAtPos(PrimaryVariables &values, const GlobalPosition& globalPos) const { +#if PROBLEM == 2 values[pWIdx] = 0; values[SwIdx] = 1.0; +#elif PROBLEM == 0 + values[pWIdx] = 0; + values[SwIdx] = 0.2; +#else + values[pNIdx] = 0; + values[SwIdx] = 0.0; +#endif } private: @@ -383,6 +500,12 @@ Scalar inFlux_; GlobalPosition inletLeftCoord_; GlobalPosition inletRightCoord_; static constexpr Scalar eps_ = 1e-6; +#if PROBLEM == 0 +BuckleyLeverettAnalytic<TypeTag> analyticSolution_; +#endif +#if PROBLEM == 1 +McWhorterAnalytic<TypeTag> analyticSolution_; +#endif }; } //end namespace diff --git a/test/decoupled/2p/test_mpfa2pspatialparams.hh b/test/decoupled/2p/test_mpfa2pspatialparams.hh index 5cd2f69c6507d9f9b3fbd60d71f79f373f8c3c43..068ef74b453b8a6d59083932982197a2d92a814b 100644 --- a/test/decoupled/2p/test_mpfa2pspatialparams.hh +++ b/test/decoupled/2p/test_mpfa2pspatialparams.hh @@ -94,7 +94,13 @@ public: Scalar porosity(const Element& element) const { +#if PROBLEM == 0 + return 0.2; +#elif PROBLEM == 1 + return 0.3; +#else return 0.4; +#endif } // return the brooks-corey context depending on the position @@ -114,6 +120,20 @@ public: ParentType(gridView), permBackground_(0), permLenses_(0), lensOneLowerLeft_(0), lensOneUpperRight_(0), lensTwoLowerLeft_(0), lensTwoUpperRight_(0), lensThreeLowerLeft_(0), lensThreeUpperRight_(0) { +#if PROBLEM == 0 + // residual saturations + materialLawParamsBackground_.setSwr(0.2); + materialLawParamsBackground_.setSnr(0.2); + + materialLawParamsLenses_.setSwr(0.2); + materialLawParamsLenses_.setSnr(0.2); + + //parameters for Brooks-Corey law + + // entry pressures function + materialLawParamsBackground_.setPe(0.); + materialLawParamsLenses_.setPe(0.); +#elif PROBLEM == 1 // residual saturations materialLawParamsBackground_.setSwr(0.); materialLawParamsBackground_.setSnr(0.); @@ -122,6 +142,20 @@ public: materialLawParamsLenses_.setSnr(0.); //parameters for Brooks-Corey law + + // entry pressures function + materialLawParamsBackground_.setPe(5000.); + materialLawParamsLenses_.setPe(5000.); +#else + // residual saturations + materialLawParamsBackground_.setSwr(0.); + materialLawParamsBackground_.setSnr(0.); + + materialLawParamsLenses_.setSwr(0.); + materialLawParamsLenses_.setSnr(0.); + + //parameters for Brooks-Corey law + // entry pressures function materialLawParamsBackground_.setPe(0.); if (ParameterTree::tree().hasKey("SpatialParams.BackgroundEntryPressure")) @@ -134,16 +168,40 @@ public: { materialLawParamsLenses_.setPe(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, LenseEntryPressure)); } +#endif // Brooks-Corey shape parameters + +#if PROBLEM == 2 materialLawParamsBackground_.setLambda(3); + if (ParameterTree::tree().hasKey("SpatialParams.BackgroundLambda")) + { + materialLawParamsBackground_.setLambda(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, BackgroundLambda)); + } materialLawParamsLenses_.setLambda(2); + if (ParameterTree::tree().hasKey("SpatialParams.LenseLambda")) + { + materialLawParamsLenses_.setLambda(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, LenseLambda)); + } +#else + materialLawParamsBackground_.setLambda(2); + materialLawParamsLenses_.setLambda(2); +#endif +#if PROBLEM == 0 + permBackground_[0][0] = 1e-7; + permBackground_[1][1] = 1e-7; + permLenses_[0][0] = 1e-7; + permLenses_[1][1] = 1e-7; +#else permBackground_[0][0] = 1e-10; permBackground_[1][1] = 1e-10; permLenses_[0][0] = 1e-10; permLenses_[1][1] = 1e-10; +#endif + +#if PROBLEM == 2 if (ParameterTree::tree().hasKey("SpatialParams.BackgroundPermeabilityXX")) { permBackground_[0][0] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, BackgroundPermeabilityXX); @@ -232,6 +290,7 @@ public: { lensThreeUpperRight_[1] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, LensThreeUpperRightY); } +#endif } private: