commit
54cae0f07e
@ -63,7 +63,6 @@ if(ENABLE_ECL_INPUT)
|
|||||||
src/opm/parser/eclipse/EclipseState/EclipseConfig.cpp
|
src/opm/parser/eclipse/EclipseState/EclipseConfig.cpp
|
||||||
src/opm/parser/eclipse/EclipseState/EclipseState.cpp
|
src/opm/parser/eclipse/EclipseState/EclipseState.cpp
|
||||||
src/opm/parser/eclipse/EclipseState/EndpointScaling.cpp
|
src/opm/parser/eclipse/EclipseState/EndpointScaling.cpp
|
||||||
src/opm/parser/eclipse/EclipseState/Edit/EDITNNC.cpp
|
|
||||||
src/opm/parser/eclipse/EclipseState/Grid/FieldProps.cpp
|
src/opm/parser/eclipse/EclipseState/Grid/FieldProps.cpp
|
||||||
src/opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.cpp
|
src/opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.cpp
|
||||||
src/opm/parser/eclipse/EclipseState/Grid/Box.cpp
|
src/opm/parser/eclipse/EclipseState/Grid/Box.cpp
|
||||||
@ -382,6 +381,7 @@ if(ENABLE_ECL_INPUT)
|
|||||||
tests/parser/TuningTests.cpp
|
tests/parser/TuningTests.cpp
|
||||||
tests/parser/UDQTests.cpp
|
tests/parser/UDQTests.cpp
|
||||||
tests/parser/UnitTests.cpp
|
tests/parser/UnitTests.cpp
|
||||||
|
tests/parser/integration/NNCTests.cpp
|
||||||
tests/parser/WellSolventTests.cpp
|
tests/parser/WellSolventTests.cpp
|
||||||
tests/parser/WellTracerTests.cpp
|
tests/parser/WellTracerTests.cpp
|
||||||
tests/parser/WellTests.cpp
|
tests/parser/WellTests.cpp
|
||||||
@ -580,7 +580,6 @@ if(ENABLE_ECL_INPUT)
|
|||||||
opm/parser/eclipse/EclipseState/Util/IOrderSet.hpp
|
opm/parser/eclipse/EclipseState/Util/IOrderSet.hpp
|
||||||
opm/parser/eclipse/EclipseState/Util/OrderedMap.hpp
|
opm/parser/eclipse/EclipseState/Util/OrderedMap.hpp
|
||||||
opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp
|
opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp
|
||||||
opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp
|
|
||||||
opm/parser/eclipse/EclipseState/Grid/FieldData.hpp
|
opm/parser/eclipse/EclipseState/Grid/FieldData.hpp
|
||||||
opm/parser/eclipse/EclipseState/Grid/Keywords.hpp
|
opm/parser/eclipse/EclipseState/Grid/Keywords.hpp
|
||||||
opm/parser/eclipse/EclipseState/Grid/GridDims.hpp
|
opm/parser/eclipse/EclipseState/Grid/GridDims.hpp
|
||||||
|
@ -44,11 +44,9 @@ list(APPEND EXTRA_TESTS EclipseStateTests)
|
|||||||
foreach (test BoxTest
|
foreach (test BoxTest
|
||||||
CheckDeckValidity
|
CheckDeckValidity
|
||||||
EclipseGridCreateFromDeck
|
EclipseGridCreateFromDeck
|
||||||
EDITNNCTests
|
|
||||||
IncludeTest
|
IncludeTest
|
||||||
IntegrationTests
|
IntegrationTests
|
||||||
IOConfigIntegrationTest
|
IOConfigIntegrationTest
|
||||||
NNCTests
|
|
||||||
ParseKEYWORD
|
ParseKEYWORD
|
||||||
Polymer
|
Polymer
|
||||||
ScheduleCreateFromDeck
|
ScheduleCreateFromDeck
|
||||||
|
@ -112,7 +112,7 @@ public:
|
|||||||
* are not yet written to disk.
|
* are not yet written to disk.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void writeInitial( data::Solution simProps = data::Solution(), std::map<std::string, std::vector<int> > int_data = {}, const NNC& nnc = NNC());
|
void writeInitial( data::Solution simProps = data::Solution(), std::map<std::string, std::vector<int> > int_data = {}, const std::vector<NNCdata>& nnc = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Overwrite the initial OIP values.
|
* \brief Overwrite the initial OIP values.
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
class EclipseGrid;
|
class EclipseGrid;
|
||||||
@ -52,7 +54,7 @@ namespace Opm { namespace InitIO {
|
|||||||
const ::Opm::Schedule& schedule,
|
const ::Opm::Schedule& schedule,
|
||||||
const ::Opm::data::Solution& simProps,
|
const ::Opm::data::Solution& simProps,
|
||||||
std::map<std::string, std::vector<int>> int_data,
|
std::map<std::string, std::vector<int>> int_data,
|
||||||
const ::Opm::NNC& nnc,
|
const std::vector<::Opm::NNCdata>& nnc,
|
||||||
::Opm::EclIO::OutputStream::Init& initFile);
|
::Opm::EclIO::OutputStream::Init& initFile);
|
||||||
|
|
||||||
}} // namespace Opm::InitIO
|
}} // namespace Opm::InitIO
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include <opm/parser/eclipse/EclipseState/AquiferConfig.hpp>
|
#include <opm/parser/eclipse/EclipseState/AquiferConfig.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/EclipseConfig.hpp>
|
#include <opm/parser/eclipse/EclipseState/EclipseConfig.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/TracerConfig.hpp>
|
#include <opm/parser/eclipse/EclipseState/TracerConfig.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp>
|
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/FaultCollection.hpp>
|
#include <opm/parser/eclipse/EclipseState/Grid/FaultCollection.hpp>
|
||||||
@ -78,7 +77,7 @@ namespace Opm {
|
|||||||
|
|
||||||
const InitConfig& getInitConfig() const;
|
const InitConfig& getInitConfig() const;
|
||||||
InitConfig& getInitConfig();
|
InitConfig& getInitConfig();
|
||||||
|
|
||||||
const SimulationConfig& getSimulationConfig() const;
|
const SimulationConfig& getSimulationConfig() const;
|
||||||
virtual const EclipseGrid& getInputGrid() const;
|
virtual const EclipseGrid& getInputGrid() const;
|
||||||
|
|
||||||
@ -90,11 +89,6 @@ namespace Opm {
|
|||||||
const NNC& getInputNNC() const;
|
const NNC& getInputNNC() const;
|
||||||
bool hasInputNNC() const;
|
bool hasInputNNC() const;
|
||||||
|
|
||||||
/// editing non-neighboring connections
|
|
||||||
/// the non-standard adjacencies as specified in input deck
|
|
||||||
const EDITNNC& getInputEDITNNC() const;
|
|
||||||
bool hasInputEDITNNC() const;
|
|
||||||
|
|
||||||
// The potentially parallelized field properties
|
// The potentially parallelized field properties
|
||||||
virtual const FieldPropsManager& fieldProps() const;
|
virtual const FieldPropsManager& fieldProps() const;
|
||||||
// Always the non-parallel field properties
|
// Always the non-parallel field properties
|
||||||
@ -127,7 +121,6 @@ namespace Opm {
|
|||||||
m_eclipseConfig.serializeOp(serializer);
|
m_eclipseConfig.serializeOp(serializer);
|
||||||
m_deckUnitSystem.serializeOp(serializer);
|
m_deckUnitSystem.serializeOp(serializer);
|
||||||
m_inputNnc.serializeOp(serializer);
|
m_inputNnc.serializeOp(serializer);
|
||||||
m_inputEditNnc.serializeOp(serializer);
|
|
||||||
m_gridDims.serializeOp(serializer);
|
m_gridDims.serializeOp(serializer);
|
||||||
m_simulationConfig.serializeOp(serializer);
|
m_simulationConfig.serializeOp(serializer);
|
||||||
m_transMult.serializeOp(serializer);
|
m_transMult.serializeOp(serializer);
|
||||||
@ -152,9 +145,8 @@ namespace Opm {
|
|||||||
Runspec m_runspec;
|
Runspec m_runspec;
|
||||||
EclipseConfig m_eclipseConfig;
|
EclipseConfig m_eclipseConfig;
|
||||||
UnitSystem m_deckUnitSystem;
|
UnitSystem m_deckUnitSystem;
|
||||||
NNC m_inputNnc;
|
|
||||||
EDITNNC m_inputEditNnc;
|
|
||||||
EclipseGrid m_inputGrid;
|
EclipseGrid m_inputGrid;
|
||||||
|
NNC m_inputNnc;
|
||||||
GridDims m_gridDims;
|
GridDims m_gridDims;
|
||||||
FieldPropsManager field_props;
|
FieldPropsManager field_props;
|
||||||
SimulationConfig m_simulationConfig;
|
SimulationConfig m_simulationConfig;
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 Equinor AS
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
#ifndef OPM_COMMON_EDITNNC_HPP
|
|
||||||
#define OPM_COMMON_EDITNNC_HPP
|
|
||||||
|
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
|
||||||
namespace Opm
|
|
||||||
{
|
|
||||||
|
|
||||||
/// Represents edit information for non-neighboring connections (NNCs, faults, etc.)
|
|
||||||
class EDITNNC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EDITNNC() = default;
|
|
||||||
|
|
||||||
/// Construct from input deck
|
|
||||||
explicit EDITNNC(const Deck& deck);
|
|
||||||
|
|
||||||
/// Returns an instance used for serialization test
|
|
||||||
static EDITNNC serializeObject();
|
|
||||||
|
|
||||||
/// \brief Get an ordered set of EDITNNC
|
|
||||||
const std::vector<NNCdata>& data() const
|
|
||||||
{
|
|
||||||
return m_editnnc;
|
|
||||||
}
|
|
||||||
/// \brief Get the number of entries
|
|
||||||
size_t size() const;
|
|
||||||
/// \brief Whether EDITNNC was empty.
|
|
||||||
bool empty() const;
|
|
||||||
|
|
||||||
bool operator==(const EDITNNC& data) const;
|
|
||||||
|
|
||||||
template<class Serializer>
|
|
||||||
void serializeOp(Serializer& serializer)
|
|
||||||
{
|
|
||||||
serializer.vector(m_editnnc);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<NNCdata> m_editnnc;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif // OPM_COMMON_EDITNNC_HPP
|
|
@ -89,7 +89,7 @@ namespace Opm {
|
|||||||
size_t activeIndex(size_t i, size_t j, size_t k) const;
|
size_t activeIndex(size_t i, size_t j, size_t k) const;
|
||||||
size_t activeIndex(size_t globalIndex) const;
|
size_t activeIndex(size_t globalIndex) const;
|
||||||
|
|
||||||
void save(const std::string& filename, bool formatted, const Opm::NNC& nnc, const Opm::UnitSystem& units) const;
|
void save(const std::string& filename, bool formatted, const std::vector<Opm::NNCdata>& nnc, const Opm::UnitSystem& units) const;
|
||||||
/*
|
/*
|
||||||
Observe that the there is a getGlobalIndex(i,j,k)
|
Observe that the there is a getGlobalIndex(i,j,k)
|
||||||
implementation in the base class. This method - translating
|
implementation in the base class. This method - translating
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2015 IRIS
|
Copyright 2015 IRIS
|
||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify
|
OPM is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
OPM is distributed in the hope that it will be useful,
|
OPM is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@ -22,11 +22,17 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
||||||
|
|
||||||
namespace Opm
|
namespace Opm
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class GridDims;
|
||||||
|
|
||||||
struct NNCdata {
|
struct NNCdata {
|
||||||
NNCdata(size_t c1, size_t c2, double t)
|
NNCdata(size_t c1, size_t c2, double t)
|
||||||
: cell1(c1), cell2(c2), trans(t)
|
: cell1(c1), cell2(c2), trans(t)
|
||||||
@ -48,41 +54,89 @@ struct NNCdata {
|
|||||||
serializer(trans);
|
serializer(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Observe that the operator< is only for cell ordering and does not consider the
|
||||||
|
// trans member
|
||||||
|
bool operator<(const NNCdata& other) const
|
||||||
|
{
|
||||||
|
return std::tie(this->cell1, this->cell2) < std::tie(other.cell1, other.cell2);
|
||||||
|
}
|
||||||
|
|
||||||
size_t cell1;
|
size_t cell1;
|
||||||
size_t cell2;
|
size_t cell2;
|
||||||
double trans;
|
double trans;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Deck;
|
|
||||||
|
|
||||||
/// Represents non-neighboring connections (non-standard adjacencies).
|
|
||||||
/// This class is essentially a directed weighted graph.
|
class Deck;
|
||||||
|
class EclipseGrid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This class is an internalization of the NNC and EDITNNC keywords. Because the
|
||||||
|
opm-common codebase does not itself manage the simulation grid the purpose of
|
||||||
|
the NNC class is mainly to hold on to the NNC/EDITNNC input and pass it on to
|
||||||
|
the grid construction proper.
|
||||||
|
|
||||||
|
The EDITNNC keywords can operate on two different types of NNCs.
|
||||||
|
|
||||||
|
1. NNCs which have been explicitly entered using the NNC keyword.
|
||||||
|
2. NNCs which are inderectly inferred from the grid - e.g. due to faults.
|
||||||
|
|
||||||
|
When processing the EDITNNC keyword the class will search through the NNCs
|
||||||
|
configured explicitly with the NNC keyword and apply the edit transformation
|
||||||
|
on those NNCs, EDITNNCs which affect NNCs which are not configured explicitly
|
||||||
|
are stored for later use by the simulator.
|
||||||
|
|
||||||
|
The class guarantees the following ordering:
|
||||||
|
|
||||||
|
1. For all NNC / EDITNNC records we will have cell1 <= cell2
|
||||||
|
2. The vectors NNC::input() and NNC::edit() will be ordered in ascending
|
||||||
|
order.
|
||||||
|
|
||||||
|
While constructing from a deck NNCs connected to inactive cells will be
|
||||||
|
silently ignored. Do observe though that the addNNC() function does not check
|
||||||
|
the arguments and alas there is no guarantee that only active cells are
|
||||||
|
involved.
|
||||||
|
*/
|
||||||
|
|
||||||
class NNC
|
class NNC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NNC() = default;
|
NNC() = default;
|
||||||
|
|
||||||
/// Construct from input deck.
|
/// Construct from input deck.
|
||||||
explicit NNC(const Deck& deck);
|
NNC(const EclipseGrid& grid, const Deck& deck);
|
||||||
|
|
||||||
static NNC serializeObject();
|
static NNC serializeObject();
|
||||||
|
|
||||||
void addNNC(const size_t cell1, const size_t cell2, const double trans);
|
bool addNNC(const size_t cell1, const size_t cell2, const double trans);
|
||||||
const std::vector<NNCdata>& data() const { return m_nnc; }
|
const std::vector<NNCdata>& input() const { return m_input; }
|
||||||
size_t numNNC() const;
|
const std::vector<NNCdata>& edit() const { return m_edit; }
|
||||||
bool hasNNC() const;
|
KeywordLocation input_location(const NNCdata& nnc) const;
|
||||||
|
KeywordLocation edit_location(const NNCdata& nnc) const;
|
||||||
|
|
||||||
|
|
||||||
bool operator==(const NNC& data) const;
|
bool operator==(const NNC& data) const;
|
||||||
|
|
||||||
template<class Serializer>
|
template<class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
{
|
{
|
||||||
serializer.vector(m_nnc);
|
serializer.vector(m_input);
|
||||||
|
serializer.vector(m_edit);
|
||||||
|
serializer(m_nnc_location);
|
||||||
|
serializer(m_edit_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::vector<NNCdata> m_nnc;
|
void load_input(const EclipseGrid& grid, const Deck& deck);
|
||||||
|
void load_edit(const EclipseGrid& grid, const Deck& deck);
|
||||||
|
void add_edit(const NNCdata& edit_node);
|
||||||
|
bool update_nnc(std::size_t global_index1, std::size_t global_index2, double tran_mult);
|
||||||
|
|
||||||
|
std::vector<NNCdata> m_input;
|
||||||
|
std::vector<NNCdata> m_edit;
|
||||||
|
std::optional<KeywordLocation> m_nnc_location;
|
||||||
|
std::optional<KeywordLocation> m_edit_location;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ namespace {
|
|||||||
|
|
||||||
py::list getNNC( const EclipseState& state ) {
|
py::list getNNC( const EclipseState& state ) {
|
||||||
py::list l;
|
py::list l;
|
||||||
for( const auto& x : state.getInputNNC().data() )
|
for( const auto& x : state.getInputNNC().input() )
|
||||||
l.append( py::make_tuple( x.cell1, x.cell2, x.trans ) );
|
l.append( py::make_tuple( x.cell1, x.cell2, x.trans ) );
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -99,8 +99,8 @@ namespace Opm {
|
|||||||
class EclipseIO::Impl {
|
class EclipseIO::Impl {
|
||||||
public:
|
public:
|
||||||
Impl( const EclipseState&, EclipseGrid, const Schedule&, const SummaryConfig& );
|
Impl( const EclipseState&, EclipseGrid, const Schedule&, const SummaryConfig& );
|
||||||
void writeINITFile( const data::Solution& simProps, std::map<std::string, std::vector<int> > int_data, const NNC& nnc) const;
|
void writeINITFile( const data::Solution& simProps, std::map<std::string, std::vector<int> > int_data, const std::vector<NNCdata>& nnc) const;
|
||||||
void writeEGRIDFile( const NNC& nnc );
|
void writeEGRIDFile( const std::vector<NNCdata>& nnc );
|
||||||
bool wantRFTOutput( const int report_step, const bool isSubstep ) const;
|
bool wantRFTOutput( const int report_step, const bool isSubstep ) const;
|
||||||
|
|
||||||
const EclipseState& es;
|
const EclipseState& es;
|
||||||
@ -130,7 +130,7 @@ EclipseIO::Impl::Impl( const EclipseState& eclipseState,
|
|||||||
|
|
||||||
void EclipseIO::Impl::writeINITFile(const data::Solution& simProps,
|
void EclipseIO::Impl::writeINITFile(const data::Solution& simProps,
|
||||||
std::map<std::string, std::vector<int>> int_data,
|
std::map<std::string, std::vector<int>> int_data,
|
||||||
const NNC& nnc) const
|
const std::vector<NNCdata>& nnc) const
|
||||||
{
|
{
|
||||||
EclIO::OutputStream::Init initFile {
|
EclIO::OutputStream::Init initFile {
|
||||||
EclIO::OutputStream::ResultSet { this->outputDir, this->baseName },
|
EclIO::OutputStream::ResultSet { this->outputDir, this->baseName },
|
||||||
@ -142,7 +142,7 @@ void EclipseIO::Impl::writeINITFile(const data::Solution& simP
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EclipseIO::Impl::writeEGRIDFile( const NNC& nnc ) {
|
void EclipseIO::Impl::writeEGRIDFile( const std::vector<NNCdata>& nnc ) {
|
||||||
const auto formatted = this->es.cfg().io().getFMTOUT();
|
const auto formatted = this->es.cfg().io().getFMTOUT();
|
||||||
|
|
||||||
const auto ext = '.'
|
const auto ext = '.'
|
||||||
@ -168,7 +168,7 @@ int_data: Writes key(string) and integers vector to INIT file as eclipse keyword
|
|||||||
- Key: Max 8 chars.
|
- Key: Max 8 chars.
|
||||||
- Wrong input: invalid_argument exception.
|
- Wrong input: invalid_argument exception.
|
||||||
*/
|
*/
|
||||||
void EclipseIO::writeInitial( data::Solution simProps, std::map<std::string, std::vector<int> > int_data, const NNC& nnc) {
|
void EclipseIO::writeInitial( data::Solution simProps, std::map<std::string, std::vector<int> > int_data, const std::vector<NNCdata>& nnc) {
|
||||||
if( !this->impl->output_enabled )
|
if( !this->impl->output_enabled )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -544,14 +544,14 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeNonNeighbourConnections(const ::Opm::NNC& nnc,
|
void writeNonNeighbourConnections(const std::vector<::Opm::NNCdata>& nnc,
|
||||||
const ::Opm::UnitSystem& units,
|
const ::Opm::UnitSystem& units,
|
||||||
::Opm::EclIO::OutputStream::Init& initFile)
|
::Opm::EclIO::OutputStream::Init& initFile)
|
||||||
{
|
{
|
||||||
auto tran = std::vector<double>{};
|
auto tran = std::vector<double>{};
|
||||||
tran.reserve(nnc.numNNC());
|
tran.reserve(nnc.size());
|
||||||
|
|
||||||
for (const auto& nd : nnc.data()) {
|
for (const auto& nd : nnc) {
|
||||||
tran.push_back(nd.trans);
|
tran.push_back(nd.trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,7 +566,7 @@ void Opm::InitIO::write(const ::Opm::EclipseState& es,
|
|||||||
const ::Opm::Schedule& schedule,
|
const ::Opm::Schedule& schedule,
|
||||||
const ::Opm::data::Solution& simProps,
|
const ::Opm::data::Solution& simProps,
|
||||||
std::map<std::string, std::vector<int>> int_data,
|
std::map<std::string, std::vector<int>> int_data,
|
||||||
const ::Opm::NNC& nnc,
|
const std::vector<::Opm::NNCdata>& nnc,
|
||||||
::Opm::EclIO::OutputStream::Init& initFile)
|
::Opm::EclIO::OutputStream::Init& initFile)
|
||||||
{
|
{
|
||||||
const auto& units = es.getUnits();
|
const auto& units = es.getUnits();
|
||||||
@ -587,7 +587,7 @@ void Opm::InitIO::write(const ::Opm::EclipseState& es,
|
|||||||
writeIntegerMaps(std::move(int_data), initFile);
|
writeIntegerMaps(std::move(int_data), initFile);
|
||||||
writeSatFuncScaling(es, units, initFile);
|
writeSatFuncScaling(es, units, initFile);
|
||||||
|
|
||||||
if (nnc.numNNC() > std::size_t{0}) {
|
if (!nnc.empty()) {
|
||||||
writeNonNeighbourConnections(nnc, units, initFile);
|
writeNonNeighbourConnections(nnc, units, initFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,9 +57,8 @@ namespace Opm {
|
|||||||
m_runspec( deck ),
|
m_runspec( deck ),
|
||||||
m_eclipseConfig( deck ),
|
m_eclipseConfig( deck ),
|
||||||
m_deckUnitSystem( deck.getActiveUnitSystem() ),
|
m_deckUnitSystem( deck.getActiveUnitSystem() ),
|
||||||
m_inputNnc( deck ),
|
|
||||||
m_inputEditNnc( deck ),
|
|
||||||
m_inputGrid( deck, nullptr ),
|
m_inputGrid( deck, nullptr ),
|
||||||
|
m_inputNnc( m_inputGrid, deck),
|
||||||
m_gridDims( deck ),
|
m_gridDims( deck ),
|
||||||
field_props( deck, m_runspec.phases(), m_inputGrid, m_tables),
|
field_props( deck, m_runspec.phases(), m_inputGrid, m_tables),
|
||||||
m_simulationConfig( m_eclipseConfig.getInitConfig().restartRequested(), deck, field_props),
|
m_simulationConfig( m_eclipseConfig.getInitConfig().restartRequested(), deck, field_props),
|
||||||
@ -177,16 +176,9 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool EclipseState::hasInputNNC() const {
|
bool EclipseState::hasInputNNC() const {
|
||||||
return m_inputNnc.hasNNC();
|
return !m_inputNnc.input().empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
const EDITNNC& EclipseState::getInputEDITNNC() const {
|
|
||||||
return m_inputEditNnc;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EclipseState::hasInputEDITNNC() const {
|
|
||||||
return !m_inputEditNnc.empty();
|
|
||||||
}
|
|
||||||
std::string EclipseState::getTitle() const {
|
std::string EclipseState::getTitle() const {
|
||||||
return m_title;
|
return m_title;
|
||||||
}
|
}
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
|
|
||||||
#include <array>
|
|
||||||
#include <sstream>
|
|
||||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
|
||||||
#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/EclipseState/Grid/EclipseGrid.hpp>
|
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/GridDims.hpp>
|
|
||||||
#include <opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp>
|
|
||||||
#include <opm/parser/eclipse/Parser/ParserKeywords/E.hpp>
|
|
||||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Opm
|
|
||||||
{
|
|
||||||
|
|
||||||
bool isNeighbor(const std::array<size_t, 3>& ijk1, const std::array<size_t, 3>& ijk2)
|
|
||||||
{
|
|
||||||
if ( (ijk1[0] + 1) == ijk2[0] || (ijk1[0] - 1) == ijk2[0] )
|
|
||||||
{
|
|
||||||
return ijk1[1] == ijk2[1] && ijk1[2] == ijk2[2];
|
|
||||||
}
|
|
||||||
if ( (ijk1[1] + 1) == ijk2[1] || (ijk1[1] - 1) == ijk2[1] )
|
|
||||||
{
|
|
||||||
return ijk1[0] == ijk2[0] && ijk1[2] == ijk2[2];
|
|
||||||
}
|
|
||||||
if( (ijk1[2] + 1) == ijk2[2] || (ijk1[2] - 1) == ijk2[2] )
|
|
||||||
{
|
|
||||||
return ijk1[1] == ijk2[1] && ijk1[1] == ijk2[1];
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
|
||||||
editNncs.reserve(editNncs.size()+nnc.size());
|
|
||||||
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).get<double>(0);
|
|
||||||
using std::abs;
|
|
||||||
if ( !isNeighbor(ijk1, ijk2) )
|
|
||||||
{
|
|
||||||
editNncs.emplace_back(global_index1, global_index2, trans);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::ostringstream sstr;
|
|
||||||
sstr << "Cannot edit neighboring connection from " << global_index1 <<" to "<<
|
|
||||||
global_index2<< " with EDITNNC";
|
|
||||||
Opm::OpmLog::warning(sstr.str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EDITNNC::EDITNNC(const Deck& deck)
|
|
||||||
{
|
|
||||||
GridDims gridDims(deck);
|
|
||||||
const auto& tmpEditNncs = deck.getKeywordList<ParserKeywords::EDITNNC>();
|
|
||||||
readEditNncs(tmpEditNncs, m_editnnc, gridDims);
|
|
||||||
auto compare = [](const NNCdata& d1, const NNCdata& d2)
|
|
||||||
{ return d1.cell1 < d2.cell1 ||
|
|
||||||
( d1.cell1 == d2.cell1 && d1.cell2 < d2.cell2 );};
|
|
||||||
std::sort(m_editnnc.begin(), m_editnnc.end(), compare);
|
|
||||||
}
|
|
||||||
|
|
||||||
EDITNNC EDITNNC::serializeObject()
|
|
||||||
{
|
|
||||||
EDITNNC result;
|
|
||||||
result.m_editnnc = {{1,2,1.0},{2,3,2.0}};
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t EDITNNC::size() const {
|
|
||||||
return(m_editnnc.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EDITNNC::empty() const {
|
|
||||||
return m_editnnc.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EDITNNC::operator==(const EDITNNC& data) const {
|
|
||||||
return m_editnnc == data.m_editnnc;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Opm
|
|
@ -1558,7 +1558,7 @@ std::vector<double> EclipseGrid::createDVector(const std::array<int,3>& dims, st
|
|||||||
return m_zcorn;
|
return m_zcorn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EclipseGrid::save(const std::string& filename, bool formatted, const Opm::NNC& nnc, const Opm::UnitSystem& units) const {
|
void EclipseGrid::save(const std::string& filename, bool formatted, const std::vector<Opm::NNCdata>& nnc, const Opm::UnitSystem& units) const {
|
||||||
|
|
||||||
Opm::UnitSystem::UnitType unitSystemType = units.getType();
|
Opm::UnitSystem::UnitType unitSystemType = units.getType();
|
||||||
const auto length = ::Opm::UnitSystem::measure::length;
|
const auto length = ::Opm::UnitSystem::measure::length;
|
||||||
@ -1601,7 +1601,7 @@ std::vector<double> EclipseGrid::createDVector(const std::array<int,3>& dims, st
|
|||||||
std::vector<int> nnc1;
|
std::vector<int> nnc1;
|
||||||
std::vector<int> nnc2;
|
std::vector<int> nnc2;
|
||||||
|
|
||||||
for (const NNCdata& n : nnc.data() ) {
|
for (const NNCdata& n : nnc ) {
|
||||||
nnc1.push_back(n.cell1 + 1);
|
nnc1.push_back(n.cell1 + 1);
|
||||||
nnc2.push_back(n.cell2 + 1);
|
nnc2.push_back(n.cell2 + 1);
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2015 IRIS
|
Copyright 2015 IRIS
|
||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify
|
OPM is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
OPM is distributed in the hope that it will be useful,
|
OPM is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
@ -23,64 +23,218 @@
|
|||||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.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/EclipseState/Grid/NNC.hpp>
|
||||||
|
#include <opm/parser/eclipse/Parser/ParserKeywords/E.hpp>
|
||||||
#include <opm/parser/eclipse/Parser/ParserKeywords/N.hpp>
|
#include <opm/parser/eclipse/Parser/ParserKeywords/N.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Opm
|
namespace Opm
|
||||||
{
|
{
|
||||||
NNC::NNC(const Deck& deck) {
|
|
||||||
GridDims gridDims(deck);
|
namespace {
|
||||||
const auto& nncs = deck.getKeywordList<ParserKeywords::NNC>();
|
|
||||||
for (size_t idx_nnc = 0; idx_nnc<nncs.size(); ++idx_nnc) {
|
std::optional<std::size_t> global_index(const EclipseGrid& grid, const DeckRecord& record, std::size_t item_offset) {
|
||||||
const auto& nnc = *nncs[idx_nnc];
|
std::size_t i = static_cast<size_t>(record.getItem(0 + item_offset).get< int >(0)-1);
|
||||||
for (size_t i = 0; i < nnc.size(); ++i) {
|
std::size_t j = static_cast<size_t>(record.getItem(1 + item_offset).get< int >(0)-1);
|
||||||
std::array<size_t, 3> ijk1;
|
std::size_t k = static_cast<size_t>(record.getItem(2 + item_offset).get< int >(0)-1);
|
||||||
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);
|
if (i >= grid.getNX())
|
||||||
ijk1[2] = static_cast<size_t>(nnc.getRecord(i).getItem(2).get< int >(0)-1);
|
return {};
|
||||||
size_t global_index1 = gridDims.getGlobalIndex(ijk1[0],ijk1[1],ijk1[2]);
|
|
||||||
|
if (j >= grid.getNY())
|
||||||
std::array<size_t, 3> ijk2;
|
return {};
|
||||||
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);
|
if (k >= grid.getNZ())
|
||||||
ijk2[2] = static_cast<size_t>(nnc.getRecord(i).getItem(5).get< int >(0)-1);
|
return {};
|
||||||
size_t global_index2 = gridDims.getGlobalIndex(ijk2[0],ijk2[1],ijk2[2]);
|
|
||||||
|
if (!grid.cellActive(i,j,k))
|
||||||
const double trans = nnc.getRecord(i).getItem(6).getSIDouble(0);
|
return {};
|
||||||
|
|
||||||
addNNC(global_index1,global_index2,trans);
|
return grid.getGlobalIndex(i,j,k);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::optional<std::pair<std::size_t, std::size_t>> make_index_pair(const EclipseGrid& grid, const DeckRecord& record) {
|
||||||
|
auto g1 = global_index(grid, record, 0);
|
||||||
|
auto g2 = global_index(grid, record, 3);
|
||||||
|
if (!g1)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (!g2)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (*g1 < *g2)
|
||||||
|
return std::make_pair(*g1, *g2);
|
||||||
|
else
|
||||||
|
return std::make_pair(*g2, *g1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_neighbor(const EclipseGrid& grid, std::size_t g1, std::size_t g2) {
|
||||||
|
auto diff = g2 - g1;
|
||||||
|
if (diff == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (diff == 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (diff == grid.getNX())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (diff == grid.getNY())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NNC::NNC(const EclipseGrid& grid, const Deck& deck) {
|
||||||
|
this->load_input(grid, deck);
|
||||||
|
this->load_edit(grid, deck);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NNC::load_input(const EclipseGrid& grid, const Deck& deck) {
|
||||||
|
for (const auto& keyword_ptr : deck.getKeywordList<ParserKeywords::NNC>()) {
|
||||||
|
for (const auto& record : *keyword_ptr) {
|
||||||
|
auto index_pair = make_index_pair(grid, record);
|
||||||
|
if (!index_pair)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto [g1, g2] = index_pair.value();
|
||||||
|
double trans = record.getItem(6).getSIDouble(0);
|
||||||
|
this->m_input.emplace_back(g1, g2, trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this->m_nnc_location)
|
||||||
|
this->m_nnc_location = keyword_ptr->location();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(this->m_input.begin(), this->m_input.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NNC::load_edit(const EclipseGrid& grid, const Deck& deck) {
|
||||||
|
std::vector<NNCdata> nnc_edit;
|
||||||
|
for (const auto& keyword_ptr : deck.getKeywordList<ParserKeywords::EDITNNC>()) {
|
||||||
|
for (const auto& record : *keyword_ptr) {
|
||||||
|
double tran_mult = record.getItem(6).get<double>(0);
|
||||||
|
if (tran_mult == 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto index_pair = make_index_pair(grid, record);
|
||||||
|
if (!index_pair)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto [g1, g2] = index_pair.value();
|
||||||
|
if (is_neighbor(grid, g1, g2))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nnc_edit.emplace_back( g1, g2, tran_mult);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->m_edit_location)
|
||||||
|
this->m_edit_location = keyword_ptr->location();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(nnc_edit.begin(), nnc_edit.end());
|
||||||
|
|
||||||
|
auto current_input = this->m_input.begin();
|
||||||
|
for (const auto& current_edit : nnc_edit) {
|
||||||
|
if (current_input == this->m_input.end()) {
|
||||||
|
this->add_edit(current_edit);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_input->cell1 != current_edit.cell1 || current_input->cell2 != current_edit.cell2) {
|
||||||
|
current_input = std::lower_bound(this->m_input.begin(),
|
||||||
|
this->m_input.end(),
|
||||||
|
NNCdata(current_edit.cell1, current_edit.cell2, 0));
|
||||||
|
if (current_input == this->m_input.end()) {
|
||||||
|
this->add_edit(current_edit);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool edit_processed = false;
|
||||||
|
while (current_input != this->m_input.end()
|
||||||
|
&& current_input->cell1 == current_edit.cell1
|
||||||
|
&& current_input->cell2 == current_edit.cell2)
|
||||||
|
{
|
||||||
|
current_input->trans *= current_edit.trans;
|
||||||
|
++current_input;
|
||||||
|
edit_processed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!edit_processed)
|
||||||
|
this->add_edit(current_edit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NNC NNC::serializeObject()
|
NNC NNC::serializeObject()
|
||||||
{
|
{
|
||||||
NNC result;
|
NNC result;
|
||||||
result.m_nnc = {{1,2,1.0},{2,3,2.0}};
|
result.m_input= {{1,2,1.0},{2,3,2.0}};
|
||||||
|
result.m_edit= {{1,2,1.0},{2,3,2.0}};
|
||||||
|
result.m_nnc_location = {"NNC?", "File", 123};
|
||||||
|
result.m_edit_location = {"EDITNNC?", "File", 123};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NNC::addNNC(const size_t cell1, const size_t cell2, const double trans) {
|
bool NNC::addNNC(const size_t cell1, const size_t cell2, const double trans) {
|
||||||
NNCdata tmp;
|
if (cell1 > cell2)
|
||||||
tmp.cell1 = cell1;
|
return this->addNNC(cell2, cell1, trans);
|
||||||
tmp.cell2 = cell2;
|
|
||||||
tmp.trans = trans;
|
|
||||||
m_nnc.push_back(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t NNC::numNNC() const {
|
auto nnc = NNCdata(cell1, cell2, trans);
|
||||||
return(m_nnc.size());
|
auto insert_iter = std::lower_bound(this->m_input.begin(), this->m_input.end(), nnc);
|
||||||
}
|
this->m_input.insert( insert_iter, nnc);
|
||||||
|
return true;
|
||||||
bool NNC::hasNNC() const {
|
|
||||||
return m_nnc.size()>0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NNC::operator==(const NNC& data) const {
|
bool NNC::operator==(const NNC& data) const {
|
||||||
return m_nnc == data.m_nnc;
|
return m_input == data.m_input &&
|
||||||
|
m_edit == data.m_edit &&
|
||||||
|
m_edit_location == data.m_edit_location &&
|
||||||
|
m_nnc_location == data.m_nnc_location;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NNC::add_edit(const NNCdata& edit_node) {
|
||||||
|
if (!this->m_edit.empty()) {
|
||||||
|
auto& back = this->m_edit.back();
|
||||||
|
if (back.cell1 == edit_node.cell1 && back.cell2 == edit_node.cell2) {
|
||||||
|
back.trans *= edit_node.trans;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_edit.push_back(edit_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
In principle we can have multiple NNC keywords, and to provide a good error
|
||||||
|
message we should be able to return the location of the offending NNC. That
|
||||||
|
will require some bookkeeping of which NNC originated in which NNC
|
||||||
|
keyword/location. For now we just return the location of the first NNC
|
||||||
|
keyword, but we should be ready for a more elaborate implementation without
|
||||||
|
any API change.
|
||||||
|
*/
|
||||||
|
KeywordLocation NNC::input_location([[maybe_unused]] const NNCdata& nnc) const {
|
||||||
|
if (this->m_nnc_location)
|
||||||
|
return *this->m_nnc_location;
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KeywordLocation NNC::edit_location([[maybe_unused]] const NNCdata& nnc) const {
|
||||||
|
if (this->m_edit_location)
|
||||||
|
return *this->m_edit_location;
|
||||||
|
else
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
@ -1686,7 +1686,7 @@ BOOST_AUTO_TEST_CASE(SAVE_FIELD_UNITS) {
|
|||||||
|
|
||||||
const auto& grid1 = es.getInputGrid();
|
const auto& grid1 = es.getInputGrid();
|
||||||
|
|
||||||
Opm::NNC nnc( deck );
|
Opm::NNC nnc(grid1, deck);
|
||||||
bool formatted = false;
|
bool formatted = false;
|
||||||
|
|
||||||
time_t timer;
|
time_t timer;
|
||||||
@ -1702,7 +1702,7 @@ BOOST_AUTO_TEST_CASE(SAVE_FIELD_UNITS) {
|
|||||||
Opm::filesystem::create_directory(testDir);
|
Opm::filesystem::create_directory(testDir);
|
||||||
|
|
||||||
std::string fileName = testDir + "/" + "TMP.EGRID";
|
std::string fileName = testDir + "/" + "TMP.EGRID";
|
||||||
grid1.save(fileName, formatted, nnc, units);
|
grid1.save(fileName, formatted, nnc.input(), units);
|
||||||
|
|
||||||
Opm::EclIO::EclFile file1(fileName);
|
Opm::EclIO::EclFile file1(fileName);
|
||||||
|
|
||||||
@ -1757,13 +1757,13 @@ BOOST_AUTO_TEST_CASE(SAVE_FIELD_UNITS) {
|
|||||||
|
|
||||||
Opm::EclipseState es2(deck2);
|
Opm::EclipseState es2(deck2);
|
||||||
Opm::UnitSystem units2 = es.getDeckUnitSystem();
|
Opm::UnitSystem units2 = es.getDeckUnitSystem();
|
||||||
Opm::NNC nnc2( deck2 );
|
|
||||||
|
|
||||||
const auto& grid2 = es2.getInputGrid();
|
const auto& grid2 = es2.getInputGrid();
|
||||||
|
Opm::NNC nnc2(grid2, deck2 );
|
||||||
|
|
||||||
|
|
||||||
std::string fileName2 = testDir + "/" + "TMP2.FEGRID";
|
std::string fileName2 = testDir + "/" + "TMP2.FEGRID";
|
||||||
|
|
||||||
grid2.save(fileName2, true, nnc2, units);
|
grid2.save(fileName2, true, nnc2.input(), units);
|
||||||
|
|
||||||
Opm::EclIO::EclFile file2(fileName2);
|
Opm::EclIO::EclFile file2(fileName2);
|
||||||
|
|
||||||
@ -1783,13 +1783,13 @@ BOOST_AUTO_TEST_CASE(SAVE_FIELD_UNITS) {
|
|||||||
|
|
||||||
Opm::EclipseState es3(deck3);
|
Opm::EclipseState es3(deck3);
|
||||||
Opm::UnitSystem units3 = es.getDeckUnitSystem();
|
Opm::UnitSystem units3 = es.getDeckUnitSystem();
|
||||||
Opm::NNC nnc3( deck3 );
|
|
||||||
|
|
||||||
const auto& grid3 = es3.getInputGrid();
|
const auto& grid3 = es3.getInputGrid();
|
||||||
|
Opm::NNC nnc3(grid3, deck3);
|
||||||
|
|
||||||
|
|
||||||
std::string fileName3 = testDir + "/" + "TMP3.FEGRID";
|
std::string fileName3 = testDir + "/" + "TMP3.FEGRID";
|
||||||
|
|
||||||
grid3.save(fileName3, true, nnc3, units3);
|
grid3.save(fileName3, true, nnc3.input(), units3);
|
||||||
|
|
||||||
Opm::EclIO::EclFile file3(fileName3);
|
Opm::EclIO::EclFile file3(fileName3);
|
||||||
|
|
||||||
@ -1878,7 +1878,7 @@ BOOST_AUTO_TEST_CASE(SAVE_METRIC_UNITS) {
|
|||||||
const auto length = ::Opm::UnitSystem::measure::length;
|
const auto length = ::Opm::UnitSystem::measure::length;
|
||||||
|
|
||||||
const auto& grid1 = es1.getInputGrid();
|
const auto& grid1 = es1.getInputGrid();
|
||||||
Opm::NNC nnc( deck1 );
|
Opm::NNC nnc(grid1, deck1);
|
||||||
|
|
||||||
bool formatted = true;
|
bool formatted = true;
|
||||||
|
|
||||||
@ -1895,7 +1895,7 @@ BOOST_AUTO_TEST_CASE(SAVE_METRIC_UNITS) {
|
|||||||
Opm::filesystem::create_directory(testDir);
|
Opm::filesystem::create_directory(testDir);
|
||||||
|
|
||||||
std::string fileName = testDir + "/" + "TMP.FEGRID";
|
std::string fileName = testDir + "/" + "TMP.FEGRID";
|
||||||
grid1.save(fileName, formatted, nnc, units1);
|
grid1.save(fileName, formatted, nnc.input(), units1);
|
||||||
|
|
||||||
Opm::EclIO::EclFile file1(fileName);
|
Opm::EclIO::EclFile file1(fileName);
|
||||||
|
|
||||||
@ -1949,7 +1949,7 @@ BOOST_AUTO_TEST_CASE(SAVE_METRIC_UNITS) {
|
|||||||
BOOST_CHECK( file1.hasKey("NNCHEAD"));
|
BOOST_CHECK( file1.hasKey("NNCHEAD"));
|
||||||
const std::vector<int> nnchead = file1.get<int>("NNCHEAD");
|
const std::vector<int> nnchead = file1.get<int>("NNCHEAD");
|
||||||
|
|
||||||
BOOST_CHECK( nnchead[0] == static_cast<int>(nnc.numNNC()) );
|
BOOST_CHECK( nnchead[0] == static_cast<int>(nnc.input().size()) );
|
||||||
|
|
||||||
std::vector<int> ref_nnc1 = { 6, 7, 8 };
|
std::vector<int> ref_nnc1 = { 6, 7, 8 };
|
||||||
std::vector<int> ref_nnc2 = { 26, 27, 28 };
|
std::vector<int> ref_nnc2 = { 26, 27, 28 };
|
||||||
@ -1981,7 +1981,7 @@ BOOST_AUTO_TEST_CASE(SAVE_METRIC_UNITS) {
|
|||||||
|
|
||||||
std::string fileName2 = testDir + "/" + "TMP2.FEGRID";
|
std::string fileName2 = testDir + "/" + "TMP2.FEGRID";
|
||||||
|
|
||||||
grid2.save(fileName2, true, nnc, units2);
|
grid2.save(fileName2, true, nnc.input(), units2);
|
||||||
|
|
||||||
Opm::EclIO::EclFile file2(fileName2);
|
Opm::EclIO::EclFile file2(fileName2);
|
||||||
|
|
||||||
@ -2588,16 +2588,16 @@ BOOST_AUTO_TEST_CASE(TEST_GDFILE_2) {
|
|||||||
Opm::UnitSystem units1a = es1a.getDeckUnitSystem();
|
Opm::UnitSystem units1a = es1a.getDeckUnitSystem();
|
||||||
|
|
||||||
const auto& grid1a = es1a.getInputGrid();
|
const auto& grid1a = es1a.getInputGrid();
|
||||||
Opm::NNC nnc( deck1a );
|
Opm::NNC nnc(grid1a, deck1a);
|
||||||
|
|
||||||
grid1a.save("BAD_CP_M.EGRID", false, nnc, units1a);
|
grid1a.save("BAD_CP_M.EGRID", false, nnc.input(), units1a);
|
||||||
|
|
||||||
auto deck1b = parser.parseString( deckData1b) ;
|
auto deck1b = parser.parseString( deckData1b) ;
|
||||||
Opm::EclipseState es1b( deck1b );
|
Opm::EclipseState es1b( deck1b );
|
||||||
Opm::UnitSystem units1b = es1b.getDeckUnitSystem();
|
Opm::UnitSystem units1b = es1b.getDeckUnitSystem();
|
||||||
const auto& grid1b = es1b.getInputGrid();
|
const auto& grid1b = es1b.getInputGrid();
|
||||||
|
|
||||||
grid1b.save("BAD_CP_F.EGRID", false, nnc, units1b);
|
grid1b.save("BAD_CP_F.EGRID", false, nnc.input(), units1b);
|
||||||
|
|
||||||
auto deck1 = parser.parseString( deckData1) ;
|
auto deck1 = parser.parseString( deckData1) ;
|
||||||
Opm::EclipseGrid grid1( deck1);
|
Opm::EclipseGrid grid1( deck1);
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
RUNSPEC
|
|
||||||
|
|
||||||
OIL
|
|
||||||
GAS
|
|
||||||
WATER
|
|
||||||
|
|
||||||
|
|
||||||
DIMENS
|
|
||||||
10 10 1 /
|
|
||||||
|
|
||||||
GRID
|
|
||||||
|
|
||||||
DXV
|
|
||||||
10*1000.0
|
|
||||||
/
|
|
||||||
|
|
||||||
DYV
|
|
||||||
10*1000.0
|
|
||||||
/
|
|
||||||
|
|
||||||
DZ
|
|
||||||
100*20.0
|
|
||||||
/
|
|
||||||
|
|
||||||
TOPS
|
|
||||||
100*10
|
|
||||||
/
|
|
||||||
|
|
||||||
PORO
|
|
||||||
100*0.15 /
|
|
||||||
|
|
||||||
EDIT
|
|
||||||
|
|
||||||
EDITNNC
|
|
||||||
3 1 1 1 1 1 0.1 /
|
|
||||||
1 1 1 1 2 1 0.01 /
|
|
||||||
2 1 1 2 3 1 0.1 /
|
|
||||||
/
|
|
||||||
|
|
||||||
EDITNNC
|
|
||||||
1 1 1 2 1 1 0.1 /
|
|
||||||
2 1 1 2 3 1 0.1 /
|
|
||||||
/
|
|
@ -1,40 +0,0 @@
|
|||||||
RUNSPEC
|
|
||||||
|
|
||||||
OIL
|
|
||||||
GAS
|
|
||||||
WATER
|
|
||||||
|
|
||||||
|
|
||||||
DIMENS
|
|
||||||
10 10 1 /
|
|
||||||
|
|
||||||
GRID
|
|
||||||
|
|
||||||
DXV
|
|
||||||
10*1000.0
|
|
||||||
/
|
|
||||||
|
|
||||||
DYV
|
|
||||||
10*1000.0
|
|
||||||
/
|
|
||||||
|
|
||||||
DZ
|
|
||||||
100*20.0
|
|
||||||
/
|
|
||||||
|
|
||||||
TOPS
|
|
||||||
100*10
|
|
||||||
/
|
|
||||||
|
|
||||||
PORO
|
|
||||||
100*0.15 /
|
|
||||||
|
|
||||||
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 /
|
|
||||||
/
|
|
@ -1,30 +0,0 @@
|
|||||||
RUNSPEC
|
|
||||||
|
|
||||||
OIL
|
|
||||||
GAS
|
|
||||||
WATER
|
|
||||||
|
|
||||||
|
|
||||||
DIMENS
|
|
||||||
10 10 1 /
|
|
||||||
|
|
||||||
GRID
|
|
||||||
|
|
||||||
DXV
|
|
||||||
10*1000.0
|
|
||||||
/
|
|
||||||
|
|
||||||
DYV
|
|
||||||
10*1000.0
|
|
||||||
/
|
|
||||||
|
|
||||||
DZ
|
|
||||||
100*20.0
|
|
||||||
/
|
|
||||||
|
|
||||||
TOPS
|
|
||||||
100*10
|
|
||||||
/
|
|
||||||
|
|
||||||
PORO
|
|
||||||
100*0.15 /
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2015 IRIS
|
|
||||||
Copyright 2018 Equinor AS
|
|
||||||
|
|
||||||
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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp>
|
|
||||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
|
||||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
|
||||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
|
||||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
|
||||||
|
|
||||||
#define BOOST_TEST_MODULE NNCTests
|
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
|
|
||||||
using namespace Opm;
|
|
||||||
|
|
||||||
inline std::string pathprefix() {
|
|
||||||
return boost::unit_test::framework::master_test_suite().argv[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(noNNC)
|
|
||||||
{
|
|
||||||
Parser parser;
|
|
||||||
auto deck = parser.parseFile(pathprefix() + "NNC/noNNC.DATA");
|
|
||||||
EclipseState eclipseState(deck);
|
|
||||||
const auto& editnnc = eclipseState.getInputEDITNNC();
|
|
||||||
BOOST_CHECK(!eclipseState.hasInputEDITNNC());
|
|
||||||
BOOST_CHECK(editnnc.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(readDeck)
|
|
||||||
{
|
|
||||||
Parser parser;
|
|
||||||
auto deck = parser.parseFile(pathprefix() + "EDITNNC/EDITNNC.DATA");
|
|
||||||
EclipseState eclipseState(deck);
|
|
||||||
const auto& editnnc = eclipseState.getInputEDITNNC();
|
|
||||||
BOOST_CHECK(!editnnc.empty());
|
|
||||||
const std::vector<NNCdata>& data = editnnc.data();
|
|
||||||
|
|
||||||
// test the NNCs in nnc.DATA
|
|
||||||
BOOST_CHECK_EQUAL(editnnc.size(), 3); //neighbouring connections in EDITNNC are ignored
|
|
||||||
BOOST_CHECK_EQUAL(data[0].cell1, 1);
|
|
||||||
BOOST_CHECK_EQUAL(data[0].cell2, 21);
|
|
||||||
BOOST_CHECK_EQUAL(data[0].trans, 0.1);
|
|
||||||
BOOST_CHECK_EQUAL(data[1].cell1, 1);
|
|
||||||
BOOST_CHECK_EQUAL(data[1].cell2, 21);
|
|
||||||
BOOST_CHECK_EQUAL(data[1].trans, 0.1);
|
|
||||||
BOOST_CHECK_EQUAL(data[2].cell1, 2);
|
|
||||||
BOOST_CHECK_EQUAL(data[2].cell2, 0);
|
|
||||||
BOOST_CHECK_EQUAL(data[2].trans, 0.1);
|
|
||||||
|
|
||||||
}
|
|
@ -20,7 +20,7 @@
|
|||||||
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
||||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/parser/eclipse/EclipseState/Grid/GridDims.hpp>
|
||||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||||
|
|
||||||
@ -30,67 +30,330 @@
|
|||||||
|
|
||||||
using namespace Opm;
|
using namespace Opm;
|
||||||
|
|
||||||
inline std::string pathprefix() {
|
|
||||||
return boost::unit_test::framework::master_test_suite().argv[1];
|
const std::string no_nnc_input = R"(
|
||||||
|
RUNSPEC
|
||||||
|
|
||||||
|
OIL
|
||||||
|
GAS
|
||||||
|
WATER
|
||||||
|
|
||||||
|
|
||||||
|
DIMENS
|
||||||
|
10 10 1 /
|
||||||
|
|
||||||
|
GRID
|
||||||
|
|
||||||
|
DXV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DYV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DZ
|
||||||
|
100*20.0
|
||||||
|
/
|
||||||
|
|
||||||
|
TOPS
|
||||||
|
100*10
|
||||||
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
100*0.15 /
|
||||||
|
)";
|
||||||
|
|
||||||
|
const std::string actnum = R"(
|
||||||
|
RUNSPEC
|
||||||
|
|
||||||
|
OIL
|
||||||
|
GAS
|
||||||
|
WATER
|
||||||
|
|
||||||
|
|
||||||
|
DIMENS
|
||||||
|
10 10 1 /
|
||||||
|
|
||||||
|
GRID
|
||||||
|
|
||||||
|
DXV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DYV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DZ
|
||||||
|
100*20.0
|
||||||
|
/
|
||||||
|
|
||||||
|
TOPS
|
||||||
|
100*10
|
||||||
|
/
|
||||||
|
|
||||||
|
ACTNUM
|
||||||
|
10*0 90*1
|
||||||
|
/
|
||||||
|
|
||||||
|
NNC
|
||||||
|
1 1 1 1 3 1 0.5 / -- Inactive cell
|
||||||
|
3 1 1 3 3 1 0.5 / -- Inactive cell
|
||||||
|
2 2 1 3 3 1 1.0 / -- Valid
|
||||||
|
100 100 100 200 200 200 1.0 / -- Very invalid
|
||||||
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
100*0.15 /
|
||||||
|
|
||||||
|
EDIT
|
||||||
|
|
||||||
|
EDITNNC
|
||||||
|
5 1 1 1 5 3 0.5 / -- Inactive cell
|
||||||
|
2 2 1 3 3 1 0.5 / -- Valid - coupled to NNC
|
||||||
|
4 4 1 5 5 1 2.0 / -- Valid
|
||||||
|
-1 4 4 -1 7 7 1.0 / -- Very invalid
|
||||||
|
/
|
||||||
|
|
||||||
|
)";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const std::string nnc_input = R"(
|
||||||
|
RUNSPEC
|
||||||
|
|
||||||
|
OIL
|
||||||
|
GAS
|
||||||
|
WATER
|
||||||
|
|
||||||
|
|
||||||
|
DIMENS
|
||||||
|
10 10 1 /
|
||||||
|
|
||||||
|
GRID
|
||||||
|
|
||||||
|
DXV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DYV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DZ
|
||||||
|
100*20.0
|
||||||
|
/
|
||||||
|
|
||||||
|
TOPS
|
||||||
|
100*10
|
||||||
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
100*0.15 /
|
||||||
|
|
||||||
|
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 /
|
||||||
|
/
|
||||||
|
)";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const std::string editnnc_input = R"(
|
||||||
|
RUNSPEC
|
||||||
|
|
||||||
|
OIL
|
||||||
|
GAS
|
||||||
|
WATER
|
||||||
|
|
||||||
|
|
||||||
|
DIMENS
|
||||||
|
10 10 1 /
|
||||||
|
|
||||||
|
GRID
|
||||||
|
|
||||||
|
NNC
|
||||||
|
7 1 1 3 1 1 0.1 /
|
||||||
|
3 1 1 5 1 1 0.1 /
|
||||||
|
/
|
||||||
|
|
||||||
|
|
||||||
|
DXV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DYV
|
||||||
|
10*1000.0
|
||||||
|
/
|
||||||
|
|
||||||
|
DZ
|
||||||
|
100*20.0
|
||||||
|
/
|
||||||
|
|
||||||
|
TOPS
|
||||||
|
100*10
|
||||||
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
100*0.15 /
|
||||||
|
|
||||||
|
EDIT
|
||||||
|
|
||||||
|
|
||||||
|
EDITNNC
|
||||||
|
5 1 1 3 1 1 2.0 /
|
||||||
|
3 1 1 1 1 1 0.1 /
|
||||||
|
1 1 1 1 2 1 0.01 / -- This is ignored because the two cells are ijk neighbours
|
||||||
|
2 1 1 2 3 1 0.2 /
|
||||||
|
/
|
||||||
|
|
||||||
|
EDITNNC
|
||||||
|
1 1 1 2 1 1 0.1 / -- Ignored
|
||||||
|
2 1 1 2 3 1 0.3 /
|
||||||
|
/
|
||||||
|
)";
|
||||||
|
|
||||||
|
|
||||||
|
std::optional<NNCdata> find_nnc(const std::vector<NNCdata>& v, std::size_t c1, std::size_t c2) {
|
||||||
|
if (c1 > c2)
|
||||||
|
return find_nnc(v, c2, c1);
|
||||||
|
|
||||||
|
auto iter = std::find_if(v.begin(), v.end(), [c1,c2](const NNCdata& nnc) { return nnc.cell1 == c1 && nnc.cell2 == c2; });
|
||||||
|
if (iter != v.end())
|
||||||
|
return *iter;
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void check_edit_nnc(const std::vector<NNCdata>& v, std::size_t c1, std::size_t c2, double t) {
|
||||||
|
const auto& nnc = find_nnc(v, c1, c2);
|
||||||
|
BOOST_REQUIRE(nnc.has_value());
|
||||||
|
BOOST_CHECK_CLOSE(nnc->trans, t , 1e-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_nnc(const std::vector<NNCdata>& v, std::size_t c1, std::size_t c2, double t) {
|
||||||
|
check_edit_nnc(v, c1, c2, t*Opm::Metric::Transmissibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_nnc(const std::vector<NNCdata>& v, std::size_t c1, std::size_t c2) {
|
||||||
|
const auto& nnc = find_nnc(v, c1, c2);
|
||||||
|
return nnc.has_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_order(const std::vector<NNCdata>& d) {
|
||||||
|
for (const auto& nnc : d)
|
||||||
|
BOOST_CHECK(nnc.cell1 <= nnc.cell2);
|
||||||
|
|
||||||
|
if (d.size() <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (std::size_t index=1; index < d.size(); index++) {
|
||||||
|
const auto& nnc1 = d[index - 1];
|
||||||
|
const auto& nnc2 = d[index];
|
||||||
|
|
||||||
|
if (nnc1 < nnc2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(nnc1.cell1, nnc2.cell1);
|
||||||
|
BOOST_CHECK_EQUAL(nnc1.cell2, nnc2.cell2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void check_order(const NNC& nnc) {
|
||||||
|
check_order(nnc.input());
|
||||||
|
check_order(nnc.edit());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(noNNC)
|
BOOST_AUTO_TEST_CASE(noNNC)
|
||||||
{
|
{
|
||||||
Parser parser;
|
Parser parser;
|
||||||
auto deck = parser.parseFile(pathprefix() + "NNC/noNNC.DATA");
|
auto deck = parser.parseString(no_nnc_input);
|
||||||
EclipseState eclipseState(deck);
|
EclipseState eclipseState(deck);
|
||||||
const auto& nnc = eclipseState.getInputNNC();
|
const auto& nnc = eclipseState.getInputNNC();
|
||||||
|
check_order(nnc);
|
||||||
BOOST_CHECK(!eclipseState.hasInputNNC());
|
BOOST_CHECK(!eclipseState.hasInputNNC());
|
||||||
BOOST_CHECK(!nnc.hasNNC());
|
BOOST_CHECK(nnc.input().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(readDeck)
|
BOOST_AUTO_TEST_CASE(readDeck)
|
||||||
{
|
{
|
||||||
Parser parser;
|
Parser parser;
|
||||||
auto deck = parser.parseFile(pathprefix() + "NNC/NNC.DATA");
|
auto deck = parser.parseString(nnc_input);
|
||||||
EclipseState eclipseState(deck);
|
EclipseState eclipseState(deck);
|
||||||
|
const auto& grid = eclipseState.getInputGrid();
|
||||||
const auto& nnc = eclipseState.getInputNNC();
|
const auto& nnc = eclipseState.getInputNNC();
|
||||||
BOOST_CHECK(nnc.hasNNC());
|
check_order(nnc);
|
||||||
const std::vector<NNCdata>& nncdata = nnc.data();
|
BOOST_CHECK(!nnc.input().empty());
|
||||||
|
const std::vector<NNCdata>& nncdata = nnc.input();
|
||||||
|
|
||||||
// test the NNCs in nnc.DATA
|
// test the NNCs in nnc.DATA
|
||||||
BOOST_CHECK_EQUAL(nnc.numNNC(), 4);
|
BOOST_CHECK_EQUAL(nncdata.size(), 4);
|
||||||
BOOST_CHECK_EQUAL(nncdata[0].cell1, 0);
|
check_nnc(nncdata, grid.getGlobalIndex(0,0,0), grid.getGlobalIndex(1,0,0), 0.50);
|
||||||
BOOST_CHECK_EQUAL(nncdata[0].cell2, 1);
|
check_nnc(nncdata, grid.getGlobalIndex(0,0,0), grid.getGlobalIndex(0,1,0), 1.00);
|
||||||
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);
|
|
||||||
|
|
||||||
|
const auto& loc = nnc.input_location( nncdata[0] );
|
||||||
|
BOOST_CHECK_EQUAL(loc.keyword, "NNC");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(addNNCfromDeck)
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(noNNC_EDIT)
|
||||||
{
|
{
|
||||||
Parser parser;
|
Parser parser;
|
||||||
auto deck = parser.parseFile(pathprefix() + "NNC/NNC.DATA");
|
auto deck = parser.parseString(no_nnc_input);
|
||||||
EclipseState eclipseState(deck);
|
EclipseState eclipseState(deck);
|
||||||
auto nnc = eclipseState.getInputNNC();
|
const auto& editnnc = eclipseState.getInputNNC();
|
||||||
BOOST_CHECK(nnc.hasNNC());
|
BOOST_CHECK(editnnc.edit().empty());
|
||||||
const std::vector<NNCdata>& nncdata = nnc.data();
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(nnc.numNNC(), 4);
|
|
||||||
// test add NNC
|
|
||||||
nnc.addNNC(2, 2, 2.0);
|
|
||||||
BOOST_CHECK_EQUAL(nnc.numNNC(), 5);
|
|
||||||
BOOST_CHECK_EQUAL(nncdata[4].cell1, 2);
|
|
||||||
BOOST_CHECK_EQUAL(nncdata[4].cell2, 2);
|
|
||||||
BOOST_CHECK_EQUAL(nncdata[4].trans, 2.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(addNNC)
|
|
||||||
|
BOOST_AUTO_TEST_CASE(readDeck_EDIT)
|
||||||
{
|
{
|
||||||
Opm::NNC nnc;
|
Parser parser;
|
||||||
// add NNC
|
auto deck = parser.parseString(editnnc_input);
|
||||||
nnc.addNNC(2,2,2.0);
|
EclipseGrid grid(10,10,10);
|
||||||
const std::vector<NNCdata>& nncdata = nnc.data();
|
|
||||||
BOOST_CHECK_EQUAL(nnc.numNNC(), 1);
|
NNC nnc(grid, deck);
|
||||||
BOOST_CHECK_EQUAL(nncdata[0].cell1, 2);
|
const std::vector<NNCdata>& data = nnc.edit();
|
||||||
BOOST_CHECK_EQUAL(nncdata[0].cell1, 2);
|
|
||||||
BOOST_CHECK_EQUAL(nncdata[0].trans, 2.0);
|
BOOST_CHECK_EQUAL(data.size(), 2); //neighbouring connections in EDITNNC are ignored
|
||||||
|
BOOST_CHECK(!has_nnc(data, grid.getGlobalIndex(0,0,0), grid.getGlobalIndex(0,1,0)));
|
||||||
|
BOOST_CHECK(!has_nnc(data, grid.getGlobalIndex(0,0,0), grid.getGlobalIndex(1,0,0)));
|
||||||
|
|
||||||
|
check_order(nnc);
|
||||||
|
check_edit_nnc(data, grid.getGlobalIndex(2,0,0), grid.getGlobalIndex(0,0,0), 0.1);
|
||||||
|
check_edit_nnc(data, grid.getGlobalIndex(1,0,0), grid.getGlobalIndex(1,2,0), 0.06);
|
||||||
|
|
||||||
|
const std::vector<NNCdata>& input = nnc.input();
|
||||||
|
check_nnc(input, grid.getGlobalIndex(2,0,0), grid.getGlobalIndex(4,0,0), 0.20);
|
||||||
|
check_nnc(input, grid.getGlobalIndex(2,0,0), grid.getGlobalIndex(6,0,0), 0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(ACTNUM)
|
||||||
|
{
|
||||||
|
Parser parser;
|
||||||
|
auto deck = parser.parseString(actnum);
|
||||||
|
EclipseState eclipseState(deck);
|
||||||
|
const auto& grid = eclipseState.getInputGrid();
|
||||||
|
const auto& editnnc = eclipseState.getInputNNC();
|
||||||
|
const auto& edit = editnnc.edit();
|
||||||
|
const auto& input = editnnc.input();
|
||||||
|
BOOST_CHECK_EQUAL(edit.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(input.size(), 1);
|
||||||
|
check_nnc(input, grid.getGlobalIndex(1,1,0), grid.getGlobalIndex(2,2,0), 0.5);
|
||||||
|
check_edit_nnc(edit, grid.getGlobalIndex(3,3,0), grid.getGlobalIndex(4,4,0), 2.0);
|
||||||
|
check_order(editnnc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user