Add Tool for Checking Array Dimensions
This commit introduces a new function,
Opm::checkConsistentArrayDimensions()
that inspects various dynamic array/table sizes and compares those
to the maximum dimensions requested in the relevant *DIMS keywords
of the RUNSPEC section.
At present we check only items one through four of WELLDIMS since
those are directly relevant for the ECLIPSE-compatible output code.
We leverage the ErrorGuard to integrate into the existing mechanism
for terminating a simulation run if there's a parse failure.
This commit is contained in:
280
tests/test_ArrayDimChecker.cpp
Normal file
280
tests/test_ArrayDimChecker.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA
|
||||
|
||||
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 3 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/>.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE Array_Dimension_Checker
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/output_test_stream.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
Opm::Deck simCaseWellDims()
|
||||
{
|
||||
const auto input = std::string{ R"(RUNSPEC
|
||||
TITLE
|
||||
'Check Well Dimensions' /
|
||||
|
||||
DIMENS
|
||||
20 20 15 /
|
||||
|
||||
OIL
|
||||
WATER
|
||||
|
||||
METRIC
|
||||
|
||||
EQLDIMS
|
||||
-- Defaulted
|
||||
/
|
||||
|
||||
TABDIMS
|
||||
-- Defaulted
|
||||
/
|
||||
|
||||
WELLDIMS
|
||||
-- Defaulted
|
||||
/
|
||||
|
||||
-- ====================================================================
|
||||
GRID
|
||||
|
||||
SPECGRID
|
||||
20 20 15 1 F /
|
||||
|
||||
DXV
|
||||
20*100.0 /
|
||||
|
||||
DYV
|
||||
20*100.0 /
|
||||
|
||||
DZV
|
||||
15*0.1 /
|
||||
|
||||
DEPTHZ
|
||||
441*2000 /
|
||||
|
||||
PORO
|
||||
6000*0.3 /
|
||||
|
||||
PERMX
|
||||
6000*100.0 /
|
||||
|
||||
COPY
|
||||
'PERMX' 'PERMY' /
|
||||
'PERMX' 'PERMZ' /
|
||||
/
|
||||
|
||||
MULTIPLY
|
||||
'PERMZ' 0.1 /
|
||||
/
|
||||
|
||||
-- ====================================================================
|
||||
PROPS
|
||||
|
||||
SWOF
|
||||
0 0 1 0
|
||||
1 1 0 0 /
|
||||
|
||||
PVDO
|
||||
1 1.0 0.5
|
||||
800 0.99 0.51 /
|
||||
|
||||
PVTW
|
||||
300 0.99 1.0e-6 0.25 0 /
|
||||
|
||||
DENSITY
|
||||
850.0 1014.0 1.05 /
|
||||
|
||||
-- ====================================================================
|
||||
SOLUTION
|
||||
|
||||
EQUIL
|
||||
2000 300 2010 0.0 2000 10 /
|
||||
|
||||
-- ====================================================================
|
||||
SUMMARY
|
||||
ALL
|
||||
|
||||
-- ====================================================================
|
||||
SCHEDULE
|
||||
|
||||
RPTRST
|
||||
BASIC=5 FREQ=6 /
|
||||
|
||||
GRUPTREE
|
||||
'G1' 'FIELD' /
|
||||
'PLAT1' 'G1' /
|
||||
'PLAT2' 'G1' /
|
||||
'I-NORTH' 'PLAT1' /
|
||||
'P-NORTH' 'PLAT1' /
|
||||
'O-WEST' 'PLAT2' /
|
||||
'I-SOUTH' 'PLAT2' /
|
||||
'P-EAST' 'PLAT2' /
|
||||
'G2' 'FIELD' /
|
||||
'PLAT3' 'G2' /
|
||||
'I-2' 'PLAT3' /
|
||||
/
|
||||
|
||||
WELSPECS
|
||||
'I-N-1' 'I-NORTH' 1 1 2000.15 'WATER' /
|
||||
'I-N-2' 'I-NORTH' 5 1 2001.05 'WATER' /
|
||||
'P-N-0' 'P-NORTH' 1 10 2000.15 'OIL' /
|
||||
'P-N-1' 'P-NORTH' 10 15 2000.15 'OIL' /
|
||||
'P-N-2' 'P-NORTH' 1 20 2000.15 'OIL' /
|
||||
'P-N-3' 'P-NORTH' 19 20 2000.15 'OIL' /
|
||||
'P-N-4' 'P-NORTH' 15 10 2000.15 'OIL' /
|
||||
'P-N-5' 'P-NORTH' 10 10 2000.15 'OIL' /
|
||||
'P-N-6' 'P-NORTH' 10 20 2000.15 'OIL' /
|
||||
'P-N-7' 'P-NORTH' 7 15 2000.15 'OIL' /
|
||||
'P-N-8' 'P-NORTH' 2 20 2000.15 'OIL' /
|
||||
'P-N-9' 'P-NORTH' 20 1 2000.05 'OIL' /
|
||||
/
|
||||
|
||||
COMPDAT
|
||||
'I-N-1' 0 0 2 10 'OPEN' 1* 1* 1.0 /
|
||||
'I-N-2' 0 0 10 15 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-0' 0 0 2 3 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-1' 0 0 2 4 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-2' 0 0 2 5 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-3' 0 0 2 6 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-4' 0 0 2 7 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-5' 0 0 2 8 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-6' 0 0 2 9 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-7' 0 0 2 10 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-8' 0 0 2 5 'OPEN' 1* 1* 1.0 /
|
||||
'P-N-9' 0 0 1 15 'OPEN' 1* 1* 1.0 /
|
||||
/
|
||||
|
||||
WCONPROD
|
||||
-- Well O/S Mode ORAT WRAT GRAT LRAT RESV BHP
|
||||
'P-N-*' 'OPEN' 'LRAT' 1* 1* 1* 5E3 1* 100 /
|
||||
/
|
||||
|
||||
WCONINJE
|
||||
-- Well Type O/S Mode RATE RESV BHP
|
||||
'I-N-*' 'WATER' 'OPEN' 'RATE' 25E3 1* 500 /
|
||||
/
|
||||
|
||||
TSTEP
|
||||
100*30 /
|
||||
|
||||
END
|
||||
)" };
|
||||
|
||||
return Opm::Parser{}.parseString(input);
|
||||
}
|
||||
}
|
||||
|
||||
struct CaseObjects
|
||||
{
|
||||
explicit CaseObjects(const Opm::Deck& deck);
|
||||
~CaseObjects();
|
||||
|
||||
CaseObjects(const CaseObjects& rhs) = default;
|
||||
CaseObjects(CaseObjects&& rhs) = default;
|
||||
|
||||
CaseObjects& operator=(const CaseObjects& rhs) = default;
|
||||
CaseObjects& operator=(CaseObjects&& rhs) = default;
|
||||
|
||||
Opm::ErrorGuard guard;
|
||||
Opm::ParseContext ctxt;
|
||||
Opm::EclipseState es;
|
||||
Opm::Schedule sched;
|
||||
};
|
||||
|
||||
CaseObjects::CaseObjects(const Opm::Deck& deck)
|
||||
: guard{}
|
||||
, ctxt {}
|
||||
, es (deck, ctxt, guard)
|
||||
, sched(deck, es, ctxt, guard)
|
||||
{}
|
||||
|
||||
CaseObjects::~CaseObjects()
|
||||
{
|
||||
this->guard.clear();
|
||||
}
|
||||
|
||||
class RedirectCERR
|
||||
{
|
||||
public:
|
||||
explicit RedirectCERR(std::streambuf* buf);
|
||||
~RedirectCERR();
|
||||
|
||||
private:
|
||||
std::streambuf* orig_;
|
||||
};
|
||||
|
||||
RedirectCERR::RedirectCERR(std::streambuf* buf)
|
||||
: orig_{ std::cerr.rdbuf(buf) }
|
||||
{
|
||||
}
|
||||
|
||||
RedirectCERR::~RedirectCERR()
|
||||
{
|
||||
std::cerr.rdbuf(this->orig_);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(WellDimensions)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MaxGroupSize)
|
||||
{
|
||||
auto cse = CaseObjects{ simCaseWellDims() };
|
||||
|
||||
// Verify at most ten wells in a single group.
|
||||
BOOST_CHECK_EQUAL(Opm::maxGroupSize(cse.sched, 1), 10);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(WellDims)
|
||||
{
|
||||
auto cse = CaseObjects{ simCaseWellDims() };
|
||||
|
||||
// There should be no failures in basic input layer
|
||||
BOOST_CHECK(!cse.guard);
|
||||
|
||||
Opm::checkConsistentArrayDimensions(cse.es , cse.sched,
|
||||
cse.ctxt, cse.guard);
|
||||
|
||||
// There *should* be errors from dimension checking
|
||||
BOOST_CHECK(cse.guard);
|
||||
|
||||
// Verify that we get expected output from ErrorGuard::dump()
|
||||
boost::test_tools::output_test_stream output{"expect-wdims.err.out", true};
|
||||
{
|
||||
RedirectCERR stream(output.rdbuf());
|
||||
|
||||
cse.guard.dump();
|
||||
|
||||
BOOST_CHECK(output.match_pattern());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user