Merge pull request #695 from chflo/OPM_139_wellinfo_eclrestart
Opm 139 wellinfo eclrestart
This commit is contained in:
@@ -150,6 +150,7 @@ list (APPEND MAIN_SOURCE_FILES
|
||||
# originally generated with the command:
|
||||
# find tests -name '*.cpp' -a ! -wholename '*/not-unit/*' -printf '\t%p\n' | sort
|
||||
list (APPEND TEST_SOURCE_FILES
|
||||
tests/test_writenumwells.cpp
|
||||
tests/test_EclipseWriter.cpp
|
||||
tests/test_compressedpropertyaccess.cpp
|
||||
tests/test_spline.cpp
|
||||
@@ -211,6 +212,7 @@ list (APPEND TEST_DATA_FILES
|
||||
tests/satfuncEPS_D.DATA
|
||||
tests/testBlackoilState1.DATA
|
||||
tests/testBlackoilState2.DATA
|
||||
tests/testBlackoilState3.DATA
|
||||
tests/wells_manager_data.data
|
||||
tests/wells_manager_data_expanded.data
|
||||
tests/wells_manager_data_wellSTOP.data
|
||||
|
||||
@@ -69,6 +69,15 @@ find_library (ERT_LIBRARY_ECL
|
||||
DOC "Path to ERT Eclipse library archive/shared object files"
|
||||
${_no_default_path}
|
||||
)
|
||||
find_library (ERT_LIBRARY_ECL_WELL
|
||||
NAMES "ecl_well"
|
||||
HINTS "${ERT_ROOT}"
|
||||
PATHS "${PROJECT_BINARY_DIR}/../ert" "${PROJECT_BINARY_DIR}/../ert-build"
|
||||
"${PROJECT_BINARY_DIR}/../ert/devel"
|
||||
PATH_SUFFIXES "lib" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}"
|
||||
DOC "Path to ERT Eclipse library archive/shared object files"
|
||||
${_no_default_path}
|
||||
)
|
||||
find_library (ERT_LIBRARY_GEOMETRY
|
||||
NAMES "ert_geometry"
|
||||
HINTS "${ERT_ROOT}"
|
||||
@@ -95,6 +104,7 @@ list (APPEND ERT_INCLUDE_DIR
|
||||
)
|
||||
list (APPEND ERT_LIBRARY
|
||||
${ERT_LIBRARY_ECL}
|
||||
${ERT_LIBRARY_ECL_WELL}
|
||||
${ERT_LIBRARY_GEOMETRY}
|
||||
${ERT_LIBRARY_UTIL}
|
||||
)
|
||||
|
||||
@@ -23,10 +23,9 @@
|
||||
#include "EclipseWriter.hpp"
|
||||
|
||||
#include <opm/core/props/BlackoilPhases.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/core/props/phaseUsageFromDeck.hpp>
|
||||
#include <opm/core/grid.h>
|
||||
#include <opm/core/grid/cpgpreprocess/preprocess.h>
|
||||
#include <opm/core/props/phaseUsageFromDeck.hpp>
|
||||
#include <opm/core/simulator/SimulatorState.hpp>
|
||||
#include <opm/core/simulator/SimulatorTimer.hpp>
|
||||
#include <opm/core/simulator/WellState.hpp>
|
||||
@@ -39,6 +38,9 @@
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
#include <opm/parser/eclipse/Utility/SpecgridWrapper.hpp>
|
||||
#include <opm/parser/eclipse/Utility/WelspecsWrapper.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp> // to_upper_copy
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
@@ -59,6 +61,8 @@
|
||||
#include <ert/ecl/ecl_init_file.h>
|
||||
#include <ert/ecl/ecl_file.h>
|
||||
#include <ert/ecl/ecl_rst_file.h>
|
||||
#include <ert/ecl_well/well_const.h>
|
||||
#include <ert/ecl/ecl_rsthead.h>
|
||||
|
||||
// namespace start here since we don't want the ERT headers in it
|
||||
namespace Opm {
|
||||
@@ -120,6 +124,9 @@ int ertPhaseMask(const PhaseUsage uses)
|
||||
| (uses.phase_used[BlackoilPhases::Vapour] ? ECL_GAS_PHASE : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Eclipse "keyword" (i.e. named data) for a vector.
|
||||
*/
|
||||
@@ -144,6 +151,11 @@ public:
|
||||
: ertHandle_(0)
|
||||
{ set(name, data); }
|
||||
|
||||
Keyword(const std::string& name,
|
||||
const std::vector<const char*>& data)
|
||||
: ertHandle_(0)
|
||||
{set(name, data); }
|
||||
|
||||
~Keyword()
|
||||
{
|
||||
if (ertHandle_)
|
||||
@@ -153,10 +165,12 @@ public:
|
||||
template <class DataElementType>
|
||||
void set(const std::string name, const std::vector<DataElementType>& data)
|
||||
{
|
||||
|
||||
if(ertHandle_) {
|
||||
ecl_kw_free(ertHandle_);
|
||||
}
|
||||
|
||||
|
||||
ertHandle_ = ecl_kw_alloc(name.c_str(),
|
||||
data.size(),
|
||||
ertType_());
|
||||
@@ -165,12 +179,32 @@ public:
|
||||
const int numEntries = data.size();
|
||||
|
||||
// fill it with values
|
||||
|
||||
T* target = static_cast<T*>(ecl_kw_get_ptr(ertHandle()));
|
||||
for (int i = 0; i < numEntries; ++i) {
|
||||
target[i] = static_cast<T>(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void set(const std::string name, const std::vector<const char *>& data)
|
||||
{
|
||||
if(ertHandle_) {
|
||||
ecl_kw_free(ertHandle_);
|
||||
}
|
||||
|
||||
|
||||
ertHandle_ = ecl_kw_alloc(name.c_str(),
|
||||
data.size(),
|
||||
ertType_());
|
||||
|
||||
// number of elements to take
|
||||
const int numEntries = data.size();
|
||||
for (int i = 0; i < numEntries; ++i) {
|
||||
ecl_kw_iset_char_ptr( ertHandle_, i, data[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ecl_kw_type *ertHandle() const
|
||||
{ return ertHandle_; }
|
||||
|
||||
@@ -183,6 +217,9 @@ private:
|
||||
{ return ECL_DOUBLE_TYPE; }
|
||||
if (std::is_same<T, int>::value)
|
||||
{ return ECL_INT_TYPE; }
|
||||
if (std::is_same<T, const char *>::value)
|
||||
{ return ECL_CHAR_TYPE; }
|
||||
|
||||
|
||||
OPM_THROW(std::logic_error,
|
||||
"Unhandled type for data elements in EclipseWriterDetails::Keyword");
|
||||
@@ -222,6 +259,23 @@ private:
|
||||
class Restart : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
static const int NIWELZ = 11; //Number of data elements per well in IWEL array in restart file
|
||||
static const int NZWELZ = 3; //Number of 8-character words per well in ZWEL array restart file
|
||||
static const int NICONZ = 14; //Number of data elements per completion in ICON array restart file
|
||||
|
||||
/**
|
||||
* The constants NIWELZ and NZWELZ referes to the number of elements per well that we write to
|
||||
* the IWEL and ZWEL eclipse restart file data arrays. The constant NICONZ refers to the number of
|
||||
* elements per completion in the eclipse restart file ICON data array.These numbers are written
|
||||
* to the INTEHEAD header.
|
||||
* The elements are added in the methods addRestartFileIwelData(...), addRestartFileZwelData(...)
|
||||
* and addRestartFileIconData(...), respectively.
|
||||
* We write as many elements that we need to be able to view the restart file in Resinsight.
|
||||
* The restart file will not be possible to open with Eclipse, we write to little information to
|
||||
* be able to do this.
|
||||
*/
|
||||
|
||||
|
||||
Restart(const std::string& outputDir,
|
||||
const std::string& baseName,
|
||||
int reportStepIdx)
|
||||
@@ -240,6 +294,78 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void add_kw(const Keyword<T>& kw)
|
||||
{ ecl_rst_file_add_kw(restartFileHandle_, kw.ertHandle()); }
|
||||
|
||||
|
||||
void addRestartFileIwelData(std::vector<int>& iwel_data, size_t currentStep, WellConstPtr well_ptr) const {
|
||||
iwel_data.reserve(iwel_data.size() + Opm::EclipseWriterDetails::Restart::NIWELZ);
|
||||
|
||||
int eclipse_offset = 1;
|
||||
iwel_data.push_back(well_ptr->getHeadI() + eclipse_offset); // item 1 - gridhead I value
|
||||
iwel_data.push_back(well_ptr->getHeadJ() + eclipse_offset); // item 2 - gridhead J value
|
||||
iwel_data.push_back(0); // item 3 - gridhead K value
|
||||
iwel_data.push_back(0); // item 4 - undefined - 0
|
||||
|
||||
CompletionSetConstPtr completions_ptr = well_ptr->getCompletions(currentStep);
|
||||
int num_completions = completions_ptr->size();
|
||||
iwel_data.push_back(num_completions); // item 5 - number of completions
|
||||
iwel_data.push_back(1); // item 6 - for now, set all group indexes to 1
|
||||
|
||||
WellType welltype = well_ptr->isProducer(currentStep) ? PRODUCER : INJECTOR;
|
||||
int ert_welltype = EclipseWriter::eclipseWellTypeMask(welltype, well_ptr->getInjectionProperties(currentStep).injectorType);
|
||||
iwel_data.push_back(ert_welltype); // item 7 - welltype
|
||||
|
||||
iwel_data.insert(iwel_data.end(), 3, 0); //items 8,9,10 - undefined - 0
|
||||
iwel_data.push_back(EclipseWriter::eclipseWellStatusMask(well_ptr->getStatus(currentStep))); // item 11 - well status
|
||||
}
|
||||
|
||||
|
||||
|
||||
void addRestartFileZwelData(std::vector<const char*>& zwel_data, size_t currentstep, WellConstPtr well_ptr) const {
|
||||
zwel_data.reserve(zwel_data.size() + Opm::EclipseWriterDetails::Restart::NZWELZ);
|
||||
|
||||
zwel_data.push_back(well_ptr->name().c_str());
|
||||
zwel_data.push_back("");
|
||||
zwel_data.push_back("");
|
||||
}
|
||||
|
||||
|
||||
void addRestartFileIconData(std::vector<int>& icon_data, size_t currentstep, int ncwmax, WellConstPtr well_ptr) const {
|
||||
icon_data.reserve(icon_data.size() + Opm::EclipseWriterDetails::Restart::NICONZ * ncwmax);
|
||||
|
||||
CompletionSetConstPtr completions_set_ptr = well_ptr->getCompletions(currentstep);
|
||||
|
||||
int zero_pad = ncwmax - completions_set_ptr->size();
|
||||
|
||||
for (size_t i = 0; i < completions_set_ptr->size(); ++i) {
|
||||
CompletionConstPtr completion_ptr = completions_set_ptr->get(i);
|
||||
icon_data.push_back(1);
|
||||
|
||||
int eclipse_offset = 1;
|
||||
icon_data.push_back(completion_ptr->getI() + eclipse_offset);
|
||||
icon_data.push_back(completion_ptr->getJ() + eclipse_offset) ;
|
||||
icon_data.push_back(completion_ptr->getK() + eclipse_offset);
|
||||
icon_data.push_back(0);
|
||||
|
||||
CompletionStateEnum completion_state = completion_ptr->getState();
|
||||
if (completion_state == CompletionStateEnum::OPEN) {
|
||||
icon_data.push_back(1);
|
||||
} else {
|
||||
icon_data.push_back(0);
|
||||
}
|
||||
|
||||
icon_data.insert(icon_data.end(), 7, 0);
|
||||
icon_data.push_back((int)completion_ptr->getDirection());
|
||||
}
|
||||
|
||||
for(int i=0;i<zero_pad;i++){
|
||||
icon_data.insert(icon_data.end(), Restart::NICONZ, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~Restart()
|
||||
{
|
||||
free(restartFileName_);
|
||||
@@ -248,20 +374,13 @@ public:
|
||||
|
||||
void writeHeader(const SimulatorTimer& timer,
|
||||
int reportStepIdx,
|
||||
int numCells,
|
||||
int nx,
|
||||
int ny,
|
||||
int nz,
|
||||
const PhaseUsage uses)
|
||||
ecl_rsthead_type * rsthead_data)
|
||||
{
|
||||
ecl_rst_file_fwrite_header(restartFileHandle_,
|
||||
reportStepIdx,
|
||||
timer.currentPosixTime(),
|
||||
Opm::unit::convert::to(timer.simulationTimeElapsed(),
|
||||
Opm::unit::day),
|
||||
nx, ny, nz,
|
||||
numCells,
|
||||
ertPhaseMask(uses));
|
||||
|
||||
ecl_rst_file_fwrite_header(restartFileHandle_,
|
||||
reportStepIdx,
|
||||
rsthead_data);
|
||||
|
||||
}
|
||||
|
||||
ecl_rst_file_type *ertHandle() const
|
||||
@@ -849,6 +968,51 @@ void Summary::addAllWells(Opm::EclipseStateConstPtr eclipseState,
|
||||
}
|
||||
} // end namespace EclipseWriterDetails
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert opm-core WellType and InjectorType to eclipse welltype
|
||||
*/
|
||||
int EclipseWriter::eclipseWellTypeMask(WellType wellType, WellInjector::TypeEnum injectorType)
|
||||
{
|
||||
int ert_well_type = IWEL_UNDOCUMENTED_ZERO;
|
||||
|
||||
if (PRODUCER == wellType) {
|
||||
ert_well_type = IWEL_PRODUCER;
|
||||
} else if (INJECTOR == wellType) {
|
||||
switch (injectorType) {
|
||||
case WellInjector::WATER:
|
||||
ert_well_type = IWEL_WATER_INJECTOR;
|
||||
break;
|
||||
case WellInjector::GAS:
|
||||
ert_well_type = IWEL_GAS_INJECTOR;
|
||||
break;
|
||||
case WellInjector::OIL :
|
||||
ert_well_type = IWEL_OIL_INJECTOR;
|
||||
break;
|
||||
default:
|
||||
ert_well_type = IWEL_UNDOCUMENTED_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
return ert_well_type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert opm-core WellStatus to eclipse format: > 0 open, <= 0 shut
|
||||
*/
|
||||
int EclipseWriter::eclipseWellStatusMask(WellCommon::StatusEnum wellStatus)
|
||||
{
|
||||
int well_status = 0;
|
||||
|
||||
if (wellStatus == WellCommon::OPEN) {
|
||||
well_status = 1;
|
||||
}
|
||||
return well_status;
|
||||
}
|
||||
|
||||
|
||||
void EclipseWriter::writeInit(const SimulatorTimer &timer)
|
||||
{
|
||||
// if we don't want to write anything, this method becomes a
|
||||
@@ -894,6 +1058,7 @@ void EclipseWriter::writeInit(const SimulatorTimer &timer)
|
||||
summary_->addAllWells(eclipseState_, phaseUsage_);
|
||||
}
|
||||
|
||||
|
||||
void EclipseWriter::writeTimeStep(const SimulatorTimer& timer,
|
||||
const SimulatorState& reservoirState,
|
||||
const WellState& wellState)
|
||||
@@ -909,15 +1074,51 @@ void EclipseWriter::writeTimeStep(const SimulatorTimer& timer,
|
||||
return;
|
||||
}
|
||||
|
||||
// start writing to files
|
||||
|
||||
std::vector<WellConstPtr> wells_ptr = eclipseState_->getSchedule()->getWells(timer.currentStepNum());
|
||||
std::vector<int> iwell_data;
|
||||
std::vector<const char*> zwell_data;
|
||||
std::vector<int> icon_data;
|
||||
|
||||
ecl_rsthead_type rsthead_data = { 0 };
|
||||
rsthead_data.sim_time = timer.currentPosixTime();
|
||||
rsthead_data.nactive = numCells_;
|
||||
rsthead_data.nx = cartesianSize_[0];
|
||||
rsthead_data.ny = cartesianSize_[1];
|
||||
rsthead_data.nz = cartesianSize_[2];
|
||||
rsthead_data.nwells = eclipseState_->getSchedule()->numWells(timer.currentStepNum());
|
||||
rsthead_data.niwelz = 0;
|
||||
rsthead_data.nzwelz = 0;
|
||||
rsthead_data.niconz = 0;
|
||||
rsthead_data.ncwmax = 0;
|
||||
rsthead_data.phase_sum = Opm::EclipseWriterDetails::ertPhaseMask(phaseUsage_);
|
||||
|
||||
EclipseWriterDetails::Restart restartHandle(outputDir_, baseName_, reportStepIdx_);
|
||||
|
||||
for (std::vector<WellConstPtr>::const_iterator c_iter = wells_ptr.begin(); c_iter != wells_ptr.end(); ++c_iter) {
|
||||
WellConstPtr well_ptr = *c_iter;
|
||||
|
||||
rsthead_data.ncwmax = eclipseState_->getSchedule()->getMaxNumCompletionsForWells(timer.currentStepNum());
|
||||
restartHandle.addRestartFileIwelData(iwell_data, timer.currentStepNum(), well_ptr);
|
||||
restartHandle.addRestartFileZwelData(zwell_data, timer.currentStepNum(), well_ptr);
|
||||
restartHandle.addRestartFileIconData(icon_data, timer.currentStepNum(), rsthead_data.ncwmax, well_ptr);
|
||||
|
||||
rsthead_data.niwelz = EclipseWriterDetails::Restart::NIWELZ;
|
||||
rsthead_data.nzwelz = EclipseWriterDetails::Restart::NZWELZ;
|
||||
rsthead_data.niconz = EclipseWriterDetails::Restart::NICONZ;
|
||||
}
|
||||
|
||||
rsthead_data.sim_days = Opm::unit::convert::to(timer.simulationTimeElapsed(), Opm::unit::day); //data for doubhead
|
||||
|
||||
restartHandle.writeHeader(timer,
|
||||
reportStepIdx_,
|
||||
numCells_,
|
||||
cartesianSize_[0],
|
||||
cartesianSize_[1],
|
||||
cartesianSize_[2],
|
||||
phaseUsage_);
|
||||
&rsthead_data);
|
||||
|
||||
|
||||
restartHandle.add_kw(EclipseWriterDetails::Keyword<int>(IWEL_KW, iwell_data));
|
||||
restartHandle.add_kw(EclipseWriterDetails::Keyword<const char *>(ZWEL_KW, zwell_data));
|
||||
restartHandle.add_kw(EclipseWriterDetails::Keyword<int>(ICON_KW, icon_data));
|
||||
|
||||
EclipseWriterDetails::Solution sol(restartHandle);
|
||||
|
||||
// write out the pressure of the reference phase (whatever phase that is...). this is
|
||||
@@ -949,6 +1150,7 @@ void EclipseWriter::writeTimeStep(const SimulatorTimer& timer,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Summary variables (well reporting) */
|
||||
// TODO: instead of writing the header (smspec) every time, it should
|
||||
// only be written when there is a change in the well configuration
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <opm/core/io/OutputWriter.hpp>
|
||||
#include <opm/core/props/BlackoilPhases.hpp>
|
||||
#include <opm/core/wells.h> // WellType
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
|
||||
@@ -97,6 +98,9 @@ public:
|
||||
const SimulatorState& reservoirState,
|
||||
const WellState& wellState);
|
||||
|
||||
static int eclipseWellTypeMask(WellType wellType, WellInjector::TypeEnum injectorType);
|
||||
static int eclipseWellStatusMask(WellCommon::StatusEnum wellStatus);
|
||||
|
||||
private:
|
||||
Opm::EclipseStateConstPtr eclipseState_;
|
||||
int numCells_;
|
||||
@@ -114,6 +118,10 @@ private:
|
||||
|
||||
void init(const parameter::ParameterGroup& params);
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<EclipseWriter> EclipseWriterPtr;
|
||||
typedef std::shared_ptr<const EclipseWriter> EclipseWriterConstPtr;
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
|
||||
|
||||
@@ -90,6 +90,11 @@ namespace Opm
|
||||
const int current_step,
|
||||
const double current_time,
|
||||
const boost::posix_time::ptime& current_date_time,
|
||||
const int num_wells,
|
||||
const int niwelz,
|
||||
const int nzwelz,
|
||||
const int niconz,
|
||||
const int ncwmax,
|
||||
const std::string& output_dir,
|
||||
const std::string& base_name) {
|
||||
|
||||
@@ -98,7 +103,6 @@ namespace Opm
|
||||
|
||||
char * filename = ecl_util_alloc_filename(output_dir.c_str() , base_name.c_str() , file_type , fmt_file , current_step );
|
||||
int phases = ECL_OIL_PHASE + ECL_WATER_PHASE;
|
||||
double days = Opm::unit::convert::to(current_time, Opm::unit::day);
|
||||
time_t date = 0;
|
||||
int nx = grid.cartdims[0];
|
||||
int ny = grid.cartdims[1];
|
||||
@@ -119,7 +123,25 @@ namespace Opm
|
||||
else
|
||||
rst_file = ecl_rst_file_open_write( filename );
|
||||
|
||||
ecl_rst_file_fwrite_header( rst_file , current_step , date , days , nx , ny , nz , nactive , phases );
|
||||
{
|
||||
ecl_rsthead_type rsthead_data = { 0 };
|
||||
rsthead_data.nx = nx;
|
||||
rsthead_data.ny = ny;
|
||||
rsthead_data.nz = nz;
|
||||
rsthead_data.nwells = num_wells;
|
||||
rsthead_data.niwelz = niwelz;
|
||||
rsthead_data.nzwelz = nzwelz;
|
||||
rsthead_data.niconz = niconz;
|
||||
rsthead_data.ncwmax = ncwmax;
|
||||
rsthead_data.nactive = nactive;
|
||||
rsthead_data.phase_sum = phases;
|
||||
rsthead_data.sim_time = date;
|
||||
|
||||
rsthead_data.sim_days = Opm::unit::convert::to(current_time, Opm::unit::day); //Data for doubhead
|
||||
|
||||
ecl_rst_file_fwrite_header( rst_file , current_step , &rsthead_data);
|
||||
}
|
||||
|
||||
ecl_rst_file_start_solution( rst_file );
|
||||
|
||||
{
|
||||
|
||||
119
tests/testBlackoilState3.DATA
Normal file
119
tests/testBlackoilState3.DATA
Normal file
@@ -0,0 +1,119 @@
|
||||
RUNSPEC
|
||||
|
||||
TITLE
|
||||
UNIT TEST
|
||||
|
||||
|
||||
START
|
||||
1 NOV 1979 /
|
||||
|
||||
OIL
|
||||
GAS
|
||||
WATER
|
||||
|
||||
|
||||
METRIC
|
||||
|
||||
DIMENS
|
||||
10 10 10 /
|
||||
|
||||
GRID
|
||||
DXV
|
||||
10*10 /
|
||||
|
||||
DYV
|
||||
10*10 /
|
||||
|
||||
DZV
|
||||
10*10 /
|
||||
|
||||
DEPTHZ
|
||||
121*1000 /
|
||||
/
|
||||
|
||||
|
||||
|
||||
|
||||
SCHEDULE
|
||||
|
||||
|
||||
RPTSCHED
|
||||
RESTART=2/
|
||||
|
||||
DATES
|
||||
1 DES 1979/
|
||||
/
|
||||
|
||||
WELSPECS
|
||||
'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
'OP_2' 'OP' 8 8 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
'OP_3' 'OP' 7 7 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
/
|
||||
|
||||
COMPDAT
|
||||
'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
||||
'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 /
|
||||
'OP_1' 9 9 3 3 'OPEN' 1* 51.867 0.311 4799.764 1* 1* 'X' 22.143 /
|
||||
'OP_1' 9 9 4 4 'OPEN' 1* 34.243 0.311 3169.482 1* 1* 'X' 22.166 /
|
||||
'OP_1' 9 9 5 5 'OPEN' 1* 36.435 0.311 3375.309 1* 1* 'X' 22.262 /
|
||||
'OP_1' 9 9 6 6 'OPEN' 1* 39.630 0.311 3672.067 1* 1* 'X' 22.283 /
|
||||
'OP_1' 9 9 7 7 'OPEN' 1* 33.975 0.311 3148.671 1* 1* 'X' 22.307 /
|
||||
'OP_1' 9 9 8 8 'OPEN' 1* 24.869 0.311 2305.242 1* 1* 'X' 22.329 /
|
||||
'OP_1' 9 9 9 9 'OPEN' 1* 38.301 0.311 3551.043 1* 1* 'X' 22.351 /
|
||||
'OP_1' 9 9 10 10 'OPEN' 1* 6.642 0.311 615.914 1* 1* 'X' 22.372 /
|
||||
'OP_2' 8 8 1 3 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Y' 21.925 /
|
||||
'OP_2' 8 7 3 3 'OPEN' 1* 15.071 0.311 1391.859 1* 1* 'Y' 21.920 /
|
||||
'OP_2' 8 7 3 6 'OPEN' 1* 6.242 0.311 576.458 1* 1* 'Y' 21.915 /
|
||||
'OP_3' 7 7 1 1 'OPEN' 1* 27.412 0.311 2445.337 1* 1* 'Y' 18.521 /
|
||||
'OP_3' 7 7 2 2 'OPEN' 1* 55.195 0.311 4923.842 1* 1* 'Y' 18.524 /
|
||||
'OP_3' 7 7 3 3 'OPEN' 1* 18.032 0.311 1608.615 1* 1* 'Y' 18.526 /
|
||||
'OP_3' 7 7 4 4 'OPEN' 1* 56.817 0.311 5047.177 1* 1* 'Y' 18.155 /
|
||||
'OP_3' 7 7 5 5 'OPEN' 1* 4.728 0.311 420.067 1* 1* 'Y' 18.162 /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 JUN 1980/
|
||||
/
|
||||
|
||||
|
||||
WELSPECS
|
||||
'OP_4' 'OP' 2 2 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
'OP_5' 'OP' 5 4 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
'OP_6' 'OP' 8 2 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
/
|
||||
|
||||
COMPDAT
|
||||
'OP_4' 2 2 1 10 'OPEN' 1* 6.642 0.311 615.914 1* 1* 'X' 22.372 /
|
||||
'OP_5' 5 4 1 3 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Y' 21.925 /
|
||||
'OP_6' 8 2 1 3 'OPEN' 1* 27.412 0.311 2445.337 1* 1* 'Y' 18.521 /
|
||||
'OP_6' 8 3 3 3 'OPEN' 1* 55.195 0.311 4923.842 1* 1* 'Y' 18.524 /
|
||||
'OP_6' 8 4 3 3 'OPEN' 1* 18.032 0.311 1608.615 1* 1* 'Y' 18.526 /
|
||||
'OP_6' 8 5 3 5 'OPEN' 1* 56.817 0.311 5047.177 1* 1* 'Y' 18.155 /
|
||||
'OP_6' 8 5 5 6 'OPEN' 1* 4.728 0.311 420.067 1* 1* 'Y' 18.162 /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 NOV 1980/
|
||||
/
|
||||
|
||||
WELSPECS
|
||||
'WI_1' 'WI' 3 3 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
'WI_2' 'WI' 3 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
'WI_3' 'WI' 3 6 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
/
|
||||
|
||||
COMPDAT
|
||||
'WI_1' 3 3 1 10 'OPEN' 1* 6.642 0.311 615.914 1* 1* 'X' 22.372 /
|
||||
'WI_2' 3 9 1 7 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Y' 21.925 /
|
||||
'WI_3' 3 6 1 3 'OPEN' 1* 27.412 0.311 2445.337 1* 1* 'Y' 18.521 /
|
||||
/
|
||||
|
||||
|
||||
|
||||
|
||||
DATES
|
||||
1 NOV 1982/
|
||||
/
|
||||
|
||||
END
|
||||
|
||||
194
tests/test_writenumwells.cpp
Normal file
194
tests/test_writenumwells.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
/*
|
||||
Copyright 2014 Statoil IT
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_DYNAMIC_BOOST_TEST
|
||||
#define BOOST_TEST_DYN_LINK
|
||||
#endif
|
||||
|
||||
#define BOOST_TEST_MODULE EclipseWriter
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <opm/core/io/eclipse/EclipseWriter.hpp>
|
||||
#include <opm/core/grid/GridManager.hpp>
|
||||
#include <opm/core/props/phaseUsageFromDeck.hpp>
|
||||
#include <opm/core/simulator/BlackoilState.hpp>
|
||||
#include <opm/core/simulator/WellState.hpp>
|
||||
#include <opm/core/simulator/SimulatorTimer.hpp>
|
||||
#include <opm/core/utility/parameters/ParameterGroup.hpp>
|
||||
#include <opm/core/wells.h>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
|
||||
// ERT stuff
|
||||
#include <ert/ecl/ecl_kw.h>
|
||||
#include <ert/ecl/ecl_file.h>
|
||||
#include <ert/ecl/ecl_kw_magic.h>
|
||||
#include <ert/ecl_well/well_info.h>
|
||||
#include <ert/ecl_well/well_state.h>
|
||||
#include <ert/util/test_work_area.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void verifyWellState(const std::string& rst_filename,
|
||||
Opm::EclipseGridConstPtr ecl_grid,
|
||||
Opm::ScheduleConstPtr schedule) {
|
||||
|
||||
well_info_type * well_info = well_info_alloc(ecl_grid->c_ptr());
|
||||
well_info_load_rstfile(well_info, rst_filename.c_str(), false);
|
||||
|
||||
//Verify numwells
|
||||
int numwells = well_info_get_num_wells(well_info);
|
||||
BOOST_CHECK(numwells == (int)schedule->numWells());
|
||||
|
||||
std::vector<Opm::WellConstPtr> wells = schedule->getWells();
|
||||
|
||||
for (int i = 0; i < numwells; ++i) {
|
||||
|
||||
//Verify wellnames
|
||||
const char * wellname = well_info_iget_well_name(well_info, i);
|
||||
Opm::WellConstPtr well = wells.at(i);
|
||||
BOOST_CHECK(wellname == well->name());
|
||||
|
||||
// Verify well-head position data
|
||||
well_ts_type * well_ts = well_info_get_ts(well_info , wellname);
|
||||
well_state_type * well_state = well_ts_iget_state(well_ts, 0);
|
||||
const well_conn_type * well_head = well_state_get_wellhead(well_state, ECL_GRID_GLOBAL_GRID);
|
||||
BOOST_CHECK(well_conn_get_i(well_head) == well->getHeadI());
|
||||
BOOST_CHECK(well_conn_get_j(well_head) == well->getHeadJ());
|
||||
|
||||
for (int j = 0; j < well_ts_get_size(well_ts); ++j) {
|
||||
well_state_type * well_state = well_ts_iget_state(well_ts, j);
|
||||
|
||||
//Verify welltype
|
||||
int ert_well_type = well_state_get_type(well_state);
|
||||
WellType welltype = well->isProducer(j) ? PRODUCER : INJECTOR;
|
||||
Opm::WellInjector::TypeEnum injectortype = well->getInjectionProperties(j).injectorType;
|
||||
int ecl_converted_welltype = Opm::EclipseWriter::eclipseWellTypeMask(welltype, injectortype);
|
||||
int ert_converted_welltype = well_state_translate_ecl_type_int(ecl_converted_welltype);
|
||||
BOOST_CHECK(ert_well_type == ert_converted_welltype);
|
||||
|
||||
//Verify wellstatus
|
||||
int ert_well_status = well_state_is_open(well_state) ? 1 : 0;
|
||||
|
||||
Opm::WellCommon::StatusEnum status = well->getStatus(j);
|
||||
int wellstatus = Opm::EclipseWriter::eclipseWellStatusMask(status);
|
||||
|
||||
BOOST_CHECK(ert_well_status == wellstatus);
|
||||
|
||||
//Verify number of completion connections
|
||||
const well_conn_collection_type * well_connections = well_state_get_global_connections( well_state );
|
||||
size_t num_wellconnections = well_conn_collection_get_size(well_connections);
|
||||
|
||||
int report_nr = well_state_get_report_nr(well_state);
|
||||
Opm::CompletionSetConstPtr completions_set = well->getCompletions((size_t)report_nr);
|
||||
|
||||
BOOST_CHECK(num_wellconnections == completions_set->size());
|
||||
|
||||
//Verify coordinates for each completion connection
|
||||
for (size_t k = 0; k < num_wellconnections; ++k) {
|
||||
const well_conn_type * well_connection = well_conn_collection_iget_const(well_connections , k);
|
||||
|
||||
Opm::CompletionConstPtr completion = completions_set->get(k);
|
||||
|
||||
BOOST_CHECK(well_conn_get_i(well_connection) == completion->getI());
|
||||
BOOST_CHECK(well_conn_get_j(well_connection) == completion->getJ());
|
||||
BOOST_CHECK(well_conn_get_k(well_connection) == completion->getK());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
well_info_free(well_info);
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Opm::BlackoilState> createBlackOilState(Opm::EclipseGridConstPtr eclGrid) {
|
||||
|
||||
std::shared_ptr<Opm::GridManager> ourFineGridManagerPtr(new Opm::GridManager(eclGrid));
|
||||
std::shared_ptr<Opm::BlackoilState> blackoilState(new Opm::BlackoilState);
|
||||
blackoilState->init(*ourFineGridManagerPtr->c_grid(), 3);
|
||||
|
||||
return blackoilState;
|
||||
}
|
||||
|
||||
|
||||
Opm::DeckConstPtr createDeck(const std::string& eclipse_data_filename) {
|
||||
Opm::ParserPtr parser(new Opm::Parser());
|
||||
Opm::ParserLogPtr parserLog(new Opm::ParserLog);
|
||||
Opm::DeckConstPtr deck = parser->parseFile(eclipse_data_filename, true, parserLog);
|
||||
|
||||
return deck;
|
||||
}
|
||||
|
||||
|
||||
Opm::EclipseWriterPtr createEclipseWriter(Opm::DeckConstPtr deck,
|
||||
Opm::EclipseStatePtr eclipseState,
|
||||
std::string& eclipse_data_filename) {
|
||||
|
||||
Opm::parameter::ParameterGroup params;
|
||||
params.insertParameter("deck_filename", eclipse_data_filename);
|
||||
|
||||
const Opm::PhaseUsage phaseUsage = Opm::phaseUsageFromDeck(deck);
|
||||
|
||||
Opm::EclipseWriterPtr eclWriter(new Opm::EclipseWriter(params,
|
||||
eclipseState,
|
||||
phaseUsage,
|
||||
eclipseState->getEclipseGrid()->getCartesianSize(),
|
||||
0));
|
||||
return eclWriter;
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(EclipseWriteRestartWellInfo)
|
||||
{
|
||||
std::string eclipse_data_filename = "testBlackoilState3.DATA";
|
||||
std::string eclipse_restart_filename = "TESTBLACKOILSTATE3.UNRST";
|
||||
|
||||
test_work_area_type * test_area = test_work_area_alloc("TEST_EclipseWriteNumWells");
|
||||
test_work_area_copy_file(test_area, eclipse_data_filename.c_str());
|
||||
|
||||
Opm::DeckConstPtr deck = createDeck(eclipse_data_filename);
|
||||
Opm::EclipseStatePtr eclipseState(new Opm::EclipseState(deck));
|
||||
Opm::EclipseWriterPtr eclipseWriter = createEclipseWriter(deck, eclipseState, eclipse_data_filename);
|
||||
|
||||
std::shared_ptr<Opm::SimulatorTimer> simTimer( new Opm::SimulatorTimer() );
|
||||
simTimer->init(eclipseState->getSchedule()->getTimeMap());
|
||||
|
||||
eclipseWriter->writeInit(*simTimer);
|
||||
|
||||
std::shared_ptr<Opm::WellState> wellState(new Opm::WellState());
|
||||
std::shared_ptr<Opm::BlackoilState> blackoilState = createBlackOilState(eclipseState->getEclipseGrid());
|
||||
wellState->init(0, *blackoilState);
|
||||
|
||||
int countTimeStep = eclipseState->getSchedule()->getTimeMap()->numTimesteps();
|
||||
|
||||
for(int timestep=0; timestep <= countTimeStep; ++timestep){
|
||||
simTimer->setCurrentStepNum(timestep);
|
||||
eclipseWriter->writeTimeStep(*simTimer, *blackoilState, *wellState);
|
||||
}
|
||||
|
||||
verifyWellState(eclipse_restart_filename, eclipseState->getEclipseGrid(), eclipseState->getSchedule());
|
||||
|
||||
test_work_area_free(test_area);
|
||||
}
|
||||
Reference in New Issue
Block a user