Merge pull request #535 from blattms/support-editnnc

Added support for honoring keyword EDITNNC during deck parsing.
This commit is contained in:
Joakim Hove
2018-10-25 15:49:06 +02:00
committed by GitHub
4 changed files with 189 additions and 5 deletions

View File

@@ -31,6 +31,10 @@ struct NNCdata {
size_t cell1;
size_t cell2;
double trans;
NNCdata(size_t c1, size_t c2, double t)
: cell1(c1), cell2(c2), trans(t)
{}
NNCdata() = default;
};
class Deck;

View File

@@ -22,19 +22,115 @@
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/GridDims.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/N.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/E.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <sstream>
namespace Opm
{
void readEditNncs(const std::vector< const DeckKeyword* >&, std::vector<NNCdata>&, const GridDims&);
void applyEditNncs(std::vector<NNCdata>&, std::vector<NNCdata>&);
NNC::NNC(const Deck& deck) {
GridDims gridDims(deck);
const auto& nncs = deck.getKeywordList<ParserKeywords::NNC>();
for (size_t idx_nnc = 0; idx_nnc<nncs.size(); ++idx_nnc) {
const auto& nnc = *nncs[idx_nnc];
for (size_t i = 0; i < nnc.size(); ++i) {
std::array<size_t, 3> ijk1;
ijk1[0] = static_cast<size_t>(nnc.getRecord(i).getItem(0).get< int >(0)-1);
ijk1[1] = static_cast<size_t>(nnc.getRecord(i).getItem(1).get< int >(0)-1);
ijk1[2] = static_cast<size_t>(nnc.getRecord(i).getItem(2).get< int >(0)-1);
size_t global_index1 = gridDims.getGlobalIndex(ijk1[0],ijk1[1],ijk1[2]);
std::array<size_t, 3> ijk2;
ijk2[0] = static_cast<size_t>(nnc.getRecord(i).getItem(3).get< int >(0)-1);
ijk2[1] = static_cast<size_t>(nnc.getRecord(i).getItem(4).get< int >(0)-1);
ijk2[2] = static_cast<size_t>(nnc.getRecord(i).getItem(5).get< int >(0)-1);
size_t global_index2 = gridDims.getGlobalIndex(ijk2[0],ijk2[1],ijk2[2]);
const double trans = nnc.getRecord(i).getItem(6).getSIDouble(0);
addNNC(global_index1, global_index2, trans);
}
}
const auto& tmpEditNncs = deck.getKeywordList<ParserKeywords::EDITNNC>();
std::vector<NNCdata> editNncs(tmpEditNncs.size());
readEditNncs(tmpEditNncs, editNncs, gridDims);
applyEditNncs(m_nnc, editNncs);
}
void applyEditNncs(std::vector<NNCdata>& nncs, std::vector<NNCdata>& editNncs)
{
auto compare = [](const NNCdata& d1, const NNCdata& d2)
{ return d1.cell1 < d2.cell1 ||
( d1.cell1 == d2.cell1 && d1.cell2 < d2.cell2 );};
std::sort(editNncs.begin(), editNncs.end(), compare);
std::sort(nncs.begin(), nncs.end(), compare);
std::ostringstream warning;
warning<<"The following NNC entries in EDITNNC have been ignored: ";
bool ignored = false;
std::size_t counter = 0;
// Assuming that we edit less nncs than we have
auto nncIt = nncs.begin();
for( const auto& edit: editNncs )
{
auto candidate = std::lower_bound(nncIt, nncs.end(), edit, compare);
bool processed = false;
for( auto next=candidate; next != nncs.end() &&
( next->cell1 == edit.cell1 && next->cell2 == edit.cell2 );
++next)
{
next->trans *= edit.trans;
processed = true;
}
if ( ! processed )
{
warning << edit.cell1 << "->" << edit.cell2 << " ";
ignored = true;
}
++counter;
if ( candidate != nncs.end() )
{
// There could be another edit for the same cell, start over.
nncIt = candidate;
}
else
{
// for all other editnnc there will be no nnc.
break;
}
}
if ( counter < editNncs.size() )
{
ignored = true;
for(auto nnc = editNncs.begin() + counter, end = editNncs.end(); nnc != end; ++nnc)
{
warning << nnc->cell1 << "->" << nnc->cell2 << " ";
}
}
if ( ignored )
{
OpmLog::warning(warning.str());
}
}
void readEditNncs(const std::vector< const DeckKeyword* >& editNncsKw, std::vector<NNCdata>& editNncs, const GridDims& gridDims)
{
for (size_t idx_nnc = 0; idx_nnc<editNncsKw.size(); ++idx_nnc) {
const auto& nnc = *editNncsKw[idx_nnc];
for (size_t i = 0; i < nnc.size(); ++i) {
std::array<size_t, 3> ijk1;
ijk1[0] = static_cast<size_t>(nnc.getRecord(i).getItem(0).get< int >(0)-1);
@@ -48,9 +144,9 @@ namespace Opm
ijk2[2] = static_cast<size_t>(nnc.getRecord(i).getItem(5).get< int >(0)-1);
size_t global_index2 = gridDims.getGlobalIndex(ijk2[0],ijk2[1],ijk2[2]);
const double trans = nnc.getRecord(i).getItem(6).getSIDouble(0);
const double trans = nnc.getRecord(i).getItem(6).get<double>(0);
addNNC(global_index1,global_index2,trans);
editNncs.emplace_back(global_index1, global_index2, trans);
}
}
}

View File

@@ -0,0 +1,48 @@
RUNSPEC
OIL
GAS
WATER
DIMENS
10 10 1 /
GRID
DXV
10*1000.0
/
DYV
10*1000.0
/
DZ
100*20.0
/
TOPS
100*10
/
NNC
1 1 1 2 1 1 0.5 /
1 1 1 1 2 1 1.0 /
/
NNC
1 1 1 2 1 1 0.5 /
1 2 1 1 2 1 1.0 /
2 2 1 2 2 1 1.0 /
/
EDIT
EDITNNC
1 1 1 2 1 1 2.0 /
1 2 1 1 2 1 10.0 /
3 2 1 3 2 1 10.0 /
2 2 1 2 2 1 2.0 /
2 2 1 2 2 1 3.0 /
/

View File

@@ -51,13 +51,15 @@ BOOST_AUTO_TEST_CASE(readDeck)
const std::vector<NNCdata>& nncdata = nnc.nncdata();
// test the NNCs in nnc.DATA
// NNCs are orderd lexicographically
// Therefore the two equal NNCs are next to each other
BOOST_CHECK_EQUAL(nnc.numNNC(), 4);
BOOST_CHECK_EQUAL(nncdata[0].cell1, 0);
BOOST_CHECK_EQUAL(nncdata[0].cell2, 1);
BOOST_CHECK_EQUAL(nncdata[0].trans, 0.5 * Opm::Metric::Transmissibility);
BOOST_CHECK_EQUAL(nncdata[1].cell1, 0);
BOOST_CHECK_EQUAL(nncdata[1].cell2, 10);
BOOST_CHECK_EQUAL(nncdata[1].trans, 1.0 * Opm::Metric::Transmissibility);
BOOST_CHECK_EQUAL(nncdata[2].cell1, 0);
BOOST_CHECK_EQUAL(nncdata[2].cell2, 10);
BOOST_CHECK_EQUAL(nncdata[2].trans, 1.0 * Opm::Metric::Transmissibility);
}
@@ -89,3 +91,37 @@ BOOST_AUTO_TEST_CASE(addNNC)
BOOST_CHECK_EQUAL(nncdata[0].trans, 2.0);
}
BOOST_AUTO_TEST_CASE(editNNC)
{
auto eclipseState = Parser::parse(pathprefix() + "NNC/EDITNNC.DATA");
const auto& nnc = eclipseState.getInputNNC();
BOOST_CHECK(nnc.hasNNC());
const std::vector<NNCdata>& nncdata = nnc.nncdata();
// test the NNCs in nnc.DATA
// note that these are ordered lexicographically
// 0: 1,1,1 -> 2,1,1
BOOST_CHECK_EQUAL(nncdata[0].cell1, 0);
BOOST_CHECK_EQUAL(nncdata[0].cell2, 1);
BOOST_CHECK_EQUAL(nncdata[0].trans, 1.0 * Opm::Metric::Transmissibility);
// 1: 1,1,1 -> 2,1,1
BOOST_CHECK_EQUAL(nncdata[0].cell1, 0);
BOOST_CHECK_EQUAL(nncdata[0].cell2, 1);
BOOST_CHECK_EQUAL(nncdata[0].trans, 1.0 * Opm::Metric::Transmissibility);
// 2: 1,1,1 -> 1,2,1
BOOST_CHECK_EQUAL(nncdata[2].cell1, 0);
BOOST_CHECK_EQUAL(nncdata[2].cell2, 10);
BOOST_CHECK_EQUAL(nncdata[2].trans, 1.0 * Opm::Metric::Transmissibility);
// 3: 1,2,1 -> 1,2,1
BOOST_CHECK_EQUAL(nncdata[3].cell1, 10);
BOOST_CHECK_EQUAL(nncdata[3].cell2, 10);
BOOST_CHECK_EQUAL(nncdata[3].trans, 10.0 * Opm::Metric::Transmissibility);
// 4: 2,2,1 -> 2,2,1
BOOST_CHECK_EQUAL(nncdata[4].cell1, 11);
BOOST_CHECK_EQUAL(nncdata[4].cell2, 11);
BOOST_CHECK_EQUAL(nncdata[4].trans, 6.0 * Opm::Metric::Transmissibility);
// There should be no entry due EDITNNC for 3,2,1 -> 3,2,1 as there is no nnc
BOOST_CHECK_EQUAL(nnc.numNNC(), 5);
}