2015-09-22 09:44:28 -05:00
|
|
|
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
// vi: set et ts=4 sw=4 sts=4:
|
|
|
|
/*
|
|
|
|
This file is part of the Open Porous Media project (OPM).
|
|
|
|
|
|
|
|
OPM 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.
|
|
|
|
|
|
|
|
OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
|
2016-03-14 08:11:22 -05:00
|
|
|
|
|
|
|
Consult the COPYING file in the top-level source directory of this
|
|
|
|
module for the precise wording of the license and the list of
|
|
|
|
copyright holders.
|
2015-09-22 09:44:28 -05:00
|
|
|
*/
|
|
|
|
/*!
|
|
|
|
* \file
|
|
|
|
*
|
|
|
|
* \brief This is the unit test for the class which manages the parameters for the ECL
|
|
|
|
* saturation functions.
|
|
|
|
*
|
|
|
|
* This test requires the presence of opm-parser.
|
|
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
|
2018-03-05 05:48:09 -06:00
|
|
|
#if !HAVE_ECL_INPUT
|
|
|
|
#error "The test for EclMaterialLawManager requires eclipse input support in opm-common"
|
2015-09-22 09:44:28 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp>
|
|
|
|
#include <opm/material/fluidstates/SimpleModularFluidState.hpp>
|
|
|
|
|
2021-12-14 01:24:17 -06:00
|
|
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
|
|
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
|
|
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
|
|
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2016-04-17 04:28:06 -05:00
|
|
|
#include <dune/common/parallel/mpihelper.hh>
|
|
|
|
|
2015-09-22 09:44:28 -05:00
|
|
|
// values of strings taken from the SPE1 test case1 of opm-data
|
|
|
|
static const char* fam1DeckString =
|
|
|
|
"RUNSPEC\n"
|
|
|
|
"\n"
|
|
|
|
"DIMENS\n"
|
|
|
|
" 10 10 3 /\n"
|
|
|
|
"\n"
|
|
|
|
"TABDIMS\n"
|
|
|
|
"/\n"
|
|
|
|
"\n"
|
|
|
|
"OIL\n"
|
|
|
|
"GAS\n"
|
|
|
|
"WATER\n"
|
|
|
|
"\n"
|
|
|
|
"DISGAS\n"
|
|
|
|
"\n"
|
|
|
|
"FIELD\n"
|
|
|
|
"\n"
|
|
|
|
"GRID\n"
|
|
|
|
"\n"
|
|
|
|
"DX\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 300*1000 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"DY\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 300*1000 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"DZ\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 100*20 100*30 100*50 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"TOPS\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 100*8325 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"\n"
|
2019-11-29 04:17:40 -06:00
|
|
|
"PORO\n"
|
|
|
|
" 300*0.15 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"PROPS\n"
|
|
|
|
"\n"
|
|
|
|
"SWOF\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
"0.12 0 1 0\n"
|
|
|
|
"0.18 4.64876033057851E-008 1 0\n"
|
|
|
|
"0.24 0.000000186 0.997 0\n"
|
|
|
|
"0.3 4.18388429752066E-007 0.98 0\n"
|
|
|
|
"0.36 7.43801652892562E-007 0.7 0\n"
|
|
|
|
"0.42 1.16219008264463E-006 0.35 0\n"
|
|
|
|
"0.48 1.67355371900826E-006 0.2 0\n"
|
|
|
|
"0.54 2.27789256198347E-006 0.09 0\n"
|
|
|
|
"0.6 2.97520661157025E-006 0.021 0\n"
|
|
|
|
"0.66 3.7654958677686E-006 0.01 0\n"
|
|
|
|
"0.72 4.64876033057851E-006 0.001 0\n"
|
|
|
|
"0.78 0.000005625 0.0001 0\n"
|
|
|
|
"0.84 6.69421487603306E-006 0 0\n"
|
|
|
|
"0.91 8.05914256198347E-006 0 0\n"
|
|
|
|
"1 0.984 0 0 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"SGOF\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
"0 0 1 0\n"
|
|
|
|
"0.001 0 1 0\n"
|
|
|
|
"0.02 0 0.997 0\n"
|
|
|
|
"0.05 0.005 0.980 0\n"
|
|
|
|
"0.12 0.025 0.700 0\n"
|
|
|
|
"0.2 0.075 0.350 0\n"
|
|
|
|
"0.25 0.125 0.200 0\n"
|
|
|
|
"0.3 0.190 0.090 0\n"
|
|
|
|
"0.4 0.410 0.021 0\n"
|
|
|
|
"0.45 0.60 0.010 0\n"
|
|
|
|
"0.5 0.72 0.001 0\n"
|
|
|
|
"0.6 0.87 0.0001 0\n"
|
|
|
|
"0.7 0.94 0.000 0\n"
|
|
|
|
"0.85 0.98 0.000 0\n"
|
|
|
|
"0.88 0.984 0.000 0 /\n";
|
2015-09-22 09:44:28 -05:00
|
|
|
|
|
|
|
static const char* fam2DeckString =
|
|
|
|
"RUNSPEC\n"
|
|
|
|
"\n"
|
|
|
|
"DIMENS\n"
|
|
|
|
" 10 10 3 /\n"
|
|
|
|
"\n"
|
|
|
|
"TABDIMS\n"
|
|
|
|
"/\n"
|
|
|
|
"\n"
|
|
|
|
"OIL\n"
|
|
|
|
"GAS\n"
|
|
|
|
"WATER\n"
|
|
|
|
"\n"
|
|
|
|
"DISGAS\n"
|
|
|
|
"\n"
|
|
|
|
"FIELD\n"
|
|
|
|
"\n"
|
|
|
|
"GRID\n"
|
|
|
|
"\n"
|
|
|
|
"DX\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 300*1000 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"DY\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 300*1000 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"DZ\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 100*20 100*30 100*50 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"TOPS\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 100*8325 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"\n"
|
2019-11-29 04:17:40 -06:00
|
|
|
"PORO\n"
|
|
|
|
" 300*0.15 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"PROPS\n"
|
|
|
|
"\n"
|
|
|
|
"PVTW\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 4017.55 1.038 3.22E-6 0.318 0.0 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"SWFN\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
"0.12 0 0\n"
|
|
|
|
"0.18 4.64876033057851E-008 0\n"
|
|
|
|
"0.24 0.000000186 0\n"
|
|
|
|
"0.3 4.18388429752066E-007 0\n"
|
|
|
|
"0.36 7.43801652892562E-007 0\n"
|
|
|
|
"0.42 1.16219008264463E-006 0\n"
|
|
|
|
"0.48 1.67355371900826E-006 0\n"
|
|
|
|
"0.54 2.27789256198347E-006 0\n"
|
|
|
|
"0.6 2.97520661157025E-006 0\n"
|
|
|
|
"0.66 3.7654958677686E-006 0\n"
|
|
|
|
"0.72 4.64876033057851E-006 0\n"
|
|
|
|
"0.78 0.000005625 0\n"
|
|
|
|
"0.84 6.69421487603306E-006 0\n"
|
|
|
|
"0.91 8.05914256198347E-006 0\n"
|
|
|
|
"1 0.984 0 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"SGFN\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
"0 0 0\n"
|
|
|
|
"0.001 0 0\n"
|
|
|
|
"0.02 0 0\n"
|
|
|
|
"0.05 0.005 0\n"
|
|
|
|
"0.12 0.025 0\n"
|
|
|
|
"0.2 0.075 0\n"
|
|
|
|
"0.25 0.125 0\n"
|
|
|
|
"0.3 0.190 0\n"
|
|
|
|
"0.4 0.410 0\n"
|
|
|
|
"0.45 0.60 0\n"
|
|
|
|
"0.5 0.72 0\n"
|
|
|
|
"0.6 0.87 0\n"
|
|
|
|
"0.7 0.94 0\n"
|
|
|
|
"0.85 0.98 0\n"
|
|
|
|
"0.88 0.984 0 /\n"
|
2015-09-22 09:44:28 -05:00
|
|
|
"\n"
|
|
|
|
"SOF3\n"
|
2015-10-12 07:26:19 -05:00
|
|
|
" 0 0 0 \n"
|
|
|
|
" 0.03 0 0 \n"
|
|
|
|
" 0.09 0 0 \n"
|
2017-02-24 10:09:40 -06:00
|
|
|
" 0.16 0 0 \n"
|
2015-10-12 07:26:19 -05:00
|
|
|
" 0.18 1* 0 \n"
|
|
|
|
" 0.22 0.0001 1* \n"
|
|
|
|
" 0.28 0.001 0.0001 \n"
|
|
|
|
" 0.34 0.01 1* \n"
|
|
|
|
" 0.38 1* 0.001 \n"
|
|
|
|
" 0.40 0.021 1* \n"
|
|
|
|
" 0.43 1* 0.01 \n"
|
|
|
|
" 0.46 0.09 1* \n"
|
|
|
|
" 0.48 1* 0.021 \n"
|
|
|
|
" 0.52 0.2 1* \n"
|
|
|
|
" 0.58 0.35 0.09 \n"
|
|
|
|
" 0.63 1* 0.2 \n"
|
|
|
|
" 0.64 0.7 1* \n"
|
|
|
|
" 0.68 1* 0.35 \n"
|
|
|
|
" 0.70 0.98 1* \n"
|
|
|
|
" 0.76 0.997 0.7 \n"
|
|
|
|
" 0.83 1 0.98 \n"
|
|
|
|
" 0.86 1 0.997 \n"
|
|
|
|
" 0.879 1 1 \n"
|
|
|
|
" 0.88 1 1 / \n"
|
|
|
|
"\n";
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2017-02-24 10:09:40 -06:00
|
|
|
//Taken as a mix of the SPE1 cases above, and Norne to enable hysteresis
|
|
|
|
static const char* hysterDeckString =
|
|
|
|
"RUNSPEC\n"
|
|
|
|
"\n"
|
|
|
|
"DIMENS\n"
|
|
|
|
" 10 10 3 /\n"
|
|
|
|
"\n"
|
|
|
|
"TABDIMS\n"
|
|
|
|
"/\n"
|
|
|
|
"\n"
|
|
|
|
"OIL\n"
|
|
|
|
"GAS\n"
|
|
|
|
"WATER\n"
|
|
|
|
"\n"
|
|
|
|
"DISGAS\n"
|
|
|
|
"\n"
|
|
|
|
"FIELD\n"
|
|
|
|
"\n"
|
|
|
|
"GRID\n"
|
|
|
|
"\n"
|
|
|
|
"DX\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DY\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DZ\n"
|
|
|
|
" 100*20 100*30 100*50 /\n"
|
|
|
|
"\n"
|
|
|
|
"TOPS\n"
|
|
|
|
" 100*8325 /\n"
|
2019-11-29 04:17:40 -06:00
|
|
|
"PORO\n"
|
|
|
|
" 300*0.15 /\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"EHYSTR\n"
|
2022-10-10 11:16:59 -05:00
|
|
|
"0.1 0 0.1 1* BOTH /\n"
|
2017-02-24 10:09:40 -06:00
|
|
|
"\n"
|
|
|
|
"SATOPTS\n"
|
|
|
|
"HYSTER /\n"
|
|
|
|
"\n"
|
|
|
|
"PROPS\n"
|
|
|
|
"\n"
|
|
|
|
"SWOF\n"
|
|
|
|
"0.12 0 1 0\n"
|
|
|
|
"0.18 4.64876033057851E-008 1 0\n"
|
|
|
|
"0.24 0.000000186 0.997 0\n"
|
|
|
|
"0.3 4.18388429752066E-007 0.98 0\n"
|
|
|
|
"0.36 7.43801652892562E-007 0.7 0\n"
|
|
|
|
"0.42 1.16219008264463E-006 0.35 0\n"
|
|
|
|
"0.48 1.67355371900826E-006 0.2 0\n"
|
|
|
|
"0.54 2.27789256198347E-006 0.09 0\n"
|
|
|
|
"0.6 2.97520661157025E-006 0.021 0\n"
|
|
|
|
"0.66 3.7654958677686E-006 0.01 0\n"
|
|
|
|
"0.72 4.64876033057851E-006 0.001 0\n"
|
|
|
|
"0.78 0.000005625 0.0001 0\n"
|
|
|
|
"0.84 6.69421487603306E-006 0 0\n"
|
|
|
|
"0.91 8.05914256198347E-006 0 0\n"
|
|
|
|
"1 0.984 0 0 /\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"SGOF\n"
|
|
|
|
"0 0 1 0\n"
|
|
|
|
"0.001 0 1 0\n"
|
|
|
|
"0.02 0 0.997 0\n"
|
|
|
|
"0.05 0.005 0.980 0\n"
|
|
|
|
"0.12 0.025 0.700 0\n"
|
|
|
|
"0.2 0.075 0.350 0\n"
|
|
|
|
"0.25 0.125 0.200 0\n"
|
|
|
|
"0.3 0.190 0.090 0\n"
|
|
|
|
"0.4 0.410 0.021 0\n"
|
|
|
|
"0.45 0.60 0.010 0\n"
|
|
|
|
"0.5 0.72 0.001 0\n"
|
|
|
|
"0.6 0.87 0.0001 0\n"
|
|
|
|
"0.7 0.94 0.000 0\n"
|
|
|
|
"0.85 0.98 0.000 0\n"
|
|
|
|
"0.88 0.984 0.000 0 /\n";
|
|
|
|
|
2017-11-23 03:46:55 -06:00
|
|
|
static const char* fam1DeckStringGasOil =
|
|
|
|
"RUNSPEC\n"
|
|
|
|
"\n"
|
|
|
|
"DIMENS\n"
|
|
|
|
" 10 10 3 /\n"
|
|
|
|
"\n"
|
|
|
|
"TABDIMS\n"
|
|
|
|
"/\n"
|
|
|
|
"\n"
|
|
|
|
"OIL\n"
|
|
|
|
"GAS\n"
|
|
|
|
"\n"
|
|
|
|
"DISGAS\n"
|
|
|
|
"\n"
|
|
|
|
"FIELD\n"
|
|
|
|
"\n"
|
|
|
|
"GRID\n"
|
|
|
|
"\n"
|
|
|
|
"DX\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DY\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DZ\n"
|
|
|
|
" 100*20 100*30 100*50 /\n"
|
|
|
|
"\n"
|
|
|
|
"TOPS\n"
|
|
|
|
" 100*8325 /\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
2019-11-29 04:17:40 -06:00
|
|
|
"PORO\n"
|
|
|
|
" 300*0.15 /\n"
|
2017-11-23 03:46:55 -06:00
|
|
|
"PROPS\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"SGOF\n"
|
|
|
|
"0 0 1 0\n"
|
|
|
|
"0.001 0 1 0\n"
|
|
|
|
"0.02 0 0.997 0\n"
|
|
|
|
"0.05 0.005 0.980 0\n"
|
|
|
|
"0.12 0.025 0.700 0\n"
|
|
|
|
"0.2 0.075 0.350 0\n"
|
|
|
|
"0.25 0.125 0.200 0\n"
|
|
|
|
"0.3 0.190 0.090 0\n"
|
|
|
|
"0.4 0.410 0.021 0\n"
|
|
|
|
"0.45 0.60 0.010 0\n"
|
|
|
|
"0.5 0.72 0.001 0\n"
|
|
|
|
"0.6 0.87 0.0001 0\n"
|
|
|
|
"0.7 0.94 0.000 0\n"
|
|
|
|
"0.85 0.98 0.000 0\n"
|
|
|
|
"0.88 0.984 0.000 0 /\n";
|
2017-02-24 10:09:40 -06:00
|
|
|
|
2017-11-23 03:46:55 -06:00
|
|
|
static const char* fam2DeckStringGasOil =
|
|
|
|
"RUNSPEC\n"
|
|
|
|
"\n"
|
|
|
|
"DIMENS\n"
|
|
|
|
" 10 10 3 /\n"
|
|
|
|
"\n"
|
|
|
|
"TABDIMS\n"
|
|
|
|
"/\n"
|
|
|
|
"\n"
|
|
|
|
"OIL\n"
|
|
|
|
"GAS\n"
|
|
|
|
"\n"
|
|
|
|
"DISGAS\n"
|
|
|
|
"\n"
|
|
|
|
"FIELD\n"
|
|
|
|
"\n"
|
|
|
|
"GRID\n"
|
|
|
|
"\n"
|
|
|
|
"DX\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DY\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DZ\n"
|
|
|
|
" 100*20 100*30 100*50 /\n"
|
|
|
|
"\n"
|
|
|
|
"TOPS\n"
|
|
|
|
" 100*8325 /\n"
|
2019-11-29 04:17:40 -06:00
|
|
|
"PORO\n"
|
|
|
|
" 300*0.15 /\n"
|
2017-11-23 03:46:55 -06:00
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"PROPS\n"
|
|
|
|
"\n"
|
|
|
|
"PVTW\n"
|
|
|
|
" 4017.55 1.038 3.22E-6 0.318 0.0 /\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"SGFN\n"
|
|
|
|
"0 0 0\n"
|
|
|
|
"0.001 0 0\n"
|
|
|
|
"0.02 0 0\n"
|
|
|
|
"0.05 0.005 0\n"
|
|
|
|
"0.12 0.025 0\n"
|
|
|
|
"0.2 0.075 0\n"
|
|
|
|
"0.25 0.125 0\n"
|
|
|
|
"0.3 0.190 0\n"
|
|
|
|
"0.4 0.410 0\n"
|
|
|
|
"0.45 0.60 0\n"
|
|
|
|
"0.5 0.72 0\n"
|
|
|
|
"0.6 0.87 0\n"
|
|
|
|
"0.7 0.94 0\n"
|
|
|
|
"0.85 0.98 0\n"
|
|
|
|
"0.88 0.984 0 /\n"
|
|
|
|
"\n"
|
|
|
|
"SOF2\n"
|
|
|
|
"0.12 0.000 \n"
|
|
|
|
"0.15 0.000 \n"
|
|
|
|
"0.3 0.000 \n"
|
|
|
|
"0.4 0.0001 \n"
|
|
|
|
"0.5 0.001 \n"
|
|
|
|
"0.55 0.010 \n"
|
|
|
|
"0.6 0.021 \n"
|
|
|
|
"0.7 0.090 \n"
|
|
|
|
"0.8 0.350 \n"
|
|
|
|
"0.88 0.700 \n"
|
|
|
|
"0.95 0.980 \n"
|
|
|
|
"0.98 0.997 \n"
|
|
|
|
"0.999 1 \n"
|
|
|
|
"1.0 1 \n /\n";
|
2017-02-24 10:09:40 -06:00
|
|
|
|
2022-01-28 11:02:31 -06:00
|
|
|
|
|
|
|
static const char* letDeckString =
|
|
|
|
"RUNSPEC\n"
|
|
|
|
"\n"
|
|
|
|
"DIMENS\n"
|
|
|
|
" 10 10 3 /\n"
|
|
|
|
"\n"
|
|
|
|
"TABDIMS\n"
|
|
|
|
"/\n"
|
|
|
|
"\n"
|
|
|
|
"OIL\n"
|
|
|
|
"GAS\n"
|
|
|
|
"WATER\n"
|
|
|
|
"\n"
|
|
|
|
"DISGAS\n"
|
|
|
|
"\n"
|
|
|
|
"FIELD\n"
|
|
|
|
"\n"
|
|
|
|
"GRID\n"
|
|
|
|
"\n"
|
|
|
|
"DX\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DY\n"
|
|
|
|
" 300*1000 /\n"
|
|
|
|
"DZ\n"
|
|
|
|
" 100*20 100*30 100*50 /\n"
|
|
|
|
"\n"
|
|
|
|
"TOPS\n"
|
|
|
|
" 100*8325 /\n"
|
|
|
|
"\n"
|
|
|
|
"\n"
|
|
|
|
"PORO\n"
|
|
|
|
" 300*0.15 /\n"
|
|
|
|
"PROPS\n"
|
|
|
|
"\n"
|
|
|
|
"SWOFLET\n"
|
|
|
|
" 0.1 0.2 1.5 7.0 1.5 0.5 0.05 0.15 3.5 3.0 1.3 1.0 0.7 17.0 0.95 3.8 0.04 /\n"
|
|
|
|
"\n"
|
|
|
|
"SGOFLET\n"
|
|
|
|
" 0.0 0.03 1.8 1.9 1.0 0.95 0.0 0.01 3.5 4.0 1.1 1.0 1.0 1.0 1.0 0.2 0.01 /\n"
|
|
|
|
"\n";
|
|
|
|
|
|
|
|
|
|
|
|
template <class Scalar>
|
|
|
|
inline Scalar computeLetCurve(const Scalar S, const Scalar L, const Scalar E, const Scalar T)
|
|
|
|
{
|
|
|
|
if (S <= 0.0) {
|
|
|
|
return 0.0;
|
|
|
|
} else if (S >= 1.0) {
|
|
|
|
return 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Scalar powS = Opm::pow(S,L);
|
|
|
|
const Scalar pow1mS = Opm::pow(1.0-S,T);
|
|
|
|
|
|
|
|
return powS/(powS+pow1mS*E);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-14 18:28:07 -06:00
|
|
|
template <class Scalar>
|
|
|
|
inline void testAll()
|
2015-09-22 09:44:28 -05:00
|
|
|
{
|
|
|
|
enum { numPhases = 3 };
|
|
|
|
enum { waterPhaseIdx = 0 };
|
|
|
|
enum { oilPhaseIdx = 1 };
|
|
|
|
enum { gasPhaseIdx = 2 };
|
|
|
|
typedef Opm::ThreePhaseMaterialTraits<Scalar,
|
|
|
|
/*wettingPhaseIdx=*/waterPhaseIdx,
|
|
|
|
/*nonWettingPhaseIdx=*/oilPhaseIdx,
|
|
|
|
/*gasPhaseIdx=*/gasPhaseIdx> MaterialTraits;
|
|
|
|
|
|
|
|
typedef Opm::SimpleModularFluidState<Scalar,
|
|
|
|
/*numPhases=*/3,
|
|
|
|
/*numComponents=*/3,
|
|
|
|
void,
|
|
|
|
/*storePressure=*/false,
|
|
|
|
/*storeTemperature=*/false,
|
|
|
|
/*storeComposition=*/false,
|
|
|
|
/*storeFugacity=*/false,
|
|
|
|
/*storeSaturation=*/true,
|
|
|
|
/*storeDensity=*/false,
|
|
|
|
/*storeViscosity=*/false,
|
|
|
|
/*storeEnthalpy=*/false> FluidState;
|
|
|
|
|
|
|
|
Opm::Parser parser;
|
|
|
|
|
|
|
|
{
|
|
|
|
typedef Opm::EclMaterialLawManager<MaterialTraits> MaterialLawManager;
|
2016-01-14 18:28:07 -06:00
|
|
|
typedef typename MaterialLawManager::MaterialLaw MaterialLaw;
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2019-01-07 05:20:42 -06:00
|
|
|
const auto deck = parser.parseString(fam1DeckString);
|
|
|
|
const Opm::EclipseState eclState(deck);
|
2016-10-13 07:49:48 -05:00
|
|
|
const auto& eclGrid = eclState.getInputGrid();
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2016-10-13 07:49:48 -05:00
|
|
|
size_t n = eclGrid.getCartesianSize();
|
2015-09-22 09:44:28 -05:00
|
|
|
|
|
|
|
MaterialLawManager materialLawManager;
|
2020-03-09 04:28:46 -05:00
|
|
|
materialLawManager.initFromState(eclState);
|
2020-01-28 04:16:52 -06:00
|
|
|
materialLawManager.initParamsForElements(eclState, n);
|
2015-09-22 09:44:28 -05:00
|
|
|
|
|
|
|
if (materialLawManager.enableEndPointScaling())
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between the deck and the EclMaterialLawManager");
|
2015-09-22 09:44:28 -05:00
|
|
|
|
|
|
|
if (materialLawManager.enableHysteresis())
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between the deck and the EclMaterialLawManager");
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
{
|
2019-01-07 05:20:42 -06:00
|
|
|
const auto fam2Deck = parser.parseString(fam2DeckString);
|
|
|
|
const Opm::EclipseState fam2EclState(fam2Deck);
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
Opm::EclMaterialLawManager<MaterialTraits> fam2MaterialLawManager;
|
2020-03-09 04:28:46 -05:00
|
|
|
fam2MaterialLawManager.initFromState(fam2EclState);
|
2020-01-28 04:16:52 -06:00
|
|
|
fam2MaterialLawManager.initParamsForElements(fam2EclState, n);
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
if (fam2MaterialLawManager.enableEndPointScaling())
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between the deck and the EclMaterialLawManager");
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
if (fam2MaterialLawManager.enableHysteresis())
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between the deck and the EclMaterialLawManager");
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2019-01-07 05:20:42 -06:00
|
|
|
const auto hysterDeck = parser.parseString(hysterDeckString);
|
|
|
|
const Opm::EclipseState hysterEclState(hysterDeck);
|
2017-02-24 10:09:40 -06:00
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
Opm::EclMaterialLawManager<MaterialTraits> hysterMaterialLawManager;
|
2020-03-09 04:28:46 -05:00
|
|
|
hysterMaterialLawManager.initFromState(hysterEclState);
|
2020-01-28 04:16:52 -06:00
|
|
|
hysterMaterialLawManager.initParamsForElements(hysterEclState, n);
|
2017-02-24 10:09:40 -06:00
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
if (hysterMaterialLawManager.enableEndPointScaling())
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between the deck and the EclMaterialLawManager");
|
2018-01-30 08:05:48 -06:00
|
|
|
|
|
|
|
if (hysterMaterialLawManager.enableHysteresis() != true)
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between the deck and the EclMaterialLawManager");
|
2017-02-24 10:09:40 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
// make sure that the saturation functions for both keyword families are
|
|
|
|
// identical, and that setting and getting the hysteresis parameters works
|
|
|
|
for (unsigned elemIdx = 0; elemIdx < n; ++ elemIdx) {
|
|
|
|
for (int i = -10; i < 120; ++ i) {
|
|
|
|
Scalar Sw = Scalar(i)/100;
|
|
|
|
for (int j = i; j < 120; ++ j) {
|
|
|
|
Scalar So = Scalar(j)/100;
|
|
|
|
Scalar Sg = 1 - Sw - So;
|
|
|
|
FluidState fs;
|
|
|
|
fs.setSaturation(waterPhaseIdx, Sw);
|
|
|
|
fs.setSaturation(oilPhaseIdx, So);
|
|
|
|
fs.setSaturation(gasPhaseIdx, Sg);
|
2017-02-24 10:09:40 -06:00
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
Scalar pcFam1[numPhases] = { 0.0, 0.0 };
|
|
|
|
Scalar pcFam2[numPhases] = { 0.0, 0.0 };
|
|
|
|
MaterialLaw::capillaryPressures(pcFam1,
|
2015-09-22 09:44:28 -05:00
|
|
|
materialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
2018-01-30 08:05:48 -06:00
|
|
|
MaterialLaw::capillaryPressures(pcFam2,
|
2015-09-22 09:44:28 -05:00
|
|
|
fam2MaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
2018-01-30 08:05:48 -06:00
|
|
|
Scalar krFam1[numPhases] = { 0.0, 0.0 };
|
|
|
|
Scalar krFam2[numPhases] = { 0.0, 0.0 };
|
|
|
|
MaterialLaw::relativePermeabilities(krFam1,
|
|
|
|
materialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
MaterialLaw::relativePermeabilities(krFam2,
|
|
|
|
fam2MaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
|
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
|
|
|
|
|
|
if (std::abs(pcFam1[phaseIdx] - pcFam2[phaseIdx]) > 1e-5)
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between capillary pressure of family 1 and family 2 keywords");
|
2018-01-30 08:05:48 -06:00
|
|
|
if (std::abs(krFam1[phaseIdx] - krFam2[phaseIdx]) > 1e-1)
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between relative permeabilities of family 1 and family 2 keywords");
|
2018-01-30 08:05:48 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This should ideally test each of the materials (stone1, stone2, default, two-phase),
|
|
|
|
// but currently only tests default
|
|
|
|
const Scalar pcSwMdc_in[2] = { 1.0/2.0, 1.0/3.0 };
|
|
|
|
const Scalar krnSwMdc_in[2] = { 1.0/5.0, 1.0/7.0 };
|
|
|
|
hysterMaterialLawManager.setOilWaterHysteresisParams(
|
|
|
|
pcSwMdc_in[0],
|
|
|
|
krnSwMdc_in[0],
|
|
|
|
elemIdx);
|
|
|
|
hysterMaterialLawManager.setGasOilHysteresisParams(
|
|
|
|
pcSwMdc_in[1],
|
|
|
|
krnSwMdc_in[1],
|
|
|
|
elemIdx);
|
|
|
|
|
|
|
|
Scalar pcSwMdc_out[2] = { 0.0, 0.0 };
|
|
|
|
Scalar krnSwMdc_out[2] = { 0.0, 0.0 };
|
|
|
|
hysterMaterialLawManager.oilWaterHysteresisParams(
|
|
|
|
pcSwMdc_out[0],
|
|
|
|
krnSwMdc_out[0],
|
|
|
|
elemIdx);
|
|
|
|
hysterMaterialLawManager.gasOilHysteresisParams(
|
|
|
|
pcSwMdc_out[1],
|
|
|
|
krnSwMdc_out[1],
|
|
|
|
elemIdx);
|
|
|
|
|
|
|
|
for (unsigned phasePairIdx = 0; phasePairIdx < 2; ++ phasePairIdx) {
|
|
|
|
if ((pcSwMdc_in[phasePairIdx] - pcSwMdc_out[phasePairIdx]) != 0.0)
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Hysteresis parameters did not propagate correctly");
|
2018-01-30 08:05:48 -06:00
|
|
|
if ((krnSwMdc_in[phasePairIdx] - krnSwMdc_out[phasePairIdx]) != 0.0)
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Hysteresis parameters did not propagate correctly");
|
2018-01-30 08:05:48 -06:00
|
|
|
|
|
|
|
}
|
2015-09-22 09:44:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-23 03:46:55 -06:00
|
|
|
|
|
|
|
// Gas oil
|
|
|
|
{
|
2019-01-07 05:20:42 -06:00
|
|
|
const auto fam1Deck = parser.parseString(fam1DeckStringGasOil);
|
|
|
|
const Opm::EclipseState fam1EclState(fam1Deck);
|
2017-11-23 03:46:55 -06:00
|
|
|
|
|
|
|
MaterialLawManager fam1materialLawManager;
|
2020-03-09 04:28:46 -05:00
|
|
|
fam1materialLawManager.initFromState(fam1EclState);
|
2020-01-28 04:16:52 -06:00
|
|
|
fam1materialLawManager.initParamsForElements(fam1EclState, n);
|
2017-11-23 03:46:55 -06:00
|
|
|
|
2019-01-07 05:20:42 -06:00
|
|
|
const auto fam2Deck = parser.parseString(fam2DeckStringGasOil);
|
|
|
|
const Opm::EclipseState fam2EclState(fam2Deck);
|
2017-11-23 03:46:55 -06:00
|
|
|
|
|
|
|
Opm::EclMaterialLawManager<MaterialTraits> fam2MaterialLawManager;
|
2020-03-09 04:28:46 -05:00
|
|
|
fam2MaterialLawManager.initFromState(fam2EclState);
|
2020-01-28 04:16:52 -06:00
|
|
|
fam2MaterialLawManager.initParamsForElements(fam2EclState, n);
|
2017-11-23 03:46:55 -06:00
|
|
|
|
|
|
|
for (unsigned elemIdx = 0; elemIdx < n; ++ elemIdx) {
|
|
|
|
for (int i = 0; i < 100; ++ i) {
|
|
|
|
Scalar Sw = 0;
|
|
|
|
Scalar So = Scalar(i)/100;
|
|
|
|
Scalar Sg = 1 - Sw - So;
|
|
|
|
FluidState fs;
|
|
|
|
fs.setSaturation(waterPhaseIdx, Sw);
|
|
|
|
fs.setSaturation(oilPhaseIdx, So);
|
|
|
|
fs.setSaturation(gasPhaseIdx, Sg);
|
|
|
|
|
|
|
|
Scalar pcFam1[numPhases] = { 0.0, 0.0 };
|
|
|
|
Scalar pcFam2[numPhases] = { 0.0, 0.0 };
|
|
|
|
MaterialLaw::capillaryPressures(pcFam1,
|
|
|
|
fam1materialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
MaterialLaw::capillaryPressures(pcFam2,
|
|
|
|
fam2MaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
|
|
|
Scalar krFam1[numPhases] = { 0.0, 0.0 };
|
|
|
|
Scalar krFam2[numPhases] = { 0.0, 0.0 };
|
|
|
|
MaterialLaw::relativePermeabilities(krFam1,
|
|
|
|
fam1materialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
MaterialLaw::relativePermeabilities(krFam2,
|
|
|
|
fam2MaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
|
|
|
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
|
|
|
|
|
|
|
|
if (std::abs(pcFam1[phaseIdx] - pcFam2[phaseIdx]) > 1e-5)
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between capillary pressure of family 1 and family 2 keywords");
|
2017-11-23 03:46:55 -06:00
|
|
|
if (std::abs(krFam1[phaseIdx] - krFam2[phaseIdx]) > 1e-1)
|
2018-02-01 08:40:01 -06:00
|
|
|
throw std::logic_error("Discrepancy between relative permeabilities of family 1 and family 2 keywords");
|
2017-11-23 03:46:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-28 11:02:31 -06:00
|
|
|
|
|
|
|
// LET: Curves from input parameters interpreted via MaterialLawManager versus directly computed curves.
|
|
|
|
{
|
|
|
|
const auto letDeck = parser.parseString(letDeckString);
|
|
|
|
const Opm::EclipseState letEclState(letDeck);
|
|
|
|
|
|
|
|
MaterialLawManager letmaterialLawManager;
|
|
|
|
letmaterialLawManager.initFromState(letEclState);
|
|
|
|
letmaterialLawManager.initParamsForElements(letEclState, n);
|
|
|
|
|
|
|
|
Scalar Swco = 0.1;
|
|
|
|
Scalar psi2Pa = 6894.7573;
|
|
|
|
|
|
|
|
for (unsigned elemIdx = 0; elemIdx < 1; ++ elemIdx) {
|
|
|
|
|
|
|
|
for (int i = -10; i < 120; ++ i) {
|
|
|
|
Scalar So = Scalar(i)/100;
|
|
|
|
|
|
|
|
// Oil in gas and conate water
|
|
|
|
|
|
|
|
Scalar Sw=Swco;
|
|
|
|
Scalar Sg = 1 - Sw - So;
|
|
|
|
FluidState fs;
|
|
|
|
fs.setSaturation(waterPhaseIdx, Sw);
|
|
|
|
fs.setSaturation(oilPhaseIdx, So);
|
|
|
|
fs.setSaturation(gasPhaseIdx, Sg);
|
|
|
|
|
|
|
|
Scalar pcLET[numPhases] = { 0.0, 0.0, 0.0 };
|
|
|
|
MaterialLaw::capillaryPressures(pcLET,
|
|
|
|
letmaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
|
|
|
Scalar krLET[numPhases] = { 0.0, 0.0, 0.0 };
|
|
|
|
MaterialLaw::relativePermeabilities(krLET,
|
|
|
|
letmaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
|
|
|
//SGOFLET
|
|
|
|
//0.0 0.03 1.8 1.9 1.0 0.95 0.0 0.01 3.5 4.0 1.1 1.0 1.0 1.0 1.0 0.2 0.01
|
|
|
|
Scalar krg_let = 0.95*computeLetCurve((1.0-So-0.03-Swco)/(1.0-0.03-0.01-Swco), 1.8, 1.9, 1.0);
|
|
|
|
Scalar krog_let = 1.0*computeLetCurve((So-0.01)/(1.0-0.03-0.01-Swco), 3.5, 4.0, 1.1);
|
|
|
|
//S=(So-Sorg)/(1-Sorg-Sgl-Swco), Pc = Pct + (pcir_pc-Pct)*(1-S)^L/[(1-S)^L+E*S^T]
|
|
|
|
Scalar pcog_let = psi2Pa*(0.01 + (0.2-0.01)*computeLetCurve((1.0-So-Swco)/(1.0-Swco), 1.0, 1.0, 1.0));
|
|
|
|
|
|
|
|
if (std::abs(krLET[gasPhaseIdx]-krg_let) > 1e-5 || std::abs(krLET[oilPhaseIdx]-krog_let) > 1e-5)
|
|
|
|
throw std::logic_error("Inconsistent LET relative permeabilities family 1 gas/oil");
|
|
|
|
if (std::abs(pcLET[gasPhaseIdx]-pcog_let) > 1e-2)
|
|
|
|
throw std::logic_error("Inconsistent LET capillary pressure family 1 gas/oil");
|
|
|
|
|
|
|
|
// Oil in water
|
|
|
|
|
|
|
|
Sg = 0.0;
|
|
|
|
Sw = 1.0-So-Sg;
|
|
|
|
fs.setSaturation(waterPhaseIdx, Sw);
|
|
|
|
fs.setSaturation(oilPhaseIdx, So);
|
|
|
|
fs.setSaturation(gasPhaseIdx, Sg);
|
|
|
|
|
|
|
|
MaterialLaw::capillaryPressures(pcLET,
|
|
|
|
letmaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
|
|
|
MaterialLaw::relativePermeabilities(krLET,
|
|
|
|
letmaterialLawManager.materialLawParams(elemIdx),
|
|
|
|
fs);
|
|
|
|
|
|
|
|
//SWOFLET
|
|
|
|
//0.1 0.2 1.5 7.0 1.5 0.5 0.05 0.15 3.5 3.0 1.3 1.0 0.7 17.0 0.95 3.8 0.04
|
|
|
|
Scalar krw_let = 0.5*computeLetCurve((Sw-0.2)/(1.0-0.2-0.15), 1.5, 7.0, 1.5);
|
|
|
|
Scalar krow_let = 1.0*computeLetCurve((1.0-Sw-0.15)/(1.0-0.2-0.15), 3.5, 3.0, 1.3);
|
|
|
|
// S=(Sw-Swco)/(1-Swco-Sorw), Pc = Pct + (Pcir-Pct)*(1-S)^L/[(1-S)^L+E*S^T]
|
|
|
|
Scalar pcow_let = -psi2Pa*(0.04 + (3.8-0.04)*computeLetCurve(1.0-(Sw-Swco)/(1.0-0.05-Swco), 0.7, 17.0, 0.95));
|
|
|
|
|
|
|
|
if (std::abs(krLET[waterPhaseIdx]-krw_let) > 1e-5 || std::abs(krLET[oilPhaseIdx]-krow_let) > 1e-5)
|
|
|
|
throw std::logic_error("Inconsistent LET relative permeabilities family 1 wat/oil");
|
|
|
|
if (std::abs(pcLET[waterPhaseIdx]-pcow_let) > 1e-2)
|
|
|
|
throw std::logic_error("Inconsistent LET capillary pressure family 1 wat/oil");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-09-22 09:44:28 -05:00
|
|
|
}
|
2016-01-14 18:28:07 -06:00
|
|
|
}
|
2015-09-22 09:44:28 -05:00
|
|
|
|
2016-04-17 04:28:06 -05:00
|
|
|
int main(int argc, char **argv)
|
2016-01-14 18:28:07 -06:00
|
|
|
{
|
2016-04-17 04:28:06 -05:00
|
|
|
Dune::MPIHelper::instance(argc, argv);
|
|
|
|
|
|
|
|
testAll<double>();
|
|
|
|
testAll<float>();
|
|
|
|
|
2015-09-22 09:44:28 -05:00
|
|
|
return 0;
|
|
|
|
}
|