Compare commits
36 Commits
testing/20
...
release/su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2884d02a71 | ||
|
|
90459cac7e | ||
|
|
4c6d4ee201 | ||
|
|
906ff3f4b5 | ||
|
|
238d3ddb58 | ||
|
|
42745e0bfc | ||
|
|
4e593da140 | ||
|
|
662d673c44 | ||
|
|
fdc4b0142e | ||
|
|
142994dde6 | ||
|
|
d58001f608 | ||
|
|
7dccd13c50 | ||
|
|
fb5e1229ef | ||
|
|
d30fc975e3 | ||
|
|
36af2aadb5 | ||
|
|
cf754c499d | ||
|
|
9d7ec59e9e | ||
|
|
eded8bacfc | ||
|
|
87e3beb601 | ||
|
|
079d946723 | ||
|
|
492a240f09 | ||
|
|
e6c0ccb5bf | ||
|
|
71d92c3dc8 | ||
|
|
2ea1b7860f | ||
|
|
9fd5ce396b | ||
|
|
bff3c0bff1 | ||
|
|
7cd29ea7d7 | ||
|
|
a3c9943a5e | ||
|
|
552c390465 | ||
|
|
9f9041dcae | ||
|
|
c870172a30 | ||
|
|
4a5b71d8c1 | ||
|
|
ff939b44f2 | ||
|
|
9e8110e67b | ||
|
|
5aa0bfadf0 | ||
|
|
e1948ccf99 |
@@ -150,7 +150,7 @@ if(ENABLE_ECL_INPUT)
|
||||
LIBRARIES ${_libs})
|
||||
opm_add_test(test_EclFilesComparator CONDITION ENABLE_ECL_INPUT
|
||||
LIBRARIES ${_libs})
|
||||
if(HAVE_DYNAMIC_BOOST_TEST AND NOT BUILD_SHARED_LIBS)
|
||||
if(HAVE_DYNAMIC_BOOST_TEST)
|
||||
set_target_properties(test_compareSummary PROPERTIES
|
||||
COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK)
|
||||
set_target_properties(test_EclFilesComparator PROPERTIES
|
||||
|
||||
@@ -266,6 +266,8 @@ if(ENABLE_ECL_OUTPUT)
|
||||
tests/table_deck.DATA
|
||||
tests/summary_deck_non_constant_porosity.DATA
|
||||
tests/SUMMARY_EFF_FAC.DATA
|
||||
tests/SPE1CASE1.DATA
|
||||
tests/SPE9_CP_PACKED.DATA
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -21,10 +21,28 @@ if (CXX_COMPAT_GCC)
|
||||
# disabled due to widespread bugs in the linker plugin
|
||||
option (WHOLE_PROG_OPTIM "Whole program optimization (lto)" OFF)
|
||||
if (WHOLE_PROG_OPTIM)
|
||||
check_cxx_accepts_flag ("-flto" HAVE_LINK_OPTS)
|
||||
if (HAVE_LINK_OPTS)
|
||||
list (APPEND _opt_flags "-flto")
|
||||
endif (HAVE_LINK_OPTS)
|
||||
check_cxx_accepts_flag ("-flto" HAVE_LINK_OPTS)
|
||||
check_cxx_accepts_flag ("-fuse-linker-plugin" HAVE_LINK_PLUGIN)
|
||||
if (HAVE_LINK_OPTS)
|
||||
list (APPEND _opt_flags "-flto")
|
||||
endif (HAVE_LINK_OPTS)
|
||||
if (HAVE_LINK_PLUGIN)
|
||||
list (APPEND _opt_flags "-fuse-linker-plugin")
|
||||
endif (HAVE_LINK_PLUGIN)
|
||||
if(HAVE_LINK_OPTS AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
string(REPLACE "." ";" VERSION_LIST "${CMAKE_C_COMPILER_VERSION}")
|
||||
list(GET VERSION_LIST 0 VER_MAJOR)
|
||||
find_program(LTO_AR_COMMAND NAMES ${CMAKE_C_COMPILER}-ar gcc-ar-${VER_MAJOR} gcc-ar)
|
||||
find_program(LTO_RANLIB_COMMAND NAMES ${CMAKE_C_COMPILER}-ranlib gcc-ranlib-${VER_MAJOR} gcc-ranlib)
|
||||
if(LTO_AR_COMMAND)
|
||||
set(CMAKE_AR ${LTO_AR_COMMAND})
|
||||
message(STATUS "Using LTO-enabled ar: ${CMAKE_AR}")
|
||||
endif()
|
||||
if(LTO_RANLIB_COMMAND)
|
||||
set(CMAKE_RANLIB ${LTO_RANLIB_COMMAND})
|
||||
message(STATUS "Using LTO-enabled ranlib: ${CMAKE_RANLIB}")
|
||||
endif()
|
||||
endif()
|
||||
endif (WHOLE_PROG_OPTIM)
|
||||
|
||||
# native instruction set tuning
|
||||
|
||||
@@ -29,11 +29,34 @@ if(NOT @opm-project_NAME@_FOUND)
|
||||
set (@opm-project_NAME@_LIBRARY_DIRS "@opm-project_LIBRARY_DIRS@" "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@")
|
||||
set (@opm-project_NAME@_LINKER_FLAGS "@opm-project_LINKER_FLAGS@")
|
||||
set (@opm-project_NAME@_CONFIG_VARS "@opm-project_CONFIG_VARS@")
|
||||
set (HAVE_@opm-project_NAME_UC@ 1)
|
||||
|
||||
# libraries come from the build tree where this file was generated
|
||||
set (@opm-project_NAME@_LIBRARY "@opm-project_LIBRARY@")
|
||||
set (@opm-project_NAME@_LIBRARIES ${@opm-project_NAME@_LIBRARY} "@opm-project_LIBRARIES@")
|
||||
|
||||
# The purpose of this string replacement operation is to enable use of the
|
||||
# generated opm-project-config.cmake file also in the situation where 'make
|
||||
# install' has been invoked with the DESTDIR option:
|
||||
#
|
||||
# opm-common/build> cmake .. -DCMAKE_INSTALL_PREFIX=/real/prefix
|
||||
# opm-common/budil> make install DESTDIR=/tmp/prefix
|
||||
#
|
||||
# downstream/build> cmake .. -DDEST_PREFIX=/tmp/prefix -DCMAKE_PREFIX_PATH=/tmp/prefix
|
||||
# downstream/build> make install
|
||||
#
|
||||
# That way the downstream dependency can still use find_package( opm-common )
|
||||
# even though the opm-common-config.cmake file is not internally consistent
|
||||
# with it's own location in the filesystem.
|
||||
|
||||
if(DEST_PREFIX)
|
||||
set(DEST_PREFIX "${DEST_PREFIX}${@opm-project_NAME@_PREFIX}")
|
||||
string(REPLACE ${@opm-project_NAME@_PREFIX} ${DEST_PREFIX} @opm-project_NAME@_INCLUDE_DIRS "${@opm-project_NAME@_INCLUDE_DIRS}")
|
||||
string(REPLACE ${@opm-project_NAME@_PREFIX} ${DEST_PREFIX} @opm-project_NAME@_LIBRARY_DIRS "${@opm-project_NAME@_LIBRARY_DIRS}")
|
||||
string(REPLACE ${@opm-project_NAME@_PREFIX} ${DEST_PREFIX} @opm-project_NAME@_LIBRARY "${@opm-project_NAME@_LIBRARY}")
|
||||
endif()
|
||||
|
||||
|
||||
set (HAVE_@opm-project_NAME_UC@ 1)
|
||||
mark_as_advanced (@opm-project_NAME@_LIBRARY)
|
||||
|
||||
# not all projects have targets; conditionally add this part
|
||||
@@ -71,12 +94,17 @@ if(NOT @opm-project_NAME@_FOUND)
|
||||
|
||||
# this is the contents of config.h as far as our probes can tell:
|
||||
|
||||
# extra code from variable OPM_PROJECT_EXTRA_CODE
|
||||
@OPM_PROJECT_EXTRA_CODE@
|
||||
# end extra code
|
||||
|
||||
# This call is at the bottom as we need to include
|
||||
# the OpmPackage Macros.
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" @PREREQ_LOCATION@)
|
||||
include(@opm-project_NAME@-prereqs)
|
||||
# The settings in this block do not mix well with the DEST_PREFIX
|
||||
# setting.
|
||||
if (NOT DEST_PREFIX)
|
||||
# This is required to include OpmPackage
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" @PREREQ_LOCATION@)
|
||||
|
||||
# extra code from variable OPM_PROJECT_EXTRA_CODE
|
||||
@OPM_PROJECT_EXTRA_CODE@
|
||||
# end extra code
|
||||
|
||||
include(@opm-project_NAME@-prereqs)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -231,20 +231,23 @@ void ECLRegressionTest::gridCompare(const bool volumecheck) const {
|
||||
|
||||
|
||||
void ECLRegressionTest::results() {
|
||||
if (keywords1.size() != keywords2.size()) {
|
||||
std::set<std::string> keys(keywords1.begin() , keywords1.end());
|
||||
for (const auto& key2: keywords2)
|
||||
keys.insert( key2 );
|
||||
if (!this->acceptExtraKeywords) {
|
||||
if (keywords1.size() != keywords2.size()) {
|
||||
std::set<std::string> keys(keywords1.begin() , keywords1.end());
|
||||
for (const auto& key2: keywords2)
|
||||
keys.insert( key2 );
|
||||
|
||||
for (const auto& key : keys)
|
||||
fprintf(stderr," %8s:%3d %8s:%3d \n",key.c_str() , ecl_file_get_num_named_kw( ecl_file1 , key.c_str()),
|
||||
key.c_str() , ecl_file_get_num_named_kw( ecl_file2 , key.c_str()));
|
||||
for (const auto& key : keys)
|
||||
fprintf(stderr," %8s:%3d %8s:%3d \n",key.c_str() , ecl_file_get_num_named_kw( ecl_file1 , key.c_str()),
|
||||
key.c_str() , ecl_file_get_num_named_kw( ecl_file2 , key.c_str()));
|
||||
|
||||
|
||||
OPM_THROW(std::runtime_error, "\nKeywords in first file: " << keywords1.size()
|
||||
<< "\nKeywords in second file: " << keywords2.size()
|
||||
<< "\nThe number of keywords differ.");
|
||||
OPM_THROW(std::runtime_error, "\nKeywords in first file: " << keywords1.size()
|
||||
<< "\nKeywords in second file: " << keywords2.size()
|
||||
<< "\nThe number of keywords differ.");
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& it : keywords1)
|
||||
resultsForKeyword(it);
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@ class ECLRegressionTest: public ECLFilesComparator {
|
||||
// Only compare last occurrence
|
||||
bool onlyLastOccurrence = false;
|
||||
|
||||
// Accept extra keywords in the restart file of the 'new' simulation.
|
||||
bool acceptExtraKeywords = false;
|
||||
|
||||
|
||||
// Prints results stored in absDeviation and relDeviation.
|
||||
void printResultsForKeyword(const std::string& keyword) const;
|
||||
|
||||
@@ -69,6 +73,11 @@ class ECLRegressionTest: public ECLFilesComparator {
|
||||
//! \brief Option to only compare last occurrence
|
||||
void setOnlyLastOccurrence(bool onlyLastOccurrenceArg) {this->onlyLastOccurrence = onlyLastOccurrenceArg;}
|
||||
|
||||
// Accept extra keywords: If this switch is set to true the comparison
|
||||
// of restart files will ignore extra keywords which are only present
|
||||
// in the new simulation.
|
||||
void setAcceptExtraKeywords(bool acceptExtraKeywords) { this->acceptExtraKeywords = acceptExtraKeywords; }
|
||||
|
||||
//! \brief Compares grid properties of the two cases.
|
||||
// gridCompare() checks if both the number of active and global cells in the two cases are the same. If they are, and volumecheck is true, all cells are looped over to calculate the cell volume deviation for the two cases. If the both the relative and absolute deviation exceeds the tolerances, an exception is thrown.
|
||||
void gridCompare(const bool volumecheck) const;
|
||||
|
||||
@@ -132,6 +132,7 @@ int main(int argc, char** argv) {
|
||||
bool allowSpikes = false;
|
||||
bool throwOnError = true;
|
||||
bool throwTooGreatErrorRatio = true;
|
||||
bool acceptExtraKeywords = false;
|
||||
bool analysis = false;
|
||||
bool volumecheck = true;
|
||||
char* keyword = nullptr;
|
||||
@@ -140,7 +141,7 @@ int main(int argc, char** argv) {
|
||||
int c = 0;
|
||||
int spikeLimit = -1;
|
||||
|
||||
while ((c = getopt(argc, argv, "hiIk:alnpPt:VRgs:m:vK")) != -1) {
|
||||
while ((c = getopt(argc, argv, "hiIk:alnpPt:VRgs:m:vKx")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
analysis = true;
|
||||
@@ -198,6 +199,9 @@ int main(int argc, char** argv) {
|
||||
case 'V':
|
||||
volumecheck = false;
|
||||
break;
|
||||
case 'x':
|
||||
acceptExtraKeywords = true;
|
||||
break;
|
||||
case '?':
|
||||
if (optopt == 'k' || optopt == 'm' || optopt == 's') {
|
||||
std::cerr << "Option " << optopt << " requires a keyword as argument, see manual (-h) for more information." << std::endl;
|
||||
@@ -344,6 +348,7 @@ int main(int argc, char** argv) {
|
||||
ECLRegressionTest comparator(file_type, basename1, basename2, absTolerance, relTolerance);
|
||||
comparator.throwOnErrors(throwOnError);
|
||||
comparator.doAnalysis(analysis);
|
||||
comparator.setAcceptExtraKeywords(acceptExtraKeywords);
|
||||
if (printKeywords) {
|
||||
comparator.printKeywords();
|
||||
return 0;
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ert/ecl/ecl_sum.h>
|
||||
#include <ert/ecl/Smspec.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Opm {
|
||||
|
||||
size_t getNY() const;
|
||||
size_t getNZ() const;
|
||||
size_t operator[](int dim) const;
|
||||
|
||||
const std::array<int, 3> getNXYZ() const;
|
||||
|
||||
|
||||
@@ -105,6 +105,41 @@ namespace Opm {
|
||||
------ Default ------
|
||||
If no keywords for config of writing restart files have been handled; no restart files are written.
|
||||
|
||||
|
||||
ECL compatible restart
|
||||
======================
|
||||
|
||||
Unfortunately flow & eclipse are not compatible across restarts. The
|
||||
RestartIO implementation can write restart files for flow -> flow restart
|
||||
or alternatively for flow -> eclipse restart. This is regulated by the
|
||||
boolean flag ecl_compatible_restart in the IOConfig class. The difference
|
||||
between the two are as follows:
|
||||
|
||||
ecl_compatible_restart = false:
|
||||
|
||||
1. The 'extra' fields in the RestartValue structure are actually
|
||||
written to disk.
|
||||
|
||||
2. You can optionally ask the RestartIO::save() function to save the
|
||||
solution in double precision.
|
||||
|
||||
3. The RestartIO::save() function will save opm specific vector OPM_IWEL
|
||||
and OPM_XWEL.
|
||||
|
||||
ecl_compatible_restart = true:
|
||||
|
||||
1. The 'extra' fields in the RestartValue are silently ignored.
|
||||
|
||||
2. If request double precision solution data that is silently ignored,
|
||||
it will be float.
|
||||
|
||||
3. The OPM_IWEL and OPM_XWEL vectors will not be written.
|
||||
|
||||
Observe that the solution data in the RestartValue is passed
|
||||
unconditionally to the solution section in the restart file, so if you
|
||||
pass a field in the solution section which Eclipse does not recognize you
|
||||
will end up with a restart file which Eclipse can not read, even if you
|
||||
have set ecl_compatible_restart to true.
|
||||
*/
|
||||
|
||||
|
||||
@@ -117,7 +152,8 @@ namespace Opm {
|
||||
explicit IOConfig( const Deck& );
|
||||
explicit IOConfig( const std::string& input_path );
|
||||
|
||||
|
||||
void setEclCompatibleRST(bool ecl_rst);
|
||||
bool getEclCompatibleRST() const;
|
||||
bool getWriteEGRIDFile() const;
|
||||
bool getWriteINITFile() const;
|
||||
bool getUNIFOUT() const;
|
||||
@@ -165,6 +201,7 @@ namespace Opm {
|
||||
std::string m_output_dir;
|
||||
std::string m_base_name;
|
||||
bool m_nosim;
|
||||
bool ecl_compatible_rst = true;
|
||||
|
||||
IOConfig( const GRIDSection&,
|
||||
const RUNSPECSection&,
|
||||
|
||||
@@ -362,6 +362,7 @@ namespace Opm {
|
||||
|
||||
DynamicState< RestartSchedule > restart_schedule;
|
||||
DynamicState< std::map< std::string, int > > restart_keywords;
|
||||
std::vector< bool > save_keywords;
|
||||
};
|
||||
} //namespace Opm
|
||||
|
||||
|
||||
@@ -41,50 +41,57 @@ namespace Opm {
|
||||
Connection(int i, int j , int k ,
|
||||
int complnum,
|
||||
double depth,
|
||||
WellCompletion::StateEnum state ,
|
||||
const Value<double>& connectionTransmissibilityFactor,
|
||||
const Value<double>& diameter,
|
||||
const Value<double>& skinFactor,
|
||||
const Value<double>& Kh,
|
||||
WellCompletion::StateEnum state,
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction);
|
||||
|
||||
|
||||
bool attachedToSegment() const;
|
||||
bool sameCoordinate(const int i, const int j, const int k) const;
|
||||
int getI() const;
|
||||
int getJ() const;
|
||||
int getK() const;
|
||||
double getConnectionTransmissibilityFactor() const;
|
||||
double getDiameter() const;
|
||||
double getSkinFactor() const;
|
||||
bool attachedToSegment() const;
|
||||
const Value<double>& getConnectionTransmissibilityFactorAsValueObject() const;
|
||||
const Value<double>& getEffectiveKhAsValueObject() const;
|
||||
WellCompletion::StateEnum state() const;
|
||||
WellCompletion::DirectionEnum dir() const;
|
||||
double depth() const;
|
||||
int satTableId() const;
|
||||
int complnum() const;
|
||||
int segment() const;
|
||||
double CF() const;
|
||||
double Kh() const;
|
||||
double rw() const;
|
||||
double wellPi() const;
|
||||
|
||||
void setState(WellCompletion::StateEnum state);
|
||||
void setComplnum(int compnum);
|
||||
void scaleWellPi(double wellPi);
|
||||
void updateSegment(int segment_number, double center_depth);
|
||||
|
||||
bool operator==( const Connection& ) const;
|
||||
bool operator!=( const Connection& ) const;
|
||||
|
||||
WellCompletion::DirectionEnum dir;
|
||||
double center_depth;
|
||||
WellCompletion::StateEnum state;
|
||||
int sat_tableId;
|
||||
int complnum;
|
||||
|
||||
private:
|
||||
std::array<int,3> ijk;
|
||||
Value<double> m_diameter;
|
||||
Value<double> m_connectionTransmissibilityFactor;
|
||||
Value<double> m_skinFactor;
|
||||
Value<double> m_Kh;
|
||||
WellCompletion::DirectionEnum direction;
|
||||
double center_depth;
|
||||
WellCompletion::StateEnum open_state;
|
||||
int sat_tableId;
|
||||
int m_complnum;
|
||||
double m_CF;
|
||||
double m_Kh;
|
||||
double m_rw;
|
||||
|
||||
std::array<int,3> ijk;
|
||||
|
||||
public:
|
||||
// related segment number
|
||||
// -1 means the completion is not related to segment
|
||||
int segment_number = -1;
|
||||
double wellPi = 1.0;
|
||||
double wPi = 1.0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* COMPLETION_HPP_ */
|
||||
|
||||
|
||||
@@ -35,10 +35,9 @@ namespace Opm {
|
||||
void addConnection(int i, int j , int k ,
|
||||
double depth,
|
||||
WellCompletion::StateEnum state ,
|
||||
const Value<double>& connectionTransmissibilityFactor,
|
||||
const Value<double>& diameter,
|
||||
const Value<double>& skinFactor,
|
||||
const Value<double>& Kh,
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnum::Z);
|
||||
void loadCOMPDAT(const DeckRecord& record, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties);
|
||||
@@ -47,6 +46,7 @@ namespace Opm {
|
||||
|
||||
void add( Connection );
|
||||
size_t size() const;
|
||||
const Connection& operator[](size_t index) const;
|
||||
const Connection& get(size_t index) const;
|
||||
const Connection& getFromIJK(const int i, const int j, const int k) const;
|
||||
Connection& getFromIJK(const int i, const int j, const int k);
|
||||
@@ -77,10 +77,9 @@ namespace Opm {
|
||||
int complnum,
|
||||
double depth,
|
||||
WellCompletion::StateEnum state ,
|
||||
const Value<double>& connectionTransmissibilityFactor,
|
||||
const Value<double>& diameter,
|
||||
const Value<double>& skinFactor,
|
||||
const Value<double>& Kh,
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnum::Z);
|
||||
|
||||
|
||||
@@ -24,10 +24,59 @@
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <ert/ecl/Smspec.hpp>
|
||||
#include <ert/ecl/smspec_node.h>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
/*
|
||||
Very small utility class to get value semantics on the smspec_node
|
||||
pointers. This should die as soon as the smspec_node class proper gets
|
||||
value semantics.
|
||||
*/
|
||||
|
||||
class SummaryNode {
|
||||
public:
|
||||
SummaryNode(smspec_node_type * c_ptr) :
|
||||
ptr(c_ptr)
|
||||
{}
|
||||
|
||||
SummaryNode(const SummaryNode& other) :
|
||||
ptr( smspec_node_alloc_copy(other.get()))
|
||||
{}
|
||||
|
||||
const smspec_node_type * get() const {
|
||||
return this->ptr;
|
||||
}
|
||||
|
||||
std::string wgname() const {
|
||||
return smspec_node_get_wgname(this->ptr);
|
||||
}
|
||||
|
||||
std::string keyword() const {
|
||||
return smspec_node_get_keyword(this->ptr);
|
||||
}
|
||||
|
||||
int num() const {
|
||||
return smspec_node_get_num(this->ptr);
|
||||
}
|
||||
|
||||
ecl_smspec_var_type type() const {
|
||||
return smspec_node_get_var_type(this->ptr);
|
||||
}
|
||||
|
||||
SummaryNode& operator=(const SummaryNode &other) {
|
||||
this->ptr = smspec_node_alloc_copy(other.ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SummaryNode() {
|
||||
smspec_node_free(this->ptr);
|
||||
}
|
||||
private:
|
||||
smspec_node_type * ptr;
|
||||
};
|
||||
|
||||
|
||||
class Deck;
|
||||
class TableManager;
|
||||
class EclipseState;
|
||||
@@ -38,7 +87,9 @@ namespace Opm {
|
||||
|
||||
class SummaryConfig {
|
||||
public:
|
||||
typedef std::vector< ERT::smspec_node >::const_iterator const_iterator;
|
||||
typedef SummaryNode keyword_type;
|
||||
typedef std::vector< keyword_type > keyword_list;
|
||||
typedef keyword_list::const_iterator const_iterator;
|
||||
|
||||
SummaryConfig( const Deck&, const Schedule&,
|
||||
const TableManager&, const ParseContext&);
|
||||
@@ -80,7 +131,7 @@ namespace Opm {
|
||||
part, e.g. "WWCT", and not the qualification with
|
||||
well/group name or a numerical value.
|
||||
*/
|
||||
std::vector< ERT::smspec_node > keywords;
|
||||
keyword_list keywords;
|
||||
std::set<std::string> short_keywords;
|
||||
std::set<std::string> summary_keywords;
|
||||
};
|
||||
|
||||
@@ -354,7 +354,7 @@ void EclipseIO::Impl::writeINITFile( const data::Solution& simProps, std::map<st
|
||||
const std::string& key = pair.first;
|
||||
const std::vector<int>& int_vector = pair.second;
|
||||
if (key.size() > ECL_STRING8_LENGTH)
|
||||
throw std::invalid_argument("Keyword is too long.");
|
||||
throw std::invalid_argument("Keyword is too long.");
|
||||
|
||||
writeKeyword( fortio , key , int_vector );
|
||||
}
|
||||
@@ -393,8 +393,8 @@ void EclipseIO::Impl::writeEGRIDFile( const NNC& nnc ) const {
|
||||
|
||||
/*
|
||||
int_data: Writes key(string) and integers vector to INIT file as eclipse keywords
|
||||
- Key: Max 8 chars.
|
||||
- Wrong input: invalid_argument exception.
|
||||
- Key: Max 8 chars.
|
||||
- Wrong input: invalid_argument exception.
|
||||
*/
|
||||
void EclipseIO::writeInitial( data::Solution simProps, std::map<std::string, std::vector<int> > int_data, const NNC& nnc) {
|
||||
if( !this->impl->output_enabled )
|
||||
@@ -439,9 +439,10 @@ void EclipseIO::writeTimeStep(int report_step,
|
||||
|
||||
|
||||
/*
|
||||
Summary data is written unconditionally for every timestep.
|
||||
Summary data is written unconditionally for every timestep except for the
|
||||
very intial report_step==0 call, which is only garbage.
|
||||
*/
|
||||
{
|
||||
if (report_step > 0) {
|
||||
this->impl->summary.add_timestep( report_step,
|
||||
secs_elapsed,
|
||||
es,
|
||||
|
||||
@@ -206,7 +206,7 @@ data::Wells restore_wells( const ecl_kw_type * opm_xwel,
|
||||
|
||||
for( const auto& sc : sched_well->getConnections( sim_step ) ) {
|
||||
const auto i = sc.getI(), j = sc.getJ(), k = sc.getK();
|
||||
if( !grid.cellActive( i, j, k ) || sc.state == WellCompletion::SHUT ) {
|
||||
if( !grid.cellActive( i, j, k ) || sc.state() == WellCompletion::SHUT ) {
|
||||
opm_xwel_data += data::Connection::restart_size + phases.size();
|
||||
continue;
|
||||
}
|
||||
@@ -253,6 +253,10 @@ RestartValue load( const std::string& filename,
|
||||
} else
|
||||
file_view = ecl_file_get_global_view( file.get() );
|
||||
|
||||
if (!ecl_file_view_has_kw(file_view, "OPM_XWEL"))
|
||||
throw std::runtime_error("Sorry - this file is missing the OPM_XWEL keyword - required for flow based restart\n");
|
||||
|
||||
|
||||
const ecl_kw_type * intehead = ecl_file_view_iget_named_kw( file_view , "INTEHEAD", 0 );
|
||||
const ecl_kw_type * opm_xwel = ecl_file_view_iget_named_kw( file_view , "OPM_XWEL", 0 );
|
||||
const ecl_kw_type * opm_iwel = ecl_file_view_iget_named_kw( file_view, "OPM_IWEL", 0 );
|
||||
@@ -310,10 +314,10 @@ std::vector<int> serialize_ICON( int sim_step,
|
||||
data[ offset + ICON_I_INDEX ] = connection.getI() + 1;
|
||||
data[ offset + ICON_J_INDEX ] = connection.getJ() + 1;
|
||||
data[ offset + ICON_K_INDEX ] = connection.getK() + 1;
|
||||
data[ offset + ICON_DIRECTION_INDEX ] = connection.dir;
|
||||
data[ offset + ICON_DIRECTION_INDEX ] = connection.dir();
|
||||
{
|
||||
const auto open = WellCompletion::StateEnum::OPEN;
|
||||
data[ offset + ICON_STATUS_INDEX ] = connection.state == open
|
||||
data[ offset + ICON_STATUS_INDEX ] = connection.state() == open
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
@@ -408,7 +412,7 @@ std::vector< double > serialize_OPM_XWEL( const data::Wells& wells,
|
||||
const auto i = sc.getI(), j = sc.getJ(), k = sc.getK();
|
||||
|
||||
const auto rs_size = phases.size() + data::Connection::restart_size;
|
||||
if( !grid.cellActive( i, j, k ) || sc.state == WellCompletion::SHUT ) {
|
||||
if( !grid.cellActive( i, j, k ) || sc.state() == WellCompletion::SHUT ) {
|
||||
xwel.insert( xwel.end(), rs_size, 0.0 );
|
||||
continue;
|
||||
}
|
||||
@@ -554,16 +558,20 @@ void writeWell(ecl_rst_file_type* rst_file, int sim_step, const EclipseState& es
|
||||
const auto& phases = es.runspec().phases();
|
||||
const size_t ncwmax = schedule.getMaxNumConnectionsForWells(sim_step);
|
||||
|
||||
const auto opm_xwel = serialize_OPM_XWEL( wells, sim_step, sched_wells, phases, grid );
|
||||
const auto opm_iwel = serialize_OPM_IWEL( wells, sched_wells );
|
||||
const auto iwel_data = serialize_IWEL(sim_step, sched_wells, grid);
|
||||
const auto icon_data = serialize_ICON(sim_step , ncwmax, sched_wells, grid);
|
||||
const auto zwel_data = serialize_ZWEL( sched_wells );
|
||||
|
||||
write_kw( rst_file, ERT::EclKW< int >( IWEL_KW, iwel_data) );
|
||||
write_kw( rst_file, ERT::EclKW< const char* >(ZWEL_KW, zwel_data ) );
|
||||
write_kw( rst_file, ERT::EclKW< double >( OPM_XWEL, opm_xwel ) );
|
||||
write_kw( rst_file, ERT::EclKW< int >( OPM_IWEL, opm_iwel ) );
|
||||
|
||||
if (!es.getIOConfig().getEclCompatibleRST()) {
|
||||
const auto opm_xwel = serialize_OPM_XWEL( wells, sim_step, sched_wells, phases, grid );
|
||||
const auto opm_iwel = serialize_OPM_IWEL( wells, sched_wells );
|
||||
write_kw( rst_file, ERT::EclKW< double >( OPM_XWEL, opm_xwel ) );
|
||||
write_kw( rst_file, ERT::EclKW< int >( OPM_IWEL, opm_iwel ) );
|
||||
}
|
||||
|
||||
write_kw( rst_file, ERT::EclKW< int >( ICON_KW, icon_data ) );
|
||||
}
|
||||
|
||||
@@ -605,6 +613,7 @@ void save(const std::string& filename,
|
||||
{
|
||||
checkSaveArguments(es, value, grid);
|
||||
{
|
||||
bool ecl_compatible_rst = es.getIOConfig().getEclCompatibleRST();
|
||||
int sim_step = std::max(report_step - 1, 0);
|
||||
int ert_phase_mask = es.runspec().eclPhaseMask( );
|
||||
const auto& units = es.getUnits();
|
||||
@@ -617,6 +626,9 @@ void save(const std::string& filename,
|
||||
else
|
||||
rst_file.reset( ecl_rst_file_open_write( filename.c_str() ) );
|
||||
|
||||
if (ecl_compatible_rst)
|
||||
write_double = false;
|
||||
|
||||
// Convert solution fields and extra values from SI to user units.
|
||||
value.solution.convertFromSI(units);
|
||||
for (auto & extra_value : value.extra) {
|
||||
@@ -628,8 +640,9 @@ void save(const std::string& filename,
|
||||
|
||||
writeHeader( rst_file.get(), sim_step, report_step, posix_time , sim_time, ert_phase_mask, units, schedule , grid );
|
||||
writeWell( rst_file.get(), sim_step, es , grid, schedule, value.wells);
|
||||
writeSolution( rst_file.get(), value, write_double );
|
||||
writeExtraData( rst_file.get(), value.extra );
|
||||
writeSolution( rst_file.get(), value, write_double);
|
||||
if (!ecl_compatible_rst)
|
||||
writeExtraData( rst_file.get(), value.extra );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <opm/output/eclipse/Summary.hpp>
|
||||
#include <opm/output/eclipse/RegionCache.hpp>
|
||||
|
||||
#include <ert/ecl/smspec_node.h>
|
||||
#include <ert/ecl/ecl_smspec.h>
|
||||
#include <ert/ecl/ecl_kw_magic.h>
|
||||
|
||||
@@ -362,6 +363,34 @@ inline quantity crate( const fn_args& args ) {
|
||||
return { v, rate_unit< phase >() };
|
||||
}
|
||||
|
||||
inline quantity trans_factors ( const fn_args& args ) {
|
||||
const quantity zero = { 0, measure::transmissibility };
|
||||
|
||||
if( args.schedule_wells.empty() ) return zero;
|
||||
// Like completion rate we need to look
|
||||
// up a connection with offset 0.
|
||||
const size_t global_index = args.num - 1;
|
||||
|
||||
const auto& well = args.schedule_wells.front();
|
||||
const auto& name = well->name();
|
||||
if( args.wells.count( name ) == 0 ) return zero;
|
||||
|
||||
const auto& grid = args.grid;
|
||||
const auto& connections = well->getConnections(args.sim_step);
|
||||
|
||||
const auto& connection = std::find_if(
|
||||
connections.begin(),
|
||||
connections.end(),
|
||||
[=]( const Opm::Connection& c ) {
|
||||
return grid.getGlobalIndex(c.getI(), c.getJ(), c.getK()) == global_index;
|
||||
} );
|
||||
|
||||
if( connection == connections.end() ) return zero;
|
||||
|
||||
const auto& v = connection->CF();
|
||||
return { v, measure::transmissibility };
|
||||
}
|
||||
|
||||
inline quantity bhp( const fn_args& args ) {
|
||||
const quantity zero = { 0, measure::pressure };
|
||||
if( args.schedule_wells.empty() ) return zero;
|
||||
@@ -709,6 +738,7 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "CGPT", mul( crate< rt::gas, producer >, duration ) },
|
||||
{ "CNPT", mul( crate< rt::solvent, producer >, duration ) },
|
||||
{ "CCIT", mul( crate< rt::wat, injector, polymer >, duration ) },
|
||||
{ "CTFAC", trans_factors },
|
||||
|
||||
{ "FWPR", rate< rt::wat, producer > },
|
||||
{ "FOPR", rate< rt::oil, producer > },
|
||||
@@ -971,7 +1001,7 @@ Summary::Summary( const EclipseState& st,
|
||||
std::set< std::string > unsupported_keywords;
|
||||
|
||||
for( const auto& node : sum ) {
|
||||
const auto* keyword = node.keyword();
|
||||
const auto* keyword = smspec_node_get_keyword(node.get());
|
||||
|
||||
const auto single_value_pair = single_values_units.find( keyword );
|
||||
const auto funs_pair = funs.find( keyword );
|
||||
@@ -985,15 +1015,15 @@ Summary::Summary( const EclipseState& st,
|
||||
add_timestep.
|
||||
*/
|
||||
if (single_value_pair != single_values_units.end()) {
|
||||
|
||||
if ((node.type() != ECL_SMSPEC_FIELD_VAR) && (node.type() != ECL_SMSPEC_MISC_VAR)) {
|
||||
auto node_type = smspec_node_get_var_type(node.get());
|
||||
if ((node_type != ECL_SMSPEC_FIELD_VAR) && (node_type != ECL_SMSPEC_MISC_VAR)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
node.wgname(),
|
||||
node.num(),
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( single_value_pair->second ),
|
||||
0 );
|
||||
|
||||
@@ -1002,36 +1032,37 @@ Summary::Summary( const EclipseState& st,
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
node.wgname(),
|
||||
node.num(),
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( region_pair->second ),
|
||||
0 );
|
||||
|
||||
this->handlers->region_nodes.emplace( std::make_pair(keyword, node.num()), nodeptr );
|
||||
this->handlers->region_nodes.emplace( std::make_pair(keyword, smspec_node_get_num(node.get())), nodeptr );
|
||||
|
||||
} else if (block_pair != block_units.end()) {
|
||||
if (node.type() != ECL_SMSPEC_BLOCK_VAR)
|
||||
if (smspec_node_get_var_type(node.get()) != ECL_SMSPEC_BLOCK_VAR)
|
||||
continue;
|
||||
|
||||
int global_index = node.num() - 1;
|
||||
int global_index = smspec_node_get_num(node.get()) - 1;
|
||||
if (!this->grid.cellActive(global_index))
|
||||
continue;
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
node.wgname(),
|
||||
node.num(),
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( block_pair->second ),
|
||||
0 );
|
||||
|
||||
this->handlers->block_nodes.emplace( std::make_pair(keyword, node.num()), nodeptr );
|
||||
this->handlers->block_nodes.emplace( std::make_pair(keyword, smspec_node_get_num(node.get())), nodeptr );
|
||||
|
||||
|
||||
|
||||
} else if (funs_pair != funs.end()) {
|
||||
auto node_type = smspec_node_get_var_type(node.get());
|
||||
|
||||
if ((node.type() == ECL_SMSPEC_COMPLETION_VAR) || (node.type() == ECL_SMSPEC_BLOCK_VAR)) {
|
||||
int global_index = node.num() - 1;
|
||||
if ((node_type == ECL_SMSPEC_COMPLETION_VAR) || (node_type == ECL_SMSPEC_BLOCK_VAR)) {
|
||||
int global_index = smspec_node_get_num(node.get()) - 1;
|
||||
if (!this->grid.cellActive(global_index))
|
||||
continue;
|
||||
}
|
||||
@@ -1043,7 +1074,7 @@ Summary::Summary( const EclipseState& st,
|
||||
const fn_args no_args { dummy_wells, // Wells from Schedule object
|
||||
0, // Duration of time step
|
||||
0, // Simulation step
|
||||
node.num(), // NUMS value for the summary output.
|
||||
smspec_node_get_num(node.get()), // NUMS value for the summary output.
|
||||
{}, // Well results - data::Wells
|
||||
{}, // Region <-> cell mappings.
|
||||
this->grid,
|
||||
@@ -1053,8 +1084,8 @@ Summary::Summary( const EclipseState& st,
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
node.wgname(),
|
||||
node.num(),
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( val.unit ),
|
||||
0 );
|
||||
|
||||
|
||||
@@ -42,29 +42,8 @@ serialize_SCON(int lookup_step,
|
||||
bool explicit_ctf_not_found = false;
|
||||
for (const auto& connection : connections) {
|
||||
const size_t offset = well_offset + connection_offset;
|
||||
const auto& ctf = connection.getConnectionTransmissibilityFactorAsValueObject();
|
||||
if (ctf.hasValue()) {
|
||||
// CTF explicitly set in deck, overrides calculation
|
||||
// from Peaceman model. We should also give the Kh
|
||||
// factor, we output an explicitly invalid value
|
||||
// instead. This is acceptable since it will not be
|
||||
// used (the explicit CTF factor is used instead).
|
||||
const double ctf_SI = ctf.getValue();
|
||||
const double ctf_output = units.from_si(UnitSystem::measure::transmissibility, ctf_SI);
|
||||
data[ offset + SCON_CF_INDEX ] = ctf_output;
|
||||
data[ offset + SCON_KH_INDEX ] = UNIMPLEMENTED_VALUE;
|
||||
} else {
|
||||
// CTF not set in deck, Peaceman formula used to
|
||||
// compute it. Here we should store the data for the
|
||||
// connection required to recalculate the CTF (the Kh
|
||||
// factor), as well as the actual CTF used by the
|
||||
// simulator, but that requires access to more data
|
||||
// from the simulator. As an interim measure we write
|
||||
// invalid values and give a warning.
|
||||
data[ offset + SCON_CF_INDEX ] = UNIMPLEMENTED_VALUE;
|
||||
data[ offset + SCON_KH_INDEX ] = UNIMPLEMENTED_VALUE;
|
||||
explicit_ctf_not_found = true;
|
||||
}
|
||||
data[ offset + SCON_CF_INDEX ] = units.from_si(Opm::UnitSystem::measure::transmissibility,connection.CF());
|
||||
data[ offset + SCON_KH_INDEX ] = units.from_si(Opm::UnitSystem::measure::effective_Kh, connection.Kh());
|
||||
connection_offset += nsconz;
|
||||
}
|
||||
if (explicit_ctf_not_found) {
|
||||
@@ -73,7 +52,7 @@ serialize_SCON(int lookup_step,
|
||||
}
|
||||
well_offset += well_field_size;
|
||||
}
|
||||
return data;
|
||||
return data;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -83,7 +62,7 @@ serialize_ICON(int lookup_step,
|
||||
int ncwmax,
|
||||
int niconz,
|
||||
const std::vector<const Opm::Well*>& sched_wells)
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
{
|
||||
const size_t well_field_size = ncwmax * niconz;
|
||||
std::vector<int> data(sched_wells.size() * well_field_size, 0);
|
||||
@@ -94,17 +73,17 @@ serialize_ICON(int lookup_step,
|
||||
for (const auto& connection : connections) {
|
||||
const size_t offset = well_offset + connection_offset;
|
||||
|
||||
data[ offset + ICON_IC_INDEX ] = connection.complnum;
|
||||
data[ offset + ICON_IC_INDEX ] = connection.complnum();
|
||||
data[ offset + ICON_I_INDEX ] = connection.getI() + 1;
|
||||
data[ offset + ICON_J_INDEX ] = connection.getJ() + 1;
|
||||
data[ offset + ICON_K_INDEX ] = connection.getK() + 1;
|
||||
data[ offset + ICON_DIRECTION_INDEX ] = connection.dir;
|
||||
data[ offset + ICON_DIRECTION_INDEX ] = connection.dir();
|
||||
data[ offset + ICON_STATUS_INDEX ] =
|
||||
(connection.state == WellCompletion::StateEnum::OPEN) ?
|
||||
(connection.state() == WellCompletion::StateEnum::OPEN) ?
|
||||
1 : -1000;
|
||||
data[ offset + ICON_SEGMENT_INDEX ] =
|
||||
connection.attachedToSegment() ?
|
||||
connection.segment_number : 0;
|
||||
connection.segment() : 0;
|
||||
connection_offset += niconz;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,22 @@ namespace Opm {
|
||||
return m_nz;
|
||||
}
|
||||
|
||||
size_t GridDims::operator[](int dim) const {
|
||||
switch (dim) {
|
||||
case 0:
|
||||
return this->m_nx;
|
||||
break;
|
||||
case 1:
|
||||
return this->m_ny;
|
||||
break;
|
||||
case 2:
|
||||
return this->m_nz;
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument("Invalid argument dim:" + std::to_string(dim));
|
||||
}
|
||||
}
|
||||
|
||||
const std::array<int, 3> GridDims::getNXYZ() const {
|
||||
return std::array<int, 3> {{int( m_nx ), int( m_ny ), int( m_nz )}};
|
||||
}
|
||||
@@ -116,4 +132,5 @@ namespace Opm {
|
||||
m_ny = dims[1];
|
||||
m_nz = dims[2];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -122,6 +122,14 @@ namespace Opm {
|
||||
}
|
||||
|
||||
|
||||
bool IOConfig::getEclCompatibleRST() const {
|
||||
return this->ecl_compatible_rst;
|
||||
}
|
||||
|
||||
|
||||
void IOConfig::setEclCompatibleRST(bool ecl_rst) {
|
||||
this->ecl_compatible_rst = ecl_rst;
|
||||
}
|
||||
|
||||
|
||||
void IOConfig::overrideNOSIM(bool nosim) {
|
||||
|
||||
@@ -397,6 +397,12 @@ void RestartConfig::handleScheduleSection(const SCHEDULESection& schedule) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name == "SAVE") {
|
||||
this->save_keywords[current_step] = true;
|
||||
} else {
|
||||
this->save_keywords[current_step]= false;
|
||||
}
|
||||
|
||||
if( !( name == "RPTRST" || name == "RPTSCHED" ) ) continue;
|
||||
if( this->m_timemap.size() <= current_step ) continue;
|
||||
|
||||
@@ -476,7 +482,8 @@ void RestartConfig::handleScheduleSection(const SCHEDULESection& schedule) {
|
||||
m_timemap( std::move( timemap ) ),
|
||||
m_first_restart_step( -1 ),
|
||||
restart_schedule( m_timemap, { 0, 0, 1 } ),
|
||||
restart_keywords( m_timemap, {} )
|
||||
restart_keywords( m_timemap, {} ),
|
||||
save_keywords( m_timemap.numTimesteps(), false )
|
||||
{
|
||||
handleSolutionSection( solution );
|
||||
handleScheduleSection( schedule );
|
||||
@@ -494,6 +501,12 @@ void RestartConfig::handleScheduleSection(const SCHEDULESection& schedule) {
|
||||
if (0 == timestep)
|
||||
return m_write_initial_RST_file;
|
||||
|
||||
if (save_keywords[timestep]) {
|
||||
std::string logstring = "Fast restart using SAVE is not supported. Standard restart file is written instead";
|
||||
Opm::OpmLog::warning("Unhandled output keyword", logstring);
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
RestartSchedule ts_restart_config = getNode( timestep );
|
||||
return ts_restart_config.writeRestartFile( timestep , m_timemap );
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
@@ -36,26 +35,25 @@
|
||||
|
||||
namespace Opm {
|
||||
|
||||
|
||||
Connection::Connection(int i, int j , int k ,
|
||||
int compnum,
|
||||
double depth,
|
||||
WellCompletion::StateEnum stateArg ,
|
||||
const Value<double>& connectionTransmissibilityFactor,
|
||||
const Value<double>& diameter,
|
||||
const Value<double>& skinFactor,
|
||||
const Value<double>& Kh,
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction)
|
||||
: dir(direction),
|
||||
: direction(direction),
|
||||
center_depth(depth),
|
||||
state(stateArg),
|
||||
open_state(stateArg),
|
||||
sat_tableId(satTableId),
|
||||
complnum( compnum ),
|
||||
ijk({i,j,k}),
|
||||
m_diameter(diameter),
|
||||
m_connectionTransmissibilityFactor(connectionTransmissibilityFactor),
|
||||
m_skinFactor(skinFactor),
|
||||
m_Kh(Kh)
|
||||
m_complnum( compnum ),
|
||||
m_CF(CF),
|
||||
m_Kh(Kh),
|
||||
m_rw(rw),
|
||||
ijk({i,j,k})
|
||||
{}
|
||||
|
||||
bool Connection::sameCoordinate(const int i, const int j, const int k) const {
|
||||
@@ -80,42 +78,77 @@ namespace Opm {
|
||||
return ijk[2];
|
||||
}
|
||||
|
||||
|
||||
double Connection::getConnectionTransmissibilityFactor() const {
|
||||
return m_connectionTransmissibilityFactor.getValue();
|
||||
}
|
||||
|
||||
double Connection::getDiameter() const {
|
||||
return m_diameter.getValue();
|
||||
}
|
||||
|
||||
double Connection::getSkinFactor() const {
|
||||
return m_skinFactor.getValue();
|
||||
}
|
||||
|
||||
|
||||
const Value<double>& Connection::getConnectionTransmissibilityFactorAsValueObject() const {
|
||||
return m_connectionTransmissibilityFactor;
|
||||
}
|
||||
|
||||
const Value<double>& Connection::getEffectiveKhAsValueObject() const {
|
||||
return m_Kh;
|
||||
}
|
||||
|
||||
bool Connection::attachedToSegment() const {
|
||||
return (segment_number > 0);
|
||||
}
|
||||
|
||||
WellCompletion::DirectionEnum Connection::dir() const {
|
||||
return this->direction;
|
||||
}
|
||||
|
||||
double Connection::depth() const {
|
||||
return this->center_depth;
|
||||
}
|
||||
|
||||
WellCompletion::StateEnum Connection::state() const {
|
||||
return this->open_state;
|
||||
}
|
||||
|
||||
int Connection::satTableId() const {
|
||||
return this->sat_tableId;
|
||||
}
|
||||
|
||||
int Connection::complnum() const {
|
||||
return this->m_complnum;
|
||||
}
|
||||
|
||||
void Connection::setComplnum(int complnum) {
|
||||
this->m_complnum = complnum;
|
||||
}
|
||||
|
||||
double Connection::CF() const {
|
||||
return this->m_CF;
|
||||
}
|
||||
|
||||
double Connection::Kh() const {
|
||||
return this->m_Kh;
|
||||
}
|
||||
|
||||
double Connection::rw() const {
|
||||
return this->m_rw;
|
||||
}
|
||||
|
||||
void Connection::setState(WellCompletion::StateEnum state) {
|
||||
this->open_state = state;
|
||||
}
|
||||
|
||||
void Connection::updateSegment(int segment_number, double center_depth) {
|
||||
this->segment_number = segment_number;
|
||||
this->center_depth = center_depth;
|
||||
}
|
||||
|
||||
int Connection::segment() const {
|
||||
return this->segment_number;
|
||||
}
|
||||
|
||||
void Connection::scaleWellPi(double wellPi) {
|
||||
this->wPi *= wellPi;
|
||||
}
|
||||
|
||||
double Connection::wellPi() const {
|
||||
return this->wPi;
|
||||
}
|
||||
|
||||
bool Connection::operator==( const Connection& rhs ) const {
|
||||
return this->ijk == rhs.ijk
|
||||
&& this->complnum == rhs.complnum
|
||||
&& this->m_diameter == rhs.m_diameter
|
||||
&& this->m_connectionTransmissibilityFactor == rhs.m_connectionTransmissibilityFactor
|
||||
&& this->wellPi == rhs.wellPi
|
||||
&& this->m_skinFactor == rhs.m_skinFactor
|
||||
&& this->m_complnum == rhs.m_complnum
|
||||
&& this->m_CF == rhs.m_CF
|
||||
&& this->m_rw == rhs.m_rw
|
||||
&& this->wPi == rhs.wPi
|
||||
&& this->m_Kh == rhs.m_Kh
|
||||
&& this->sat_tableId == rhs.sat_tableId
|
||||
&& this->state == rhs.state
|
||||
&& this->dir == rhs.dir
|
||||
&& this->open_state == rhs.open_state
|
||||
&& this->direction == rhs.direction
|
||||
&& this->segment_number == rhs.segment_number
|
||||
&& this->center_depth == rhs.center_depth;
|
||||
}
|
||||
|
||||
@@ -239,8 +239,7 @@ namespace Opm {
|
||||
const int k = compseg.m_k;
|
||||
|
||||
Connection& connection = connection_set.getFromIJK( i, j, k );
|
||||
connection.segment_number = compseg.segment_number;
|
||||
connection.center_depth = compseg.center_depth;
|
||||
connection.updateSegment(compseg.segment_number, compseg.center_depth);
|
||||
}
|
||||
|
||||
for (size_t ic = 0; ic < connection_set.size(); ++ic) {
|
||||
|
||||
@@ -335,7 +335,7 @@ namespace Opm {
|
||||
+ ". Can not infer reference depth" );
|
||||
}
|
||||
|
||||
return completions.get( 0 ).center_depth;
|
||||
return completions.get( 0 ).depth();
|
||||
}
|
||||
|
||||
void Well::setRefDepth( size_t timestep, double depth ) {
|
||||
@@ -356,11 +356,11 @@ namespace Opm {
|
||||
|
||||
const auto& connections = this->getConnections(time_step);
|
||||
for (const auto& conn : connections) {
|
||||
auto pair = completions.find( conn.complnum );
|
||||
auto pair = completions.find( conn.complnum() );
|
||||
if (pair == completions.end())
|
||||
completions[conn.complnum] = {};
|
||||
completions[conn.complnum()] = {};
|
||||
|
||||
pair = completions.find(conn.complnum);
|
||||
pair = completions.find(conn.complnum());
|
||||
pair->second.push_back(conn);
|
||||
}
|
||||
|
||||
@@ -641,7 +641,7 @@ namespace Opm {
|
||||
|
||||
for (auto c : this->getConnections(time_step)) {
|
||||
if (match(c))
|
||||
c.complnum = complnum;
|
||||
c.setComplnum( complnum );
|
||||
|
||||
new_connections->add(c);
|
||||
}
|
||||
@@ -654,8 +654,8 @@ namespace Opm {
|
||||
if (!match_eq(c.getI(), record, "I" , -1)) return false;
|
||||
if (!match_eq(c.getJ(), record, "J" , -1)) return false;
|
||||
if (!match_eq(c.getK(), record, "K", -1)) return false;
|
||||
if (!match_ge(c.complnum, record, "C1")) return false;
|
||||
if (!match_le(c.complnum, record, "C2")) return false;
|
||||
if (!match_ge(c.complnum(), record, "C1")) return false;
|
||||
if (!match_le(c.complnum(), record, "C2")) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
@@ -664,7 +664,7 @@ namespace Opm {
|
||||
|
||||
for (auto c : this->getConnections(time_step)) {
|
||||
if (match(c))
|
||||
c.state = status;
|
||||
c.setState( status );
|
||||
|
||||
new_connections->add(c);
|
||||
}
|
||||
@@ -692,8 +692,8 @@ namespace Opm {
|
||||
void Well::handleWPIMULT(const DeckRecord& record, size_t time_step) {
|
||||
|
||||
auto match = [=]( const Connection &c) -> bool {
|
||||
if (!match_ge(c.complnum, record, "FIRST")) return false;
|
||||
if (!match_le(c.complnum, record, "LAST")) return false;
|
||||
if (!match_ge(c.complnum(), record, "FIRST")) return false;
|
||||
if (!match_le(c.complnum(), record, "LAST")) return false;
|
||||
if (!match_eq(c.getI() , record, "I", -1)) return false;
|
||||
if (!match_eq(c.getJ() , record, "J", -1)) return false;
|
||||
if (!match_eq(c.getK() , record, "K", -1)) return false;
|
||||
@@ -706,7 +706,7 @@ namespace Opm {
|
||||
|
||||
for (auto c : this->getConnections(time_step)) {
|
||||
if (match(c))
|
||||
c.wellPi *= wellPi;
|
||||
c.scaleWellPi( wellPi );
|
||||
|
||||
new_connections->add(c);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
@@ -29,6 +30,90 @@
|
||||
|
||||
namespace Opm {
|
||||
|
||||
namespace {
|
||||
|
||||
// Compute direction permutation corresponding to completion's
|
||||
// direction. First two elements of return value are directions
|
||||
// perpendicular to completion while last element is direction
|
||||
// along completion.
|
||||
inline std::array< size_t, 3> directionIndices(const Opm::WellCompletion::DirectionEnum direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case Opm::WellCompletion::DirectionEnum::X:
|
||||
return {{ 1,2,0 }};
|
||||
|
||||
case Opm::WellCompletion::DirectionEnum::Y:
|
||||
return {{ 2,0,1}};
|
||||
|
||||
case Opm::WellCompletion::DirectionEnum::Z:
|
||||
return {{ 0,1,2 }};
|
||||
}
|
||||
// All enum values should be handled above. Therefore
|
||||
// we should never reach this one. Anyway for the sake
|
||||
// of reduced warnings we throw an exception.
|
||||
throw std::invalid_argument("unhandled enum value");
|
||||
|
||||
}
|
||||
|
||||
// Permute (diagonal) permeability components according to
|
||||
// completion's direction.
|
||||
inline std::array<double,3>
|
||||
permComponents(const Opm::WellCompletion::DirectionEnum direction,
|
||||
const std::array<double,3>& perm)
|
||||
{
|
||||
const auto p = directionIndices(direction);
|
||||
|
||||
return {{ perm[ p[0] ],
|
||||
perm[ p[1] ],
|
||||
perm[ p[2] ] }};
|
||||
}
|
||||
|
||||
// Permute cell's geometric extent according to completion's
|
||||
// direction. Honour net-to-gross ratio.
|
||||
//
|
||||
// Note: 'extent' is intentionally accepted by modifiable value
|
||||
// rather than reference-to-const to support NTG manipulation.
|
||||
inline std::array<double,3>
|
||||
effectiveExtent(const Opm::WellCompletion::DirectionEnum direction,
|
||||
const double ntg,
|
||||
std::array<double,3> extent)
|
||||
{
|
||||
// Vertical extent affected by net-to-gross ratio.
|
||||
extent[2] *= ntg;
|
||||
|
||||
const auto p = directionIndices(direction);
|
||||
|
||||
std::array<double,3>
|
||||
D = {{ extent[ p[0] ] ,
|
||||
extent[ p[1] ] ,
|
||||
extent[ p[2] ] }};
|
||||
|
||||
return D;
|
||||
}
|
||||
|
||||
// Compute Peaceman's effective radius of single completion.
|
||||
inline double
|
||||
effectiveRadius(const std::array<double,3>& K,
|
||||
const std::array<double,3>& D)
|
||||
{
|
||||
const double K01 = K[0] / K[1];
|
||||
const double K10 = K[1] / K[0];
|
||||
|
||||
const double D0_sq = D[0] * D[0];
|
||||
const double D1_sq = D[1] * D[1];
|
||||
|
||||
const double num = std::sqrt((std::sqrt(K10) * D0_sq) +
|
||||
(std::sqrt(K01) * D1_sq));
|
||||
const double den = std::pow(K01, 0.25) + std::pow(K10, 0.25);
|
||||
|
||||
// Note: Analytic constant 0.28 derived for infintely sized
|
||||
// formation with repeating well placement.
|
||||
return 0.28 * (num / den);
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
WellConnections::WellConnections(int headIArg, int headJArg) :
|
||||
headI(headIArg),
|
||||
headJ(headJArg)
|
||||
@@ -47,17 +132,16 @@ namespace Opm {
|
||||
void WellConnections::addConnection(int i, int j , int k ,
|
||||
int complnum,
|
||||
double depth,
|
||||
WellCompletion::StateEnum state ,
|
||||
const Value<double>& connectionTransmissibilityFactor,
|
||||
const Value<double>& diameter,
|
||||
const Value<double>& skinFactor,
|
||||
const Value<double>& Kh,
|
||||
WellCompletion::StateEnum state,
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction)
|
||||
{
|
||||
int conn_i = (i < 0) ? this->headI : i;
|
||||
int conn_j = (j < 0) ? this->headJ : j;
|
||||
Connection conn(conn_i, conn_j, k, complnum, depth, state, connectionTransmissibilityFactor, diameter, skinFactor, Kh, satTableId, direction);
|
||||
Connection conn(conn_i, conn_j, k, complnum, depth, state, CF, Kh, rw, satTableId, direction);
|
||||
this->add(conn);
|
||||
}
|
||||
|
||||
@@ -66,10 +150,9 @@ namespace Opm {
|
||||
void WellConnections::addConnection(int i, int j , int k ,
|
||||
double depth,
|
||||
WellCompletion::StateEnum state ,
|
||||
const Value<double>& connectionTransmissibilityFactor,
|
||||
const Value<double>& diameter,
|
||||
const Value<double>& skinFactor,
|
||||
const Value<double>& Kh,
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction)
|
||||
{
|
||||
@@ -80,15 +163,19 @@ namespace Opm {
|
||||
complnum,
|
||||
depth,
|
||||
state,
|
||||
connectionTransmissibilityFactor,
|
||||
diameter,
|
||||
skinFactor,
|
||||
CF,
|
||||
Kh,
|
||||
rw,
|
||||
satTableId,
|
||||
direction);
|
||||
}
|
||||
|
||||
void WellConnections::loadCOMPDAT(const DeckRecord& record, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties) {
|
||||
const auto& permx = eclipseProperties.getDoubleGridProperty("PERMX").getData();
|
||||
const auto& permy = eclipseProperties.getDoubleGridProperty("PERMY").getData();
|
||||
const auto& permz = eclipseProperties.getDoubleGridProperty("PERMZ").getData();
|
||||
const auto& ntg = eclipseProperties.getDoubleGridProperty("NTG").getData();
|
||||
|
||||
const auto& itemI = record.getItem( "I" );
|
||||
const auto defaulted_I = itemI.defaultApplied( 0 ) || itemI.get< int >( 0 ) == 0;
|
||||
const int I = !defaulted_I ? itemI.get< int >( 0 ) - 1 : this->headI;
|
||||
@@ -100,42 +187,37 @@ namespace Opm {
|
||||
int K1 = record.getItem("K1").get< int >(0) - 1;
|
||||
int K2 = record.getItem("K2").get< int >(0) - 1;
|
||||
WellCompletion::StateEnum state = WellCompletion::StateEnumFromString( record.getItem("STATE").getTrimmedString(0) );
|
||||
Value<double> connectionTransmissibilityFactor("CompletionTransmissibilityFactor");
|
||||
Value<double> diameter("Diameter");
|
||||
Value<double> skinFactor("SkinFactor");
|
||||
Value<double> Kh("Kh");
|
||||
|
||||
const auto& satnum = eclipseProperties.getIntGridProperty("SATNUM");
|
||||
int satTableId = -1;
|
||||
bool defaultSatTable = true;
|
||||
const auto& CFItem = record.getItem("CONNECTION_TRANSMISSIBILITY_FACTOR");
|
||||
const auto& diameterItem = record.getItem("DIAMETER");
|
||||
const auto& KhItem = record.getItem("Kh");
|
||||
const auto& satTableIdItem = record.getItem("SAT_TABLE");
|
||||
const auto& r0Item = record.getItem("PR");
|
||||
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnumFromString(record.getItem("DIR").getTrimmedString(0));
|
||||
double skin_factor = record.getItem("SKIN").getSIDouble(0);
|
||||
double rw;
|
||||
|
||||
if (satTableIdItem.hasValue(0) && satTableIdItem.get < int > (0) > 0)
|
||||
{
|
||||
const auto& connectionTransmissibilityFactorItem = record.getItem("CONNECTION_TRANSMISSIBILITY_FACTOR");
|
||||
const auto& diameterItem = record.getItem("DIAMETER");
|
||||
const auto& skinFactorItem = record.getItem("SKIN");
|
||||
const auto& KhItem = record.getItem("Kh");
|
||||
const auto& satTableIdItem = record.getItem("SAT_TABLE");
|
||||
|
||||
if (connectionTransmissibilityFactorItem.hasValue(0) && connectionTransmissibilityFactorItem.getSIDouble(0) > 0)
|
||||
connectionTransmissibilityFactor.setValue(connectionTransmissibilityFactorItem.getSIDouble(0));
|
||||
|
||||
if (diameterItem.hasValue(0))
|
||||
diameter.setValue( diameterItem.getSIDouble(0));
|
||||
|
||||
if (skinFactorItem.hasValue(0))
|
||||
skinFactor.setValue( skinFactorItem.get< double >(0));
|
||||
|
||||
if (KhItem.hasValue(0) && (KhItem.get< double >(0) > 0.0))
|
||||
Kh.setValue( KhItem.getSIDouble(0));
|
||||
|
||||
if (satTableIdItem.hasValue(0) && satTableIdItem.get < int > (0) > 0)
|
||||
{
|
||||
satTableId = satTableIdItem.get< int >(0);
|
||||
defaultSatTable = false;
|
||||
}
|
||||
satTableId = satTableIdItem.get< int >(0);
|
||||
defaultSatTable = false;
|
||||
}
|
||||
|
||||
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnumFromString(record.getItem("DIR").getTrimmedString(0));
|
||||
if (diameterItem.hasValue(0))
|
||||
rw = 0.50 * diameterItem.getSIDouble(0);
|
||||
else
|
||||
// The Eclipse100 manual does not specify a default value for the wellbore
|
||||
// diameter, but the Opm codebase has traditionally implemented a default
|
||||
// value of one foot. The same default value is used by Eclipse300.
|
||||
rw = 0.5*unit::feet;
|
||||
|
||||
for (int k = K1; k <= K2; k++) {
|
||||
double CF = -1;
|
||||
double Kh = -1;
|
||||
|
||||
if (defaultSatTable)
|
||||
satTableId = satnum.iget(grid.getGlobalIndex(I,J,k));
|
||||
|
||||
@@ -143,6 +225,50 @@ namespace Opm {
|
||||
return c.sameCoordinate( I,J,k );
|
||||
};
|
||||
|
||||
if (KhItem.hasValue(0) && KhItem.getSIDouble(0) > 0.0)
|
||||
Kh = KhItem.getSIDouble(0);
|
||||
|
||||
if (CFItem.hasValue(0) && CFItem.getSIDouble(0) > 0.0)
|
||||
CF = CFItem.getSIDouble(0);
|
||||
|
||||
/* We start with the absolute happy path; both CF and Kh are explicitly given in the deck. */
|
||||
if (CF > 0 && Kh > 0)
|
||||
goto CF_done;
|
||||
|
||||
|
||||
/* We must calculate CF and Kh from the items in the COMPDAT record and cell properties. */
|
||||
{
|
||||
// Angle of completion exposed to flow. We assume centre
|
||||
// placement so there's complete exposure (= 2\pi).
|
||||
const double angle = 6.2831853071795864769252867665590057683943387987502116419498;
|
||||
size_t global_index = grid.getGlobalIndex(I,J,k);
|
||||
std::array<double,3> cell_perm = {{ permx[global_index], permy[global_index], permz[global_index]}};
|
||||
std::array<double,3> cell_size = grid.getCellDims(global_index);
|
||||
double r0;
|
||||
const auto& K = permComponents(direction, cell_perm);
|
||||
const auto& D = effectiveExtent(direction, ntg[global_index], cell_size);
|
||||
|
||||
if (r0Item.hasValue(0))
|
||||
r0 = r0Item.getSIDouble(0);
|
||||
else
|
||||
r0 = effectiveRadius(K,D);
|
||||
|
||||
if (CF < 0) {
|
||||
if (Kh < 0)
|
||||
Kh = std::sqrt(K[0] * K[1]) * D[2];
|
||||
CF = angle * Kh / (std::log(r0 / std::min(rw, r0)) + skin_factor);
|
||||
} else {
|
||||
if (KhItem.defaultApplied(0) || KhItem.getSIDouble(0) < 0) {
|
||||
Kh = CF * (std::log(r0 / std::min(r0, rw)) + skin_factor) / angle;
|
||||
} else {
|
||||
if (Kh < 0)
|
||||
Kh = std::sqrt(K[0] * K[1]) * D[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CF_done:
|
||||
auto prev = std::find_if( this->m_connections.begin(),
|
||||
this->m_connections.end(),
|
||||
same_ijk );
|
||||
@@ -151,24 +277,22 @@ namespace Opm {
|
||||
this->addConnection(I,J,k,
|
||||
grid.getCellDepth( I,J,k ),
|
||||
state,
|
||||
connectionTransmissibilityFactor,
|
||||
diameter,
|
||||
skinFactor,
|
||||
CF,
|
||||
Kh,
|
||||
rw,
|
||||
satTableId,
|
||||
direction );
|
||||
} else {
|
||||
// The complnum value carries over; the rest of the state is fully specified by
|
||||
// the current COMPDAT keyword.
|
||||
int complnum = prev->complnum;
|
||||
int complnum = prev->complnum();
|
||||
*prev = Connection(I,J,k,
|
||||
complnum,
|
||||
grid.getCellDepth(I,J,k),
|
||||
state,
|
||||
connectionTransmissibilityFactor,
|
||||
diameter,
|
||||
skinFactor,
|
||||
CF,
|
||||
Kh,
|
||||
rw,
|
||||
satTableId,
|
||||
direction );
|
||||
}
|
||||
@@ -183,9 +307,14 @@ namespace Opm {
|
||||
}
|
||||
|
||||
const Connection& WellConnections::get(size_t index) const {
|
||||
return this->m_connections.at( index );
|
||||
return (*this)[index];
|
||||
}
|
||||
|
||||
const Connection& WellConnections::operator[](size_t index) const {
|
||||
return this->m_connections.at(index);
|
||||
}
|
||||
|
||||
|
||||
const Connection& WellConnections::getFromIJK(const int i, const int j, const int k) const {
|
||||
for (size_t ic = 0; ic < size(); ++ic) {
|
||||
if (get(ic).sameCoordinate(i, j, k)) {
|
||||
@@ -212,7 +341,7 @@ namespace Opm {
|
||||
|
||||
bool WellConnections::allConnectionsShut( ) const {
|
||||
auto shut = []( const Connection& c ) {
|
||||
return c.state == WellCompletion::StateEnum::SHUT;
|
||||
return c.state() == WellCompletion::StateEnum::SHUT;
|
||||
};
|
||||
|
||||
return std::all_of( this->m_connections.begin(),
|
||||
@@ -243,7 +372,7 @@ namespace Opm {
|
||||
|
||||
for (size_t pos = 1; pos < m_connections.size() - 1; ++pos) {
|
||||
const auto& prev = m_connections[pos - 1];
|
||||
const double prevz = prev.center_depth;
|
||||
const double prevz = prev.depth();
|
||||
size_t next_index = findClosestConnection(prev.getI(), prev.getJ(), prevz, pos);
|
||||
std::swap(m_connections[next_index], m_connections[pos]);
|
||||
}
|
||||
@@ -259,7 +388,7 @@ namespace Opm {
|
||||
for (size_t pos = start_pos; pos < m_connections.size(); ++pos) {
|
||||
const auto& connection = m_connections[ pos ];
|
||||
|
||||
const double depth = connection.center_depth;
|
||||
const double depth = connection.depth();
|
||||
const int ci = connection.getI();
|
||||
const int cj = connection.getJ();
|
||||
// Using square of distance to avoid non-integer arithmetics.
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
|
||||
#include <ert/ecl/Smspec.hpp>
|
||||
#include <ert/ecl/ecl_smspec.h>
|
||||
|
||||
#include <iostream>
|
||||
@@ -141,15 +140,15 @@ void handleMissingGroup( const ParseContext& parseContext , const std::string& k
|
||||
parseContext.handleError( ParseContext::SUMMARY_UNKNOWN_GROUP , msg );
|
||||
}
|
||||
|
||||
inline void keywordW( std::vector< ERT::smspec_node >& list,
|
||||
inline void keywordW( SummaryConfig::keyword_list& list,
|
||||
const ParseContext& parseContext,
|
||||
const DeckKeyword& keyword,
|
||||
const Schedule& schedule ) {
|
||||
|
||||
const auto type = ECL_SMSPEC_WELL_VAR;
|
||||
const auto hasValue = []( const DeckKeyword& kw ) {
|
||||
return kw.getDataRecord().getDataItem().hasValue( 0 );
|
||||
};
|
||||
const std::array<int,3> dummy_dims = {1,1,1};
|
||||
|
||||
if (keyword.size() && hasValue(keyword)) {
|
||||
for( const std::string& pattern : keyword.getStringData()) {
|
||||
@@ -159,20 +158,32 @@ inline void keywordW( std::vector< ERT::smspec_node >& list,
|
||||
handleMissingWell( parseContext, keyword.name(), pattern );
|
||||
|
||||
for( const auto* well : wells )
|
||||
list.emplace_back( type, well->name(), keyword.name() );
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_WELL_VAR,
|
||||
well->name().c_str(),
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dummy_dims.data(),
|
||||
0,0,0)));
|
||||
}
|
||||
} else
|
||||
for (const auto* well : schedule.getWells())
|
||||
list.emplace_back(type, well->name(), keyword.name());
|
||||
}
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_WELL_VAR,
|
||||
well->name().c_str(),
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dummy_dims.data(),
|
||||
0,0,0)));
|
||||
}
|
||||
|
||||
inline void keywordG( std::vector< ERT::smspec_node >& list,
|
||||
|
||||
inline void keywordG( SummaryConfig::keyword_list& list,
|
||||
const ParseContext& parseContext,
|
||||
const DeckKeyword& keyword,
|
||||
const Schedule& schedule ) {
|
||||
|
||||
const auto type = ECL_SMSPEC_GROUP_VAR;
|
||||
|
||||
const std::array<int,3> dummy_dims = {1,1,1};
|
||||
if( keyword.name() == "GMWSET" ) return;
|
||||
|
||||
if( keyword.size() == 0 ||
|
||||
@@ -180,9 +191,14 @@ inline void keywordG( std::vector< ERT::smspec_node >& list,
|
||||
|
||||
for( const auto& group : schedule.getGroups() ) {
|
||||
if( group->name() == "FIELD" ) continue;
|
||||
list.emplace_back( type, group->name(), keyword.name() );
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_GROUP_VAR,
|
||||
group->name().c_str(),
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dummy_dims.data(),
|
||||
0, 0, 0)));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -190,17 +206,33 @@ inline void keywordG( std::vector< ERT::smspec_node >& list,
|
||||
|
||||
for( const std::string& group : item.getData< std::string >() ) {
|
||||
if( schedule.hasGroup( group ) )
|
||||
list.emplace_back( ECL_SMSPEC_GROUP_VAR, group, keyword.name() );
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_GROUP_VAR,
|
||||
group.c_str(),
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dummy_dims.data(),
|
||||
0, 0, 0)));
|
||||
|
||||
|
||||
else
|
||||
handleMissingGroup( parseContext, keyword.name(), group );
|
||||
}
|
||||
}
|
||||
|
||||
inline void keywordF( std::vector< ERT::smspec_node >& list,
|
||||
const DeckKeyword& keyword ) {
|
||||
if( keyword.name() == "FMWSET" ) return;
|
||||
list.emplace_back( keyword.name() );
|
||||
}
|
||||
inline void keywordF( SummaryConfig::keyword_list& list,
|
||||
const DeckKeyword& keyword ) {
|
||||
const std::array<int,3> dummy_dims = {1,1,1};
|
||||
if( keyword.name() == "FMWSET" ) return;
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_FIELD_VAR,
|
||||
NULL,
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dummy_dims.data(),
|
||||
0, 0, 0)));
|
||||
|
||||
}
|
||||
|
||||
inline std::array< int, 3 > getijk( const DeckRecord& record,
|
||||
int offset = 0 ) {
|
||||
@@ -212,19 +244,27 @@ inline std::array< int, 3 > getijk( const DeckRecord& record,
|
||||
}
|
||||
|
||||
inline std::array< int, 3 > getijk( const Connection& completion ) {
|
||||
return {{ completion.getI(), completion.getJ(), completion.getK() }};
|
||||
return { { completion.getI(), completion.getJ(), completion.getK() }};
|
||||
}
|
||||
|
||||
inline void keywordB( std::vector< ERT::smspec_node >& list,
|
||||
const DeckKeyword& keyword,
|
||||
const GridDims& dims) {
|
||||
inline void keywordB( SummaryConfig::keyword_list& list,
|
||||
const DeckKeyword& keyword,
|
||||
const GridDims& dims) {
|
||||
for( const auto& record : keyword ) {
|
||||
auto ijk = getijk( record );
|
||||
list.emplace_back( keyword.name(), dims.getNXYZ().data(), ijk.data() );
|
||||
int global_index = 1 + dims.getGlobalIndex(ijk[0], ijk[1], ijk[2]);
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc(ECL_SMSPEC_BLOCK_VAR,
|
||||
NULL,
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dims.getNXYZ().data(),
|
||||
global_index,0,0)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline void keywordR( std::vector< ERT::smspec_node >& list,
|
||||
inline void keywordR( SummaryConfig::keyword_list& list,
|
||||
const DeckKeyword& keyword,
|
||||
const TableManager& tables,
|
||||
const GridDims& dims) {
|
||||
@@ -249,26 +289,41 @@ inline void keywordR( std::vector< ERT::smspec_node >& list,
|
||||
|
||||
for( const int region : regions ) {
|
||||
if (region >= 1 && region <= static_cast<int>(numfip))
|
||||
list.emplace_back( keyword.name(), dims.getNXYZ().data(), region );
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_REGION_VAR,
|
||||
NULL,
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dims.getNXYZ().data(),
|
||||
region,
|
||||
0, 0)));
|
||||
else
|
||||
throw std::invalid_argument("Illegal region value: " + std::to_string( region ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void keywordMISC( std::vector< ERT::smspec_node >& list,
|
||||
const DeckKeyword& keyword)
|
||||
inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
const DeckKeyword& keyword)
|
||||
{
|
||||
const std::array<int,3> dummy_dims = {1,1,1};
|
||||
if (meta_keywords.count( keyword.name() ) == 0)
|
||||
list.emplace_back( keyword.name() );
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_MISC_VAR,
|
||||
NULL,
|
||||
keyword.name().c_str(),
|
||||
"",
|
||||
":",
|
||||
dummy_dims.data(),
|
||||
0,
|
||||
0, 0)));
|
||||
}
|
||||
|
||||
|
||||
inline void keywordC( std::vector< ERT::smspec_node >& list,
|
||||
const ParseContext& parseContext,
|
||||
const DeckKeyword& keyword,
|
||||
const Schedule& schedule,
|
||||
const GridDims& dims) {
|
||||
inline void keywordC( SummaryConfig::keyword_list& list,
|
||||
const ParseContext& parseContext,
|
||||
const DeckKeyword& keyword,
|
||||
const Schedule& schedule,
|
||||
const GridDims& dims) {
|
||||
|
||||
const auto& keywordstring = keyword.name();
|
||||
const auto last_timestep = schedule.getTimeMap().last();
|
||||
@@ -297,25 +352,41 @@ inline void keywordC( std::vector< ERT::smspec_node >& list,
|
||||
auto cijk = getijk( connection );
|
||||
|
||||
if( record.getItem( 1 ).defaultApplied( 0 ) ) {
|
||||
list.emplace_back( keywordstring, name, dims.getNXYZ().data(), cijk.data() );
|
||||
}
|
||||
else {
|
||||
int global_index = 1 + dims.getGlobalIndex(cijk[0], cijk[1], cijk[2]);
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_COMPLETION_VAR,
|
||||
name.c_str(),
|
||||
keywordstring.c_str(),
|
||||
"",
|
||||
":",
|
||||
dims.getNXYZ().data(),
|
||||
global_index,
|
||||
0, 0)));
|
||||
} else {
|
||||
/* block coordinates specified */
|
||||
auto recijk = getijk( record, 1 );
|
||||
if( std::equal( recijk.begin(), recijk.end(), cijk.begin() ) )
|
||||
list.emplace_back( keywordstring, name, dims.getNXYZ().data(), cijk.data() );
|
||||
if( std::equal( recijk.begin(), recijk.end(), cijk.begin() ) ) {
|
||||
int global_index = 1 + dims.getGlobalIndex(recijk[0], recijk[1], recijk[2]);
|
||||
list.push_back( SummaryConfig::keyword_type( smspec_node_alloc( ECL_SMSPEC_COMPLETION_VAR,
|
||||
name.c_str(),
|
||||
keywordstring.c_str(),
|
||||
"",
|
||||
":",
|
||||
dims.getNXYZ().data(),
|
||||
global_index,
|
||||
0, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void handleKW( std::vector< ERT::smspec_node >& list,
|
||||
const DeckKeyword& keyword,
|
||||
const Schedule& schedule,
|
||||
const TableManager& tables,
|
||||
const ParseContext& parseContext,
|
||||
const GridDims& dims) {
|
||||
inline void handleKW( SummaryConfig::keyword_list& list,
|
||||
const DeckKeyword& keyword,
|
||||
const Schedule& schedule,
|
||||
const TableManager& tables,
|
||||
const ParseContext& parseContext,
|
||||
const GridDims& dims) {
|
||||
const auto var_type = ecl_smspec_identify_var_type( keyword.name().c_str() );
|
||||
|
||||
switch( var_type ) {
|
||||
@@ -331,25 +402,23 @@ inline void handleKW( std::vector< ERT::smspec_node >& list,
|
||||
}
|
||||
}
|
||||
|
||||
inline void uniq( std::vector< ERT::smspec_node >& vec ) {
|
||||
const auto lt = []( const ERT::smspec_node& lhs,
|
||||
const ERT::smspec_node& rhs ) {
|
||||
return ERT::smspec_node::cmp( lhs, rhs ) < 0;
|
||||
inline void uniq( SummaryConfig::keyword_list& vec ) {
|
||||
const auto lt = []( const SummaryConfig::keyword_type& lhs,
|
||||
const SummaryConfig::keyword_type& rhs ) {
|
||||
return smspec_node_cmp(lhs.get(), rhs.get()) < 0;
|
||||
};
|
||||
|
||||
const auto eq = []( const ERT::smspec_node& lhs,
|
||||
const ERT::smspec_node& rhs ) {
|
||||
return ERT::smspec_node::cmp( lhs, rhs ) == 0;
|
||||
const auto eq = []( const SummaryConfig::keyword_type& lhs,
|
||||
const SummaryConfig::keyword_type& rhs ) {
|
||||
return smspec_node_equal(lhs.get(), rhs.get());
|
||||
};
|
||||
|
||||
std::sort( vec.begin(), vec.end(), lt );
|
||||
auto logical_end = std::unique( vec.begin(), vec.end(), eq );
|
||||
vec.erase( logical_end, vec.end() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
SummaryConfig::SummaryConfig( const Deck& deck,
|
||||
const Schedule& schedule,
|
||||
const TableManager& tables,
|
||||
@@ -373,8 +442,8 @@ SummaryConfig::SummaryConfig( const Deck& deck,
|
||||
|
||||
uniq( this->keywords );
|
||||
for (const auto& kw: this->keywords) {
|
||||
this->short_keywords.insert( kw.keyword() );
|
||||
this->summary_keywords.insert( kw.key1() );
|
||||
this->short_keywords.insert( smspec_node_get_keyword( kw.get() ));
|
||||
this->summary_keywords.insert( smspec_node_get_gen_key1( kw.get() ));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"name" : "MINPVFIL" , "sections" : ["GRID"], "size" : 1 , "items" : [{"name" : "VALUE" , "value_type" : "DOUBLE" , "default" : 0.000001, "dimension" : "LiquidSurfaceVolume"}]}
|
||||
{"name" : "MINPVFIL" , "sections" : ["GRID"], "size" : 1 , "items" : [{"name" : "VALUE" , "value_type" : "DOUBLE" , "default" : 0.000001, "dimension" : "ReservoirVolume"}]}
|
||||
|
||||
435
tests/SPE1CASE1.DATA
Normal file
435
tests/SPE1CASE1.DATA
Normal file
@@ -0,0 +1,435 @@
|
||||
-- This reservoir simulation deck is made available under the Open Database
|
||||
-- License: http://opendatacommons.org/licenses/odbl/1.0/. Any rights in
|
||||
-- individual contents of the database are licensed under the Database Contents
|
||||
-- License: http://opendatacommons.org/licenses/dbcl/1.0/
|
||||
|
||||
-- Copyright (C) 2015 Statoil
|
||||
|
||||
-- This simulation is based on the data given in
|
||||
-- 'Comparison of Solutions to a Three-Dimensional
|
||||
-- Black-Oil Reservoir Simulation Problem' by Aziz S. Odeh,
|
||||
-- Journal of Petroleum Technology, January 1981
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
------------------------ SPE1 - CASE 1 ------------------------------------
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
RUNSPEC
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
TITLE
|
||||
SPE1 - CASE 1
|
||||
|
||||
DIMENS
|
||||
10 10 3 /
|
||||
|
||||
-- The number of equilibration regions is inferred from the EQLDIMS
|
||||
-- keyword.
|
||||
EQLDIMS
|
||||
/
|
||||
|
||||
-- The number of PVTW tables is inferred from the TABDIMS keyword;
|
||||
-- when no data is included in the keyword the default values are used.
|
||||
TABDIMS
|
||||
/
|
||||
|
||||
OIL
|
||||
GAS
|
||||
WATER
|
||||
DISGAS
|
||||
-- As seen from figure 4 in Odeh, GOR is increasing with time,
|
||||
-- which means that dissolved gas is present
|
||||
|
||||
FIELD
|
||||
|
||||
START
|
||||
1 'JAN' 2015 /
|
||||
|
||||
WELLDIMS
|
||||
-- Item 1: maximum number of wells in the model
|
||||
-- - there are two wells in the problem; injector and producer
|
||||
-- Item 2: maximum number of grid blocks connected to any one well
|
||||
-- - must be one as the wells are located at specific grid blocks
|
||||
-- Item 3: maximum number of groups in the model
|
||||
-- - we are dealing with only one 'group'
|
||||
-- Item 4: maximum number of wells in any one group
|
||||
-- - there must be two wells in a group as there are two wells in total
|
||||
2 1 1 2 /
|
||||
|
||||
UNIFOUT
|
||||
|
||||
GRID
|
||||
|
||||
-- The INIT keyword is used to request an .INIT file. The .INIT file
|
||||
-- is written before the simulation actually starts, and contains grid
|
||||
-- properties and saturation tables as inferred from the input
|
||||
-- deck. There are no other keywords which can be used to configure
|
||||
-- exactly what is written to the .INIT file.
|
||||
INIT
|
||||
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
NOECHO
|
||||
|
||||
DX
|
||||
-- There are in total 300 cells with length 1000ft in x-direction
|
||||
300*1000 /
|
||||
DY
|
||||
-- There are in total 300 cells with length 1000ft in y-direction
|
||||
300*1000 /
|
||||
DZ
|
||||
-- The layers are 20, 30 and 50 ft thick, in each layer there are 100 cells
|
||||
100*20 100*30 100*50 /
|
||||
|
||||
TOPS
|
||||
-- The depth of the top of each grid block
|
||||
100*8325 /
|
||||
|
||||
PORO
|
||||
-- Constant porosity of 0.3 throughout all 300 grid cells
|
||||
300*0.3 /
|
||||
|
||||
PERMX
|
||||
-- The layers have perm. 500mD, 50mD and 200mD, respectively.
|
||||
100*500 100*50 100*200 /
|
||||
|
||||
PERMY
|
||||
-- Equal to PERMX
|
||||
100*500 100*50 100*200 /
|
||||
|
||||
PERMZ
|
||||
-- Cannot find perm. in z-direction in Odeh's paper
|
||||
-- For the time being, we will assume PERMZ equal to PERMX and PERMY:
|
||||
100*500 100*50 100*200 /
|
||||
ECHO
|
||||
|
||||
PROPS
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
PVTW
|
||||
-- Item 1: pressure reference (psia)
|
||||
-- Item 2: water FVF (rb per bbl or rb per stb)
|
||||
-- Item 3: water compressibility (psi^{-1})
|
||||
-- Item 4: water viscosity (cp)
|
||||
-- Item 5: water 'viscosibility' (psi^{-1})
|
||||
|
||||
-- Using values from Norne:
|
||||
-- In METRIC units:
|
||||
-- 277.0 1.038 4.67E-5 0.318 0.0 /
|
||||
-- In FIELD units:
|
||||
4017.55 1.038 3.22E-6 0.318 0.0 /
|
||||
|
||||
ROCK
|
||||
-- Item 1: reference pressure (psia)
|
||||
-- Item 2: rock compressibility (psi^{-1})
|
||||
|
||||
-- Using values from table 1 in Odeh:
|
||||
14.7 3E-6 /
|
||||
|
||||
SWOF
|
||||
-- Column 1: water saturation
|
||||
-- - this has been set to (almost) equally spaced values from 0.12 to 1
|
||||
-- Column 2: water relative permeability
|
||||
-- - generated from the Corey-type approx. formula
|
||||
-- the coeffisient is set to 10e-5, S_{orw}=0 and S_{wi}=0.12
|
||||
-- Column 3: oil relative permeability when only oil and water are present
|
||||
-- - we will use the same values as in column 3 in SGOF.
|
||||
-- This is not really correct, but since only the first
|
||||
-- two values are of importance, this does not really matter
|
||||
-- Column 4: water-oil capillary pressure (psi)
|
||||
|
||||
0.12 0 1 0
|
||||
0.18 4.64876033057851E-008 1 0
|
||||
0.24 0.000000186 0.997 0
|
||||
0.3 4.18388429752066E-007 0.98 0
|
||||
0.36 7.43801652892562E-007 0.7 0
|
||||
0.42 1.16219008264463E-006 0.35 0
|
||||
0.48 1.67355371900826E-006 0.2 0
|
||||
0.54 2.27789256198347E-006 0.09 0
|
||||
0.6 2.97520661157025E-006 0.021 0
|
||||
0.66 3.7654958677686E-006 0.01 0
|
||||
0.72 4.64876033057851E-006 0.001 0
|
||||
0.78 0.000005625 0.0001 0
|
||||
0.84 6.69421487603306E-006 0 0
|
||||
0.91 8.05914256198347E-006 0 0
|
||||
1 0.00001 0 0 /
|
||||
|
||||
|
||||
SGOF
|
||||
-- Column 1: gas saturation
|
||||
-- Column 2: gas relative permeability
|
||||
-- Column 3: oil relative permeability when oil, gas and connate water are present
|
||||
-- Column 4: oil-gas capillary pressure (psi)
|
||||
-- - stated to be zero in Odeh's paper
|
||||
|
||||
-- Values in column 1-3 are taken from table 3 in Odeh's paper:
|
||||
0 0 1 0
|
||||
0.001 0 1 0
|
||||
0.02 0 0.997 0
|
||||
0.05 0.005 0.980 0
|
||||
0.12 0.025 0.700 0
|
||||
0.2 0.075 0.350 0
|
||||
0.25 0.125 0.200 0
|
||||
0.3 0.190 0.090 0
|
||||
0.4 0.410 0.021 0
|
||||
0.45 0.60 0.010 0
|
||||
0.5 0.72 0.001 0
|
||||
0.6 0.87 0.0001 0
|
||||
0.7 0.94 0.000 0
|
||||
0.85 0.98 0.000 0
|
||||
0.88 0.984 0.000 0 /
|
||||
--1.00 1.0 0.000 0 /
|
||||
-- Warning from Eclipse: first sat. value in SWOF + last sat. value in SGOF
|
||||
-- must not be greater than 1, but Eclipse still runs
|
||||
-- Flow needs the sum to be excactly 1 so I added a row with gas sat. = 0.88
|
||||
-- The corresponding krg value was estimated by assuming linear rel. between
|
||||
-- gas sat. and krw. between gas sat. 0.85 and 1.00 (the last two values given)
|
||||
|
||||
DENSITY
|
||||
-- Density (lb per ft³) at surface cond. of
|
||||
-- oil, water and gas, respectively (in that order)
|
||||
|
||||
-- Using values from Norne:
|
||||
-- In METRIC units:
|
||||
-- 859.5 1033.0 0.854 /
|
||||
-- In FIELD units:
|
||||
53.66 64.49 0.0533 /
|
||||
|
||||
PVDG
|
||||
-- Column 1: gas phase pressure (psia)
|
||||
-- Column 2: gas formation volume factor (rb per Mscf)
|
||||
-- - in Odeh's paper the units are said to be given in rb per bbl,
|
||||
-- but this is assumed to be a mistake: FVF-values in Odeh's paper
|
||||
-- are given in rb per scf, not rb per bbl. This will be in
|
||||
-- agreement with conventions
|
||||
-- Column 3: gas viscosity (cP)
|
||||
|
||||
-- Using values from lower right table in Odeh's table 2:
|
||||
14.700 166.666 0.008000
|
||||
264.70 12.0930 0.009600
|
||||
514.70 6.27400 0.011200
|
||||
1014.7 3.19700 0.014000
|
||||
2014.7 1.61400 0.018900
|
||||
2514.7 1.29400 0.020800
|
||||
3014.7 1.08000 0.022800
|
||||
4014.7 0.81100 0.026800
|
||||
5014.7 0.64900 0.030900
|
||||
9014.7 0.38600 0.047000 /
|
||||
|
||||
PVTO
|
||||
-- Column 1: dissolved gas-oil ratio (Mscf per stb)
|
||||
-- Column 2: bubble point pressure (psia)
|
||||
-- Column 3: oil FVF for saturated oil (rb per stb)
|
||||
-- Column 4: oil viscosity for saturated oil (cP)
|
||||
|
||||
-- Use values from top left table in Odeh's table 2:
|
||||
0.0010 14.7 1.0620 1.0400 /
|
||||
0.0905 264.7 1.1500 0.9750 /
|
||||
0.1800 514.7 1.2070 0.9100 /
|
||||
0.3710 1014.7 1.2950 0.8300 /
|
||||
0.6360 2014.7 1.4350 0.6950 /
|
||||
0.7750 2514.7 1.5000 0.6410 /
|
||||
0.9300 3014.7 1.5650 0.5940 /
|
||||
1.2700 4014.7 1.6950 0.5100
|
||||
9014.7 1.5790 0.7400 /
|
||||
1.6180 5014.7 1.8270 0.4490
|
||||
9014.7 1.7370 0.6310 /
|
||||
-- It is required to enter data for undersaturated oil for the highest GOR
|
||||
-- (i.e. the last row) in the PVTO table.
|
||||
-- In order to fulfill this requirement, values for oil FVF and viscosity
|
||||
-- at 9014.7psia and GOR=1.618 for undersaturated oil have been approximated:
|
||||
-- It has been assumed that there is a linear relation between the GOR
|
||||
-- and the FVF when keeping the pressure constant at 9014.7psia.
|
||||
-- From Odeh we know that (at 9014.7psia) the FVF is 2.357 at GOR=2.984
|
||||
-- for saturated oil and that the FVF is 1.579 at GOR=1.27 for undersaturated oil,
|
||||
-- so it is possible to use the assumption described above.
|
||||
-- An equivalent approximation for the viscosity has been used.
|
||||
/
|
||||
|
||||
SOLUTION
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
EQUIL
|
||||
-- Item 1: datum depth (ft)
|
||||
-- Item 2: pressure at datum depth (psia)
|
||||
-- - Odeh's table 1 says that initial reservoir pressure is
|
||||
-- 4800 psi at 8400ft, which explains choice of item 1 and 2
|
||||
-- Item 3: depth of water-oil contact (ft)
|
||||
-- - chosen to be directly under the reservoir
|
||||
-- Item 4: oil-water capillary pressure at the water oil contact (psi)
|
||||
-- - given to be 0 in Odeh's paper
|
||||
-- Item 5: depth of gas-oil contact (ft)
|
||||
-- - chosen to be directly above the reservoir
|
||||
-- Item 6: gas-oil capillary pressure at gas-oil contact (psi)
|
||||
-- - given to be 0 in Odeh's paper
|
||||
-- Item 7: RSVD-table
|
||||
-- Item 8: RVVD-table
|
||||
-- Item 9: Set to 0 as this is the only value supported by OPM
|
||||
|
||||
-- Item #: 1 2 3 4 5 6 7 8 9
|
||||
8400 4800 8450 0 8300 0 1 0 0 /
|
||||
|
||||
RSVD
|
||||
-- Dissolved GOR is initially constant with depth through the reservoir.
|
||||
-- The reason is that the initial reservoir pressure given is higher
|
||||
---than the bubble point presssure of 4014.7psia, meaning that there is no
|
||||
-- free gas initially present.
|
||||
8300 1.270
|
||||
8450 1.270 /
|
||||
|
||||
SUMMARY
|
||||
-- -------------------------------------------------------------------------
|
||||
|
||||
-- 1a) Oil rate vs time
|
||||
FOPR
|
||||
-- Field Oil Production Rate
|
||||
|
||||
-- 1b) GOR vs time
|
||||
WGOR
|
||||
-- Well Gas-Oil Ratio
|
||||
'PROD'
|
||||
/
|
||||
-- Using FGOR instead of WGOR:PROD results in the same graph
|
||||
FGOR
|
||||
|
||||
-- 2a) Pressures of the cell where the injector and producer are located
|
||||
BPR
|
||||
1 1 1 /
|
||||
10 10 3 /
|
||||
/
|
||||
|
||||
-- 2b) Gas saturation at grid points given in Odeh's paper
|
||||
BGSAT
|
||||
1 1 1 /
|
||||
1 1 2 /
|
||||
1 1 3 /
|
||||
10 1 1 /
|
||||
10 1 2 /
|
||||
10 1 3 /
|
||||
10 10 1 /
|
||||
10 10 2 /
|
||||
10 10 3 /
|
||||
/
|
||||
|
||||
-- In order to compare Eclipse with Flow:
|
||||
WBHP
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WGIR
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WGIT
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WGPR
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WGPT
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WOIR
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WOIT
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WOPR
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WOPT
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WWIR
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WWIT
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WWPR
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
WWPT
|
||||
'INJ'
|
||||
'PROD'
|
||||
/
|
||||
SCHEDULE
|
||||
-- -------------------------------------------------------------------------
|
||||
RPTSCHED
|
||||
'PRES' 'SGAS' 'RS' 'WELLS' 'WELSPECS' /
|
||||
|
||||
RPTRST
|
||||
'BASIC=1' /
|
||||
|
||||
|
||||
-- If no resolution (i.e. case 1), the two following lines must be added:
|
||||
DRSDT
|
||||
0 /
|
||||
-- if DRSDT is set to 0, GOR cannot rise and free gas does not
|
||||
-- dissolve in undersaturated oil -> constant bubble point pressure
|
||||
|
||||
WELSPECS
|
||||
-- Item #: 1 2 3 4 5 6
|
||||
'PROD' 'G1' 10 10 8400 'OIL' /
|
||||
'INJ' 'G1' 1 1 8335 'GAS' /
|
||||
/
|
||||
-- Coordinates in item 3-4 are retrieved from Odeh's figure 1 and 2
|
||||
-- Note that the depth at the midpoint of the well grid blocks
|
||||
-- has been used as reference depth for bottom hole pressure in item 5
|
||||
|
||||
COMPDAT
|
||||
-- Item #: 1 2 3 4 5 6 7 8 9
|
||||
'PROD' 10 10 3 3 'OPEN' 1* 1* 0.5 /
|
||||
'INJ' 1 1 1 1 'OPEN' 1* 1* 0.5 /
|
||||
/
|
||||
-- Coordinates in item 2-5 are retreived from Odeh's figure 1 and 2
|
||||
-- Item 9 is the well bore internal diameter,
|
||||
-- the radius is given to be 0.25ft in Odeh's paper
|
||||
|
||||
|
||||
WCONPROD
|
||||
-- Item #:1 2 3 4 5 9
|
||||
'PROD' 'OPEN' 'ORAT' 20000 4* 1000 /
|
||||
/
|
||||
-- It is stated in Odeh's paper that the maximum oil prod. rate
|
||||
-- is 20 000stb per day which explains the choice of value in item 4.
|
||||
-- The items > 4 are defaulted with the exception of item 9,
|
||||
-- the BHP lower limit, which is given to be 1000psia in Odeh's paper
|
||||
|
||||
WCONINJE
|
||||
-- Item #:1 2 3 4 5 6 7
|
||||
'INJ' 'GAS' 'OPEN' 'RATE' 100000 1* 9014 /
|
||||
/
|
||||
-- Stated in Odeh that gas inj. rate (item 5) is 100MMscf per day
|
||||
-- BHP upper limit (item 7) should not be exceeding the highest
|
||||
-- pressure in the PVT table=9014.7psia (default is 100 000psia)
|
||||
|
||||
TSTEP
|
||||
--Advance the simulater once a month for TEN years:
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31
|
||||
31 28 31 30 31 30 31 31 30 31 30 31 /
|
||||
|
||||
--Advance the simulator once a year for TEN years:
|
||||
--10*365 /
|
||||
|
||||
END
|
||||
6758
tests/SPE9_CP_PACKED.DATA
Normal file
6758
tests/SPE9_CP_PACKED.DATA
Normal file
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
@@ -36,6 +37,9 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellConnections.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -54,22 +58,6 @@ inline std::ostream& operator<<( std::ostream& stream, const WellConnections& cs
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(testGetFunctions) {
|
||||
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
|
||||
Opm::Connection completion(10,11,12, 1, 0.0, Opm::WellCompletion::OPEN,Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",17.29), 0, dir);
|
||||
BOOST_CHECK_EQUAL( 10 , completion.getI() );
|
||||
BOOST_CHECK_EQUAL( 11 , completion.getJ() );
|
||||
BOOST_CHECK_EQUAL( 12 , completion.getK() );
|
||||
|
||||
BOOST_CHECK_EQUAL( Opm::WellCompletion::OPEN , completion.state);
|
||||
BOOST_CHECK_EQUAL( 99.88 , completion.getConnectionTransmissibilityFactor());
|
||||
BOOST_CHECK_EQUAL( 22.33 , completion.getDiameter());
|
||||
BOOST_CHECK_EQUAL( 33.22 , completion.getSkinFactor());
|
||||
BOOST_CHECK_CLOSE( 17.29 , completion.getEffectiveKhAsValueObject().getValue() , 1.0e-10);
|
||||
BOOST_CHECK_EQUAL( 0 , completion.sat_tableId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateWellConnectionsOK) {
|
||||
Opm::WellConnections completionSet;
|
||||
@@ -81,9 +69,9 @@ BOOST_AUTO_TEST_CASE(CreateWellConnectionsOK) {
|
||||
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
|
||||
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
|
||||
Opm::WellConnections completionSet;
|
||||
Opm::Connection completion1( 10,10,10, 1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",2.718), 0, dir);
|
||||
Opm::Connection completion2( 11,10,10, 1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",3.141), 0, dir);
|
||||
completionSet.add( completion1 );
|
||||
Opm::Connection completion1( 10,10,10, 1, 0.0, Opm::WellCompletion::OPEN , 99.88, 355.113, 0.25, 0, dir);
|
||||
Opm::Connection completion2( 10,10,11, 1, 0.0, Opm::WellCompletion::SHUT , 99.88, 355.113, 0.25, 0, dir);
|
||||
completionSet.add( completion1 );
|
||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||
|
||||
completionSet.add( completion2 );
|
||||
@@ -95,9 +83,9 @@ BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
|
||||
|
||||
BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows) {
|
||||
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
|
||||
Opm::Connection completion1( 10,10,10, 1, 0.0, Opm::WellCompletion::OPEN , 99.88, 355.113, 0.25, 0, dir);
|
||||
Opm::Connection completion2( 10,10,11, 1, 0.0, Opm::WellCompletion::SHUT , 99.88, 355.113, 0.25, 0, dir);
|
||||
Opm::WellConnections completionSet;
|
||||
Opm::Connection completion1( 10,10,10,1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",17.29), 0, dir);
|
||||
Opm::Connection completion2( 11,10,10,1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",355.113), 0, dir);
|
||||
completionSet.add( completion1 );
|
||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||
|
||||
@@ -115,9 +103,9 @@ BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
||||
Opm::WellConnections completionSet;
|
||||
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
|
||||
|
||||
Opm::Connection completion1( 10,10,10, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",355.113), 0, dir);
|
||||
Opm::Connection completion2( 10,10,11, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",355.113), 0, dir);
|
||||
Opm::Connection completion3( 10,10,12, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",355.113), 0, dir);
|
||||
Opm::Connection completion1( 10,10,10, 1, 0.0, Opm::WellCompletion::OPEN , 99.88, 355.113, 0.25, 0, dir);
|
||||
Opm::Connection completion2( 10,10,11, 1, 0.0, Opm::WellCompletion::SHUT , 99.88, 355.113, 0.25, 0, dir);
|
||||
Opm::Connection completion3( 10,10,12, 1, 0.0, Opm::WellCompletion::SHUT , 99.88, 355.113, 0.25, 0, dir);
|
||||
|
||||
completionSet.add( completion1 );
|
||||
completionSet.add( completion2 );
|
||||
@@ -134,18 +122,18 @@ BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ActiveCompletions) {
|
||||
Opm::EclipseGrid grid(10,10,10);
|
||||
Opm::EclipseGrid grid(10,20,20);
|
||||
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
|
||||
Opm::WellConnections completions;
|
||||
Opm::Connection completion1( 0,0,0, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",355.113), 0, dir);
|
||||
Opm::Connection completion2( 0,0,1, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",355.113), 0, dir);
|
||||
Opm::Connection completion3( 0,0,2, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), Opm::Value<double>("Kh",355.113), 0, dir);
|
||||
Opm::Connection completion1( 0,0,0, 1, 0.0, Opm::WellCompletion::OPEN , 99.88, 355.113, 0.25, 0, dir);
|
||||
Opm::Connection completion2( 0,0,1, 1, 0.0, Opm::WellCompletion::SHUT , 99.88, 355.113, 0.25, 0, dir);
|
||||
Opm::Connection completion3( 0,0,2, 1, 0.0, Opm::WellCompletion::SHUT , 99.88, 355.113, 0.25, 0, dir);
|
||||
|
||||
completions.add( completion1 );
|
||||
completions.add( completion2 );
|
||||
completions.add( completion3 );
|
||||
|
||||
std::vector<int> actnum(1000,1);
|
||||
std::vector<int> actnum(grid.getCartesianSize(), 1);
|
||||
actnum[0] = 0;
|
||||
grid.resetACTNUM( actnum.data() );
|
||||
|
||||
@@ -154,3 +142,187 @@ BOOST_AUTO_TEST_CASE(ActiveCompletions) {
|
||||
BOOST_CHECK_EQUAL( completion2, active_completions.get(0));
|
||||
BOOST_CHECK_EQUAL( completion3, active_completions.get(1));
|
||||
}
|
||||
|
||||
Opm::WellConnections loadCOMPDAT(const std::string& compdat_keyword) {
|
||||
Opm::EclipseGrid grid(10,10,10);
|
||||
Opm::TableManager tables;
|
||||
Opm::Parser parser;
|
||||
const auto deck = parser.parseString(compdat_keyword, Opm::ParseContext());
|
||||
Opm::Eclipse3DProperties props(deck, tables, grid );
|
||||
const auto& keyword = deck.getKeyword("COMPDAT", 0);
|
||||
Opm::WellConnections connections;
|
||||
for (const auto& rec : keyword)
|
||||
connections.loadCOMPDAT(rec, grid, props);
|
||||
|
||||
return connections;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(loadCOMPDATTEST) {
|
||||
Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA.
|
||||
{
|
||||
const std::string deck = R"(COMPDAT
|
||||
-- CF Diam Kh Skin Df
|
||||
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 /
|
||||
/)";
|
||||
Opm::WellConnections connections = loadCOMPDAT(deck);
|
||||
const auto& conn0 = connections[0];
|
||||
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
||||
BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 107.872));
|
||||
}
|
||||
|
||||
{
|
||||
const std::string deck = R"(GRID
|
||||
|
||||
PERMX
|
||||
1000*0.10 /
|
||||
|
||||
COPY
|
||||
'PERMX' 'PERMZ' /
|
||||
'PERMX' 'PERMY' /
|
||||
/
|
||||
|
||||
SCHEDULE
|
||||
|
||||
COMPDAT
|
||||
-- CF Diam Kh Skin Df
|
||||
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 0 1* 1* 'Z' 21.925 /
|
||||
/)";
|
||||
Opm::WellConnections connections = loadCOMPDAT(deck);
|
||||
const auto& conn0 = connections[0];
|
||||
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
||||
BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 0.10 * 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(loadCOMPDATTESTSPE1) {
|
||||
Opm::ParseContext parseContext;
|
||||
Opm::Parser parser;
|
||||
|
||||
const auto deck = parser.parseFile("SPE1CASE1.DATA", parseContext);
|
||||
Opm::EclipseState state(deck, parseContext);
|
||||
Opm::Schedule sched(deck, state, parseContext);
|
||||
const auto& units = deck.getActiveUnitSystem();
|
||||
|
||||
const auto& prod = sched.getWell("PROD");
|
||||
const auto& connections = prod->getConnections(0);
|
||||
const auto& conn0 = connections[0];
|
||||
/* Expected values come from Eclipse simulation. */
|
||||
BOOST_CHECK_CLOSE(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 10.609), 2e-2);
|
||||
BOOST_CHECK_CLOSE(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 10000), 1e-6);
|
||||
}
|
||||
|
||||
|
||||
struct exp_conn {
|
||||
std::string well;
|
||||
int ci;
|
||||
double CF;
|
||||
double Kh;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(loadCOMPDATTESTSPE9) {
|
||||
Opm::ParseContext parseContext;
|
||||
Opm::Parser parser;
|
||||
|
||||
const auto deck = parser.parseFile("SPE9_CP_PACKED.DATA", parseContext);
|
||||
Opm::EclipseState state(deck, parseContext);
|
||||
Opm::Schedule sched(deck, state, parseContext);
|
||||
const auto& units = deck.getActiveUnitSystem();
|
||||
/*
|
||||
The list of the expected values come from the PRT file in an ECLIPSE simulation.
|
||||
*/
|
||||
std::vector<exp_conn> expected = {
|
||||
{"INJE1" ,1 , 0.166, 111.9},
|
||||
{"INJE1" ,2 , 0.597, 402.6},
|
||||
{"INJE1" ,3 , 1.866, 1259.2},
|
||||
{"INJE1" ,4 , 12.442, 8394.2},
|
||||
{"INJE1" ,5 , 6.974, 4705.3},
|
||||
|
||||
{"PRODU2" ,1 , 0.893, 602.8},
|
||||
{"PRODU2" ,2 , 3.828, 2582.8},
|
||||
{"PRODU2" ,3 , 0.563, 380.0},
|
||||
|
||||
{"PRODU3" ,1 , 1.322, 892.1},
|
||||
{"PRODU3" ,2 , 3.416, 2304.4},
|
||||
|
||||
{"PRODU4" ,1 , 4.137, 2791.2},
|
||||
{"PRODU4" ,2 , 66.455, 44834.7},
|
||||
|
||||
{"PRODU5" ,1 , 0.391, 264.0},
|
||||
{"PRODU5" ,2 , 7.282, 4912.6},
|
||||
{"PRODU5" ,3 , 1.374, 927.3},
|
||||
|
||||
{"PRODU6" ,1 , 1.463, 987.3},
|
||||
{"PRODU6" ,2 , 1.891, 1275.8},
|
||||
|
||||
{"PRODU7" ,1 , 1.061, 716.1},
|
||||
{"PRODU7" ,2 , 5.902, 3982.0},
|
||||
{"PRODU7" ,3 , 0.593, 400.1},
|
||||
|
||||
{"PRODU8" ,1 , 0.993, 670.1},
|
||||
{"PRODU8" ,2 , 17.759, 11981.5},
|
||||
|
||||
{"PRODU9" ,1 , 0.996, 671.9},
|
||||
{"PRODU9" ,2 , 2.548, 1719.0},
|
||||
|
||||
{"PRODU10" ,1 , 11.641, 7853.9},
|
||||
{"PRODU10" ,2 , 7.358, 4964.1},
|
||||
{"PRODU10" ,3 , 0.390, 262.8},
|
||||
|
||||
{"PRODU11" ,2 , 3.536, 2385.6},
|
||||
|
||||
{"PRODU12" ,1 , 3.028, 2043.1},
|
||||
{"PRODU12" ,2 , 0.301, 202.7},
|
||||
{"PRODU12" ,3 , 0.279, 188.3},
|
||||
|
||||
{"PRODU13" ,2 , 5.837, 3938.1},
|
||||
|
||||
{"PRODU14" ,1 , 180.976, 122098.1},
|
||||
{"PRODU14" ,2 , 25.134, 16957.0},
|
||||
{"PRODU14" ,3 , 0.532, 358.7},
|
||||
|
||||
{"PRODU15" ,1 , 4.125, 2783.1},
|
||||
{"PRODU15" ,2 , 6.431, 4338.7},
|
||||
|
||||
{"PRODU16" ,2 , 5.892, 3975.0},
|
||||
|
||||
{"PRODU17" ,1 , 80.655, 54414.9},
|
||||
{"PRODU17" ,2 , 9.098, 6138.3},
|
||||
|
||||
{"PRODU18" ,1 , 1.267, 855.1},
|
||||
{"PRODU18" ,2 , 18.556, 12518.9},
|
||||
|
||||
{"PRODU19" ,1 , 15.589, 10517.2},
|
||||
{"PRODU19" ,3 , 1.273, 859.1},
|
||||
|
||||
{"PRODU20" ,1 , 3.410, 2300.5},
|
||||
{"PRODU20" ,2 , 0.191, 128.8},
|
||||
{"PRODU20" ,3 , 0.249, 168.1},
|
||||
|
||||
{"PRODU21" ,1 , 0.596, 402.0},
|
||||
{"PRODU21" ,2 , 0.163, 109.9},
|
||||
|
||||
{"PRODU22" ,1 , 4.021, 2712.8},
|
||||
{"PRODU22" ,2 , 0.663, 447.1},
|
||||
|
||||
{"PRODU23" ,1 , 1.542, 1040.2},
|
||||
|
||||
{"PRODU24" ,1 , 78.939, 53257.0},
|
||||
{"PRODU24" ,3 , 17.517, 11817.8},
|
||||
|
||||
{"PRODU25" ,1 , 3.038, 2049.5},
|
||||
{"PRODU25" ,2 , 0.926, 624.9},
|
||||
{"PRODU25" ,3 , 0.891, 601.3},
|
||||
|
||||
{"PRODU26" ,1 , 0.770, 519.6},
|
||||
{"PRODU26" ,3 , 0.176, 118.6}};
|
||||
|
||||
for (const auto& ec : expected) {
|
||||
const auto& well = sched.getWell(ec.well);
|
||||
const auto& connections = well->getConnections(0);
|
||||
const auto& conn = connections[ec.ci - 1];
|
||||
|
||||
BOOST_CHECK_CLOSE( conn.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, ec.CF), 2e-1);
|
||||
BOOST_CHECK_CLOSE( conn.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, ec.Kh), 1e-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,11 @@ BOOST_AUTO_TEST_CASE(CreateGridNoCells) {
|
||||
BOOST_CHECK_EQUAL( 10 , grid.getNX());
|
||||
BOOST_CHECK_EQUAL( 10 , grid.getNY());
|
||||
BOOST_CHECK_EQUAL( 10 , grid.getNZ());
|
||||
|
||||
BOOST_CHECK_EQUAL(10, grid[0]);
|
||||
BOOST_CHECK_EQUAL(10, grid[2]);
|
||||
BOOST_CHECK_THROW( grid[10], std::invalid_argument);
|
||||
|
||||
BOOST_CHECK_EQUAL( 1000 , grid.getCartesianSize());
|
||||
}
|
||||
|
||||
|
||||
@@ -43,15 +43,15 @@
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MultisegmentWellTest) {
|
||||
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
|
||||
Opm::WellConnections connection_set;
|
||||
connection_set.add(Opm::Connection( 19, 0, 0, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.5), Opm::Value<double>("SKIN", 0.), Opm::Value<double>("Kh", 17.29), 0, dir) );
|
||||
connection_set.add(Opm::Connection( 19, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.5), Opm::Value<double>("SKIN", 0.), Opm::Value<double>("Kh", 17.29), 0, dir) );
|
||||
connection_set.add(Opm::Connection( 19, 0, 2, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), Opm::Value<double>("Kh", 17.29), 0, dir) );
|
||||
Opm::WellConnections connection_set;
|
||||
connection_set.add(Opm::Connection( 19, 0, 0, 1, 0.0, Opm::WellCompletion::OPEN , 200, 17.29, 0.25, 0, dir) );
|
||||
connection_set.add(Opm::Connection( 19, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , 200, 17.29, 0.25, 0, dir) );
|
||||
connection_set.add(Opm::Connection( 19, 0, 2, 1, 0.0, Opm::WellCompletion::OPEN , 200, 17.29, 0.25, 0, dir) );
|
||||
|
||||
connection_set.add(Opm::Connection( 18, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), Opm::Value<double>("Kh", 17.29), 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
connection_set.add(Opm::Connection( 17, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), Opm::Value<double>("Kh", 17.29), 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
connection_set.add(Opm::Connection( 16, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), Opm::Value<double>("Kh", 17.29), 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
connection_set.add(Opm::Connection( 15, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), Opm::Value<double>("Kh", 17.29), 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
connection_set.add(Opm::Connection( 18, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , 200, 17.29, 0.25, 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
connection_set.add(Opm::Connection( 17, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , 200, 17.29, 0.25, 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
connection_set.add(Opm::Connection( 16, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , 200, 17.29, 0.25, 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
connection_set.add(Opm::Connection( 15, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , 200, 17.29, 0.25, 0, Opm::WellCompletion::DirectionEnum::X) );
|
||||
|
||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||
|
||||
@@ -93,32 +93,32 @@ Opm::WellConnections connection_set;
|
||||
BOOST_CHECK_EQUAL(7U, new_connection_set->size());
|
||||
|
||||
const Opm::Connection& connection1 = new_connection_set->get(0);
|
||||
const int segment_number_connection1 = connection1.segment_number;
|
||||
const double center_depth_connection1 = connection1.center_depth;
|
||||
const int segment_number_connection1 = connection1.segment();
|
||||
const double center_depth_connection1 = connection1.depth();
|
||||
BOOST_CHECK_EQUAL(segment_number_connection1, 1);
|
||||
BOOST_CHECK_EQUAL(center_depth_connection1, 2512.5);
|
||||
|
||||
const Opm::Connection& connection3 = new_connection_set->get(2);
|
||||
const int segment_number_connection3 = connection3.segment_number;
|
||||
const double center_depth_connection3 = connection3.center_depth;
|
||||
const int segment_number_connection3 = connection3.segment();
|
||||
const double center_depth_connection3 = connection3.depth();
|
||||
BOOST_CHECK_EQUAL(segment_number_connection3, 3);
|
||||
BOOST_CHECK_EQUAL(center_depth_connection3, 2562.5);
|
||||
|
||||
const Opm::Connection& connection5 = new_connection_set->get(4);
|
||||
const int segment_number_connection5 = connection5.segment_number;
|
||||
const double center_depth_connection5 = connection5.center_depth;
|
||||
const int segment_number_connection5 = connection5.segment();
|
||||
const double center_depth_connection5 = connection5.depth();
|
||||
BOOST_CHECK_EQUAL(segment_number_connection5, 6);
|
||||
BOOST_CHECK_CLOSE(center_depth_connection5, 2538.83, 0.001);
|
||||
|
||||
const Opm::Connection& connection6 = new_connection_set->get(5);
|
||||
const int segment_number_connection6 = connection6.segment_number;
|
||||
const double center_depth_connection6 = connection6.center_depth;
|
||||
const int segment_number_connection6 = connection6.segment();
|
||||
const double center_depth_connection6 = connection6.depth();
|
||||
BOOST_CHECK_EQUAL(segment_number_connection6, 6);
|
||||
BOOST_CHECK_CLOSE(center_depth_connection6, 2537.83, 0.001);
|
||||
|
||||
const Opm::Connection& connection7 = new_connection_set->get(6);
|
||||
const int segment_number_connection7 = connection7.segment_number;
|
||||
const double center_depth_connection7 = connection7.center_depth;
|
||||
const int segment_number_connection7 = connection7.segment();
|
||||
const double center_depth_connection7 = connection7.depth();
|
||||
BOOST_CHECK_EQUAL(segment_number_connection7, 7);
|
||||
BOOST_CHECK_EQUAL(center_depth_connection7, 2534.5);
|
||||
}
|
||||
|
||||
@@ -897,5 +897,40 @@ BOOST_AUTO_TEST_CASE(RESTART_BASIC_LEQ_2) {
|
||||
BOOST_CHECK( !ioConfig.getWriteRestartFile( ts ) );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(RESTART_SAVE) {
|
||||
const char* data = "RUNSPEC\n"
|
||||
"DIMENS\n"
|
||||
" 10 10 10 /\n"
|
||||
"GRID\n"
|
||||
"START\n"
|
||||
" 21 MAY 1981 /\n"
|
||||
"\n"
|
||||
"SCHEDULE\n"
|
||||
"DATES\n"
|
||||
" 22 MAY 1981 /\n"
|
||||
"/\n"
|
||||
"DATES\n"
|
||||
" 23 MAY 1981 /\n"
|
||||
" 24 MAY 1981 /\n"
|
||||
" 23 MAY 1982 /\n"
|
||||
" 24 MAY 1982 /\n"
|
||||
" 24 MAY 1983 /\n"
|
||||
" 25 MAY 1984 /\n"
|
||||
" 26 MAY 1984 /\n"
|
||||
" 26 MAY 1985 /\n"
|
||||
" 27 MAY 1985 /\n"
|
||||
" 1 JAN 1986 /\n"
|
||||
"/\n"
|
||||
"SAVE \n"
|
||||
"TSTEP \n"
|
||||
" 1 /\n";
|
||||
|
||||
auto deck = Parser().parseString( data, ParseContext() );
|
||||
RestartConfig ioConfig( deck );
|
||||
|
||||
for( size_t ts = 1; ts < 11; ++ts )
|
||||
BOOST_CHECK( !ioConfig.getWriteRestartFile( ts ) );
|
||||
BOOST_CHECK( ioConfig.getWriteRestartFile( 12 ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -654,25 +654,25 @@ BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsAndConnectionDataWithWELOPEN) {
|
||||
constexpr auto open = WellCompletion::StateEnum::OPEN;
|
||||
|
||||
BOOST_CHECK_EQUAL( 7U, cs.size() );
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 2 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 3 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 4 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 7, 2 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 2 ).state());
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 3 ).state());
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 4 ).state());
|
||||
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 7, 2 ).state());
|
||||
|
||||
const auto& cs2 = well->getConnections( 4 );
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 2 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 3 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 4 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 7, 2 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 2 ).state());
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 3 ).state());
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 4 ).state());
|
||||
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 7, 2 ).state());
|
||||
|
||||
well = schedule.getWell("OP_3");
|
||||
const auto& cs3 = well->getConnections( 3 );
|
||||
|
||||
BOOST_CHECK_EQUAL(shut, cs3.get( 0 ).state);
|
||||
BOOST_CHECK_EQUAL(shut, cs3.get( 0 ).state());
|
||||
|
||||
const auto& cs4 = well->getConnections( 4 );
|
||||
|
||||
BOOST_CHECK_EQUAL(open, cs4.get( 0 ).state);
|
||||
BOOST_CHECK_EQUAL(open, cs4.get( 0 ).state());
|
||||
|
||||
well = schedule.getWell("OP_1");
|
||||
BOOST_CHECK_EQUAL(WellCommon::StatusEnum::SHUT, well->getStatus( 3 ));
|
||||
@@ -1072,17 +1072,17 @@ BOOST_AUTO_TEST_CASE(createDeckWithWPIMULT) {
|
||||
|
||||
const auto& cs2 = well->getConnections( 2 );
|
||||
for(size_t i = 0; i < cs2.size(); i++) {
|
||||
BOOST_CHECK_EQUAL(cs2.get( i ).wellPi, 1.3);
|
||||
BOOST_CHECK_EQUAL(cs2.get( i ).wellPi(), 1.3);
|
||||
}
|
||||
|
||||
const auto& cs3 = well->getConnections( 3 );
|
||||
for(size_t i = 0; i < cs3.size(); i++ ) {
|
||||
BOOST_CHECK_EQUAL(cs3.get( i ).wellPi, (1.3*1.3));
|
||||
BOOST_CHECK_EQUAL(cs3.get( i ).wellPi(), (1.3*1.3));
|
||||
}
|
||||
|
||||
const auto& cs4 = well->getConnections( 4 );
|
||||
for(size_t i = 0; i < cs4.size(); i++ ) {
|
||||
BOOST_CHECK_EQUAL(cs4.get( i ).wellPi, 1.0);
|
||||
BOOST_CHECK_EQUAL(cs4.get( i ).wellPi(), 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1673,16 +1673,16 @@ BOOST_AUTO_TEST_CASE( COMPDAT_sets_automatic_complnum ) {
|
||||
Schedule schedule( deck, grid, eclipseProperties, Phases( true, true, true ) ,ctx);
|
||||
|
||||
const auto& cs1 = schedule.getWell( "W1" )->getConnections( 1 );
|
||||
BOOST_CHECK_EQUAL( -1, cs1.get( 0 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -2, cs1.get( 1 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -3, cs1.get( 2 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -4, cs1.get( 3 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -1, cs1.get( 0 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -2, cs1.get( 1 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -3, cs1.get( 2 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -4, cs1.get( 3 ).complnum() );
|
||||
|
||||
const auto& cs2 = schedule.getWell( "W1" )->getConnections( 2 );
|
||||
BOOST_CHECK_EQUAL( -1, cs2.get( 0 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -2, cs2.get( 1 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -3, cs2.get( 2 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -4, cs2.get( 3 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -1, cs2.get( 0 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -2, cs2.get( 1 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -3, cs2.get( 2 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -4, cs2.get( 3 ).complnum() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
|
||||
@@ -1717,20 +1717,20 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
|
||||
Schedule schedule( deck, grid, eclipseProperties, Phases( true, true, true ) ,ctx);
|
||||
|
||||
const auto& w1cs = schedule.getWell( "W1" )->getConnections();
|
||||
BOOST_CHECK_EQUAL( -1, w1cs.get( 0 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -2, w1cs.get( 1 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -3, w1cs.get( 2 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -4, w1cs.get( 3 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -5, w1cs.get( 4 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -1, w1cs.get( 0 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -2, w1cs.get( 1 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -3, w1cs.get( 2 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -4, w1cs.get( 3 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -5, w1cs.get( 4 ).complnum() );
|
||||
|
||||
const auto& w2cs = schedule.getWell( "W2" )->getConnections();
|
||||
BOOST_CHECK_EQUAL( -1, w2cs.getFromIJK( 4, 4, 2 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -2, w2cs.getFromIJK( 4, 4, 0 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -3, w2cs.getFromIJK( 4, 4, 1 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -4, w2cs.getFromIJK( 4, 4, 3 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -5, w2cs.getFromIJK( 4, 4, 4 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -1, w2cs.getFromIJK( 4, 4, 2 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -2, w2cs.getFromIJK( 4, 4, 0 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -3, w2cs.getFromIJK( 4, 4, 1 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -4, w2cs.getFromIJK( 4, 4, 3 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -5, w2cs.getFromIJK( 4, 4, 4 ).complnum() );
|
||||
|
||||
BOOST_CHECK_THROW( w2cs.get( 5 ).complnum, std::out_of_range );
|
||||
BOOST_CHECK_THROW( w2cs.get( 5 ).complnum(), std::out_of_range );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) {
|
||||
@@ -1762,9 +1762,9 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) {
|
||||
|
||||
const auto& cs = schedule.getWell( "W1" )->getConnections();
|
||||
BOOST_CHECK_EQUAL( 3U, cs.size() );
|
||||
BOOST_CHECK_EQUAL( -1, cs.get( 0 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -2, cs.get( 1 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -3, cs.get( 2 ).complnum );
|
||||
BOOST_CHECK_EQUAL( -1, cs.get( 0 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -2, cs.get( 1 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( -3, cs.get( 2 ).complnum() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( complump_less_than_1 ) {
|
||||
@@ -1843,20 +1843,20 @@ BOOST_AUTO_TEST_CASE( complump ) {
|
||||
const auto& sc0 = well.getConnections( 0 );
|
||||
|
||||
/* complnum should be modified by COMPLNUM */
|
||||
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 0 ).complnum );
|
||||
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 1 ).complnum );
|
||||
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 2 ).complnum );
|
||||
BOOST_CHECK( sc0.getFromIJK( 2, 2, 3 ).complnum < 0);
|
||||
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 0 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 1 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 2 ).complnum() );
|
||||
BOOST_CHECK( sc0.getFromIJK( 2, 2, 3 ).complnum() < 0);
|
||||
|
||||
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 0 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 1 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 2 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 0 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 1 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 2 ).state() );
|
||||
|
||||
const auto& sc1 = well.getConnections( 1 );
|
||||
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 0 ).state );
|
||||
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 1 ).state );
|
||||
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 2 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, sc1.getFromIJK( 2, 2, 3 ).state );
|
||||
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 0 ).state() );
|
||||
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 1 ).state() );
|
||||
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 2 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, sc1.getFromIJK( 2, 2, 3 ).state() );
|
||||
|
||||
const auto completions = well.getCompletions(1);
|
||||
BOOST_CHECK_EQUAL(completions.size(), 4);
|
||||
@@ -1930,23 +1930,23 @@ BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) {
|
||||
const auto& cs2 = well.getConnections( 2 );
|
||||
|
||||
BOOST_CHECK_EQUAL( 9U, cs1.size() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 0, 0, 1 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 0 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 1 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 2 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 0 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 3 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 4 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 5 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 0, 0, 1 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 0 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 1 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 2 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 0 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 3 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 4 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 5 ).state() );
|
||||
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 0, 0, 1 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 2, 2, 0 ).state );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 1 ).state );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 2 ).state );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 0 ).state );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 3 ).state );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 4 ).state );
|
||||
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 1, 1, 5 ).state );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 0, 0, 1 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 2, 2, 0 ).state() );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 1 ).state() );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 2 ).state() );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 0 ).state() );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 3 ).state() );
|
||||
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 4 ).state() );
|
||||
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 1, 1, 5 ).state() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestCompletionStateEnum2String) {
|
||||
|
||||
@@ -98,9 +98,9 @@ static Deck createDeck( const std::string& summary ) {
|
||||
static std::vector< std::string > sorted_names( const SummaryConfig& summary ) {
|
||||
std::vector< std::string > ret;
|
||||
for( const auto& x : summary ) {
|
||||
auto wgname = x.wgname();
|
||||
auto wgname = smspec_node_get_wgname(x.get());
|
||||
if(wgname)
|
||||
ret.push_back( x.wgname() );
|
||||
ret.push_back( smspec_node_get_wgname(x.get()));
|
||||
}
|
||||
|
||||
std::sort( ret.begin(), ret.end() );
|
||||
@@ -110,7 +110,7 @@ static std::vector< std::string > sorted_names( const SummaryConfig& summary ) {
|
||||
static std::vector< std::string > sorted_keywords( const SummaryConfig& summary ) {
|
||||
std::vector< std::string > ret;
|
||||
for( const auto& x : summary )
|
||||
ret.push_back( x.keyword() );
|
||||
ret.push_back( smspec_node_get_keyword(x.get()));
|
||||
|
||||
std::sort( ret.begin(), ret.end() );
|
||||
return ret;
|
||||
@@ -119,7 +119,7 @@ static std::vector< std::string > sorted_keywords( const SummaryConfig& summary
|
||||
static std::vector< std::string > sorted_key_names( const SummaryConfig& summary ) {
|
||||
std::vector< std::string > ret;
|
||||
for( const auto& x : summary ) {
|
||||
ret.push_back( x.key1() );
|
||||
ret.push_back( smspec_node_get_gen_key1(x.get()));
|
||||
}
|
||||
|
||||
std::sort( ret.begin(), ret.end() );
|
||||
|
||||
@@ -340,15 +340,14 @@ BOOST_AUTO_TEST_CASE(NewWellZeroCompletions) {
|
||||
// Helper function for CompletionOrder test.
|
||||
inline Opm::Connection connection( int i, int j, int k, int complnum = 1 ) {
|
||||
return Opm::Connection { i, j, k,
|
||||
complnum,
|
||||
k*1.0,
|
||||
Opm::WellCompletion::AUTO,
|
||||
Opm::Value<double>("ConnectionTransmissibilityFactor",99.88),
|
||||
Opm::Value<double>("D",22.33),
|
||||
Opm::Value<double>("SKIN",33.22),
|
||||
Opm::Value<double>("Kh",17.29),
|
||||
0,
|
||||
Opm::WellCompletion::DirectionEnum::Z };
|
||||
complnum,
|
||||
k*1.0,
|
||||
Opm::WellCompletion::AUTO,
|
||||
99.88,
|
||||
17.29,
|
||||
0.25,
|
||||
0,
|
||||
Opm::WellCompletion::DirectionEnum::Z };
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -345,6 +345,8 @@ BOOST_AUTO_TEST_CASE( RestartConfig2 ) {
|
||||
else if (234 == report_step) rptConfig.push_back( std::make_tuple(report_step, true, boost::gregorian::date(2012,1,1)));
|
||||
else if (240 == report_step) rptConfig.push_back( std::make_tuple(report_step, true, boost::gregorian::date(2012,7,1)));
|
||||
else if (246 == report_step) rptConfig.push_back( std::make_tuple(report_step, true, boost::gregorian::date(2013,1,1)));
|
||||
// output when SAVE is in the deck
|
||||
else if (251 == report_step) rptConfig.push_back( std::make_tuple(report_step, true, boost::gregorian::date(2013,5,2)));
|
||||
else rptConfig.push_back( std::make_tuple(report_step, false, boost::gregorian::date(2000,1,1)));
|
||||
}
|
||||
|
||||
|
||||
@@ -577,26 +577,26 @@ BOOST_AUTO_TEST_CASE( MULTISEGMENT_ABS ) {
|
||||
BOOST_CHECK_EQUAL(7U, connections.size());
|
||||
|
||||
const Connection& connection5 = connections.get(4);
|
||||
const int seg_number_connection5 = connection5.segment_number;
|
||||
const double connection5_depth = connection5.center_depth;
|
||||
const int seg_number_connection5 = connection5.segment();
|
||||
const double connection5_depth = connection5.depth();
|
||||
BOOST_CHECK_EQUAL(seg_number_connection5, 6);
|
||||
BOOST_CHECK_CLOSE(connection5_depth, 2538.83, 0.001);
|
||||
|
||||
const Connection& connection6 = connections.get(5);
|
||||
const int seg_number_connection6 = connection6.segment_number;
|
||||
const double connection6_depth = connection6.center_depth;
|
||||
const int seg_number_connection6 = connection6.segment();
|
||||
const double connection6_depth = connection6.depth();
|
||||
BOOST_CHECK_EQUAL(seg_number_connection6, 6);
|
||||
BOOST_CHECK_CLOSE(connection6_depth, 2537.83, 0.001);
|
||||
|
||||
const Connection& connection1 = connections.get(0);
|
||||
const int seg_number_connection1 = connection1.segment_number;
|
||||
const double connection1_depth = connection1.center_depth;
|
||||
const int seg_number_connection1 = connection1.segment();
|
||||
const double connection1_depth = connection1.depth();
|
||||
BOOST_CHECK_EQUAL(seg_number_connection1, 1);
|
||||
BOOST_CHECK_EQUAL(connection1_depth, 2512.5);
|
||||
|
||||
const Connection& connection3 = connections.get(2);
|
||||
const int seg_number_connection3 = connection3.segment_number;
|
||||
const double connection3_depth = connection3.center_depth;
|
||||
const int seg_number_connection3 = connection3.segment();
|
||||
const double connection3_depth = connection3.depth();
|
||||
BOOST_CHECK_EQUAL(seg_number_connection3, 3);
|
||||
BOOST_CHECK_EQUAL(connection3_depth, 2562.5);
|
||||
}
|
||||
|
||||
@@ -349,13 +349,11 @@ BOOST_AUTO_TEST_CASE(WellTestCOMPDAT) {
|
||||
const auto& connections = well1->getConnections(3);
|
||||
BOOST_CHECK_EQUAL(4U, connections.size());
|
||||
|
||||
BOOST_CHECK_EQUAL(WellCompletion::OPEN, connections.get(3).state);
|
||||
BOOST_CHECK_EQUAL(2.2836805555555556e-12 , connections.get(3).getConnectionTransmissibilityFactor());
|
||||
BOOST_CHECK_EQUAL(0.311/Metric::Length, connections.get(3).getDiameter());
|
||||
BOOST_CHECK_EQUAL(3.3, connections.get(3).getSkinFactor());
|
||||
BOOST_CHECK_EQUAL(WellCompletion::OPEN, connections.get(3).state());
|
||||
BOOST_CHECK_EQUAL(2.2836805555555556e-12 , connections.get(3).CF());
|
||||
|
||||
BOOST_CHECK_EQUAL(4U, well1->getConnections( 7 ).size() );
|
||||
BOOST_CHECK_EQUAL(WellCompletion::SHUT, well1->getConnections( 7 ).get( 3 ).state );
|
||||
BOOST_CHECK_EQUAL(WellCompletion::SHUT, well1->getConnections( 7 ).get( 3 ).state() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,15 @@ ACTNUM
|
||||
PORO
|
||||
1000*0.2 /
|
||||
|
||||
PERMX
|
||||
1000*50 /
|
||||
|
||||
PERMY
|
||||
1000*50 /
|
||||
|
||||
PERMZ
|
||||
1000*10 /
|
||||
|
||||
REGIONS
|
||||
|
||||
FIPNUM
|
||||
@@ -578,6 +587,12 @@ CGPT
|
||||
'W_3' /
|
||||
/
|
||||
|
||||
CTFAC
|
||||
'W_1' /
|
||||
'W_2' /
|
||||
'W_3' /
|
||||
/
|
||||
|
||||
---- Connection production rates
|
||||
----CGFR
|
||||
----'E-4AH' /
|
||||
@@ -598,12 +613,12 @@ WELSPECS
|
||||
|
||||
-- Completion data.
|
||||
COMPDAT
|
||||
-- 'Well' I J K1 K2
|
||||
-- Passing 0 to I/J means they'll get the well head I/J
|
||||
W_1 0 0 1 1 / -- Active index: 0
|
||||
W_2 0 0 1 1 / -- Active index: 1
|
||||
W_2 0 0 2 2 / -- Active index: 101
|
||||
W_3 0 0 1 1 / -- Active index: 2
|
||||
-- 'Well' I J K1 K2 STATUS SatTable TransFact Rw Kh S
|
||||
W_1 0 0 1 1 2* 100 3* / -- Active index: 0
|
||||
W_2 0 0 1 1 2* 1* 5 20 0.5 / -- Active index: 1
|
||||
W_2 0 0 2 2 2* 1* 5 10 0.2 / -- Active index: 101
|
||||
W_3 0 0 1 1 2* 1* 2* 0.7 / -- Active index: 2
|
||||
/
|
||||
|
||||
WPOLYMER
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
// ERT stuff
|
||||
#include <ert/util/ert_unique_ptr.hpp>
|
||||
#include <ert/util/TestArea.hpp>
|
||||
#include <ert/util/test_work_area.h>
|
||||
|
||||
#include <ert/ecl/ecl_kw.h>
|
||||
#include <ert/ecl/ecl_grid.h>
|
||||
@@ -287,8 +287,6 @@ BOOST_AUTO_TEST_CASE(EclipseIOIntegration) {
|
||||
"'PROD' 'G' 3 3 1000 'OIL' /\n"
|
||||
"/\n";
|
||||
|
||||
ERT::TestArea ta("test_ecl_writer");
|
||||
|
||||
auto write_and_check = [&]( int first = 1, int last = 5 ) {
|
||||
ParseContext parse_context;
|
||||
auto deck = Parser().parseString( deckString, parse_context );
|
||||
@@ -376,6 +374,8 @@ BOOST_AUTO_TEST_CASE(EclipseIOIntegration) {
|
||||
* * https://github.com/OPM/opm-simulators/issues/753
|
||||
* * https://github.com/OPM/opm-output/pull/61
|
||||
*/
|
||||
|
||||
test_work_area_type * work_area = test_work_area_alloc("test_ecl_writer");
|
||||
const auto file_size = write_and_check();
|
||||
|
||||
for( int i = 0; i < 3; ++i )
|
||||
@@ -395,6 +395,7 @@ BOOST_AUTO_TEST_CASE(EclipseIOIntegration) {
|
||||
* the file
|
||||
*/
|
||||
BOOST_CHECK_EQUAL( file_size, write_and_check( 3, 5 ) );
|
||||
test_work_area_free(work_area);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(OPM_XWEL) {
|
||||
|
||||
@@ -407,6 +407,8 @@ struct Setup {
|
||||
schedule( deck, grid, es.get3DProperties(), es.runspec().phases(), parseContext),
|
||||
summary_config( deck, schedule, es.getTableManager( ), parseContext)
|
||||
{
|
||||
auto& io_config = es.getIOConfig();
|
||||
io_config.setEclCompatibleRST(false);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -433,6 +435,62 @@ BOOST_AUTO_TEST_CASE(EclipseReadWriteWellStateData) {
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ECL_FORMATTED) {
|
||||
Setup setup("FIRST_SIM.DATA");
|
||||
test_work_area_type * test_area = test_work_area_alloc("test_Restart");
|
||||
auto& io_config = setup.es.getIOConfig();
|
||||
{
|
||||
auto num_cells = setup.grid.getNumActive( );
|
||||
auto cells = mkSolution( num_cells );
|
||||
auto wells = mkWells();
|
||||
{
|
||||
RestartValue restart_value(cells, wells);
|
||||
|
||||
io_config.setEclCompatibleRST( false );
|
||||
restart_value.addExtra("EXTRA", UnitSystem::measure::pressure, {10,1,2,3});
|
||||
RestartIO::save("OPM_FILE.UNRST", 1 ,
|
||||
100,
|
||||
restart_value,
|
||||
setup.es,
|
||||
setup.grid,
|
||||
setup.schedule,
|
||||
true);
|
||||
|
||||
{
|
||||
ecl_file_type * rst_file = ecl_file_open( "OPM_FILE.UNRST" , 0 );
|
||||
ecl_kw_type * swat = ecl_file_iget_named_kw(rst_file, "SWAT", 0);
|
||||
|
||||
BOOST_CHECK_EQUAL( ECL_DOUBLE_TYPE, ecl_kw_get_type(swat));
|
||||
BOOST_CHECK( ecl_file_has_kw(rst_file, "EXTRA"));
|
||||
ecl_file_close(rst_file);
|
||||
}
|
||||
|
||||
io_config.setEclCompatibleRST( true );
|
||||
RestartIO::save("ECL_FILE.UNRST", 1 ,
|
||||
100,
|
||||
restart_value,
|
||||
setup.es,
|
||||
setup.grid,
|
||||
setup.schedule,
|
||||
true);
|
||||
{
|
||||
ecl_file_type * rst_file = ecl_file_open( "ECL_FILE.UNRST" , 0 );
|
||||
ecl_kw_type * swat = ecl_file_iget_named_kw(rst_file, "SWAT", 0);
|
||||
|
||||
BOOST_CHECK_EQUAL( ECL_FLOAT_TYPE, ecl_kw_get_type(swat));
|
||||
BOOST_CHECK( !ecl_file_has_kw(rst_file, "EXTRA"));
|
||||
BOOST_CHECK( !ecl_file_has_kw(rst_file, "OPM_XWEL"));
|
||||
BOOST_CHECK( !ecl_file_has_kw(rst_file, "OPM_IWEL"));
|
||||
ecl_file_close(rst_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
test_work_area_free(test_area);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void compare_equal( const RestartValue& fst,
|
||||
const RestartValue& snd ,
|
||||
|
||||
@@ -1036,6 +1036,11 @@ BOOST_AUTO_TEST_CASE(BLOCK_VARIABLES) {
|
||||
BOOST_CHECK_CLOSE( 8.0 , units.to_si( UnitSystem::measure::identity , ecl_sum_get_general_var( resp, 1, "BSWAT:1,1,1")) , 1e-5);
|
||||
BOOST_CHECK_CLOSE( 9.0 , units.to_si( UnitSystem::measure::identity , ecl_sum_get_general_var( resp, 1, "BSGAS:1,1,1")) , 1e-5);
|
||||
|
||||
BOOST_CHECK_CLOSE( 100 , ecl_sum_get_well_completion_var( resp, 1, "W_1", "CTFAC", 1) , 1e-5);
|
||||
BOOST_CHECK_CLOSE( 2.1430730819702148 , ecl_sum_get_well_completion_var( resp, 1, "W_2", "CTFAC", 2) , 1e-5);
|
||||
BOOST_CHECK_CLOSE( 2.6788413524627686 , ecl_sum_get_well_completion_var( resp, 1, "W_2", "CTFAC", 102) , 1e-5);
|
||||
BOOST_CHECK_CLOSE( 2.7855057716369629 , ecl_sum_get_well_completion_var( resp, 1, "W_3", "CTFAC", 3) , 1e-5);
|
||||
|
||||
// Cell is not active
|
||||
BOOST_CHECK( !ecl_sum_has_general_var( resp , "BPR:2,1,10"));
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <ert/ecl/ecl_sum.h>
|
||||
#include <ert/ecl/ecl_file.h>
|
||||
#include <ert/util/util.h>
|
||||
#include <ert/util/TestArea.hpp>
|
||||
#include <ert/util/test_work_area.h>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
@@ -53,15 +53,19 @@ using namespace Opm;
|
||||
struct setup {
|
||||
Deck deck;
|
||||
EclipseState es;
|
||||
ERT::TestArea ta;
|
||||
test_work_area_type * ta;
|
||||
|
||||
setup( const std::string& path , const ParseContext& parseContext = ParseContext( )) :
|
||||
deck( Parser().parseFile( path, parseContext ) ),
|
||||
es( deck, ParseContext() ),
|
||||
ta( ERT::TestArea("test_tables") )
|
||||
ta( test_work_area_alloc( "test_tables"))
|
||||
{
|
||||
}
|
||||
|
||||
~setup() {
|
||||
test_work_area_free(this->ta);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE( serialize_icon_test )
|
||||
const size_t offset = w_offset + c_offset;
|
||||
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_IC_INDEX],
|
||||
c.complnum);
|
||||
c.complnum());
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_I_INDEX],
|
||||
c.getI() + 1);
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_J_INDEX],
|
||||
@@ -64,9 +64,9 @@ BOOST_AUTO_TEST_CASE( serialize_icon_test )
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_K_INDEX],
|
||||
c.getK() + 1);
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_DIRECTION_INDEX],
|
||||
c.dir);
|
||||
c.dir());
|
||||
|
||||
if (c.state == Opm::WellCompletion::StateEnum::OPEN)
|
||||
if (c.state() == Opm::WellCompletion::StateEnum::OPEN)
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_STATUS_INDEX],
|
||||
1);
|
||||
else
|
||||
@@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE( serialize_icon_test )
|
||||
|
||||
if (c.attachedToSegment())
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_SEGMENT_INDEX],
|
||||
c.segment_number);
|
||||
c.segment());
|
||||
else
|
||||
BOOST_CHECK_EQUAL(icondata[offset + ICON_SEGMENT_INDEX],
|
||||
0);
|
||||
|
||||
@@ -56,15 +56,12 @@ BOOST_AUTO_TEST_CASE( serialize_scon_test )
|
||||
for (const auto c : w->getConnections(tstep)) {
|
||||
|
||||
const size_t offset = w_offset + c_offset;
|
||||
const auto ctf = c.getConnectionTransmissibilityFactorAsValueObject();
|
||||
const double expected =
|
||||
ctf.hasValue()
|
||||
? units.from_si(Opm::UnitSystem::measure::transmissibility, ctf.getValue())
|
||||
: Opm::RestartIO::Helpers::UNIMPLEMENTED_VALUE;
|
||||
const double expected_cf = units.from_si(Opm::UnitSystem::measure::transmissibility, c.CF());
|
||||
const double expected_kh = units.from_si(Opm::UnitSystem::measure::effective_Kh, c.Kh());
|
||||
BOOST_CHECK_EQUAL(scondata[offset + SCON_CF_INDEX],
|
||||
expected);
|
||||
expected_cf);
|
||||
BOOST_CHECK_EQUAL(scondata[offset + SCON_KH_INDEX],
|
||||
Opm::RestartIO::Helpers::UNIMPLEMENTED_VALUE);
|
||||
expected_kh);
|
||||
|
||||
c_offset += SCONZ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user