Merge 9b034978bd
into 9a0ccfd853
This commit is contained in:
commit
22a6bc3e16
@ -16,40 +16,42 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef COMPLETED_CELLS
|
#ifndef COMPLETED_CELLS
|
||||||
#define COMPLETED_CELLS
|
#define COMPLETED_CELLS
|
||||||
#include <optional>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/GridDims.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/GridDims.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <optional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
class CompletedCells {
|
class CompletedCells
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Cell
|
||||||
struct Cell {
|
{
|
||||||
std::size_t global_index;
|
std::size_t global_index;
|
||||||
std::size_t i, j, k;
|
std::size_t i, j, k;
|
||||||
|
|
||||||
struct Props{
|
struct Props
|
||||||
std::size_t active_index;
|
{
|
||||||
double permx;
|
std::size_t active_index{};
|
||||||
double permy;
|
double permx{};
|
||||||
double permz;
|
double permy{};
|
||||||
int satnum;
|
double permz{};
|
||||||
int pvtnum;
|
double poro{};
|
||||||
double ntg;
|
int satnum{};
|
||||||
|
int pvtnum{};
|
||||||
|
double ntg{};
|
||||||
|
|
||||||
bool operator==(const Props& other) const{
|
bool operator==(const Props& other) const;
|
||||||
return this->active_index == other.active_index &&
|
|
||||||
this->permx == other.permx &&
|
static Props serializationTestObject();
|
||||||
this->permy == other.permy &&
|
|
||||||
this->permz == other.permz &&
|
|
||||||
this->satnum == other.satnum &&
|
|
||||||
this->pvtnum == other.pvtnum &&
|
|
||||||
this->ntg == other.ntg;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Serializer>
|
template<class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
@ -57,46 +59,23 @@ public:
|
|||||||
serializer(this->permx);
|
serializer(this->permx);
|
||||||
serializer(this->permy);
|
serializer(this->permy);
|
||||||
serializer(this->permz);
|
serializer(this->permz);
|
||||||
|
serializer(this->poro);
|
||||||
serializer(this->satnum);
|
serializer(this->satnum);
|
||||||
serializer(this->pvtnum);
|
serializer(this->pvtnum);
|
||||||
serializer(this->ntg);
|
serializer(this->ntg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Props serializationTestObject(){
|
|
||||||
Props props;
|
|
||||||
props.permx = 10.0;
|
|
||||||
props.permy = 78.0;
|
|
||||||
props.permz = 45.4;
|
|
||||||
props.satnum = 3;
|
|
||||||
props.pvtnum = 5;
|
|
||||||
props.ntg = 45.1;
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<Props> props;
|
std::optional<Props> props;
|
||||||
std::size_t active_index() const;
|
std::size_t active_index() const;
|
||||||
bool is_active() const;
|
bool is_active() const;
|
||||||
|
|
||||||
double depth;
|
double depth{};
|
||||||
std::array<double, 3> dimensions;
|
std::array<double, 3> dimensions{};
|
||||||
|
|
||||||
bool operator==(const Cell& other) const {
|
bool operator==(const Cell& other) const;
|
||||||
return this->global_index == other.global_index &&
|
|
||||||
this->i == other.i &&
|
|
||||||
this->j == other.j &&
|
|
||||||
this->k == other.k &&
|
|
||||||
this->depth == other.depth &&
|
|
||||||
this->dimensions == other.dimensions &&
|
|
||||||
this->props == other.props;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Cell serializationTestObject() {
|
static Cell serializationTestObject();
|
||||||
Cell cell(0,1,1,1);
|
|
||||||
cell.depth = 12345;
|
|
||||||
cell.dimensions = {1.0,2.0,3.0};
|
|
||||||
return cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Serializer>
|
template<class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
@ -123,6 +102,7 @@ public:
|
|||||||
CompletedCells() = default;
|
CompletedCells() = default;
|
||||||
explicit CompletedCells(const GridDims& dims);
|
explicit CompletedCells(const GridDims& dims);
|
||||||
CompletedCells(std::size_t nx, std::size_t ny, std::size_t nz);
|
CompletedCells(std::size_t nx, std::size_t ny, std::size_t nz);
|
||||||
|
|
||||||
const Cell& get(std::size_t i, std::size_t j, std::size_t k) const;
|
const Cell& get(std::size_t i, std::size_t j, std::size_t k) const;
|
||||||
std::pair<bool, Cell&> try_get(std::size_t i, std::size_t j, std::size_t k);
|
std::pair<bool, Cell&> try_get(std::size_t i, std::size_t j, std::size_t k);
|
||||||
|
|
||||||
@ -141,5 +121,5 @@ private:
|
|||||||
std::unordered_map<std::size_t, Cell> cells;
|
std::unordered_map<std::size_t, Cell> cells;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#endif // COMPLETED_CELLS
|
||||||
|
@ -21,17 +21,30 @@
|
|||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
class EclipseGrid;
|
class EclipseGrid;
|
||||||
class FieldPropsManager;
|
class FieldPropsManager;
|
||||||
|
|
||||||
class ScheduleGrid {
|
} // namespace Opm
|
||||||
|
|
||||||
|
namespace Opm {
|
||||||
|
|
||||||
|
class ScheduleGrid
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
ScheduleGrid(const EclipseGrid& ecl_grid, const FieldPropsManager& fpm, CompletedCells& completed_cells);
|
ScheduleGrid(const EclipseGrid& ecl_grid,
|
||||||
|
const FieldPropsManager& fpm,
|
||||||
|
CompletedCells& completed_cells);
|
||||||
|
|
||||||
explicit ScheduleGrid(CompletedCells& completed_cells);
|
explicit ScheduleGrid(CompletedCells& completed_cells);
|
||||||
|
|
||||||
const CompletedCells::Cell& get_cell(std::size_t i, std::size_t j, std::size_t k) const;
|
const CompletedCells::Cell&
|
||||||
|
get_cell(std::size_t i, std::size_t j, std::size_t k) const;
|
||||||
|
|
||||||
const Opm::EclipseGrid* get_grid() const;
|
const Opm::EclipseGrid* get_grid() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -40,8 +53,6 @@ private:
|
|||||||
CompletedCells& cells;
|
CompletedCells& cells;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace Opm
|
||||||
|
|
||||||
|
#endif // SCHEDULE_GRID
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -17,91 +17,172 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef COMPLETION_HPP_
|
#ifndef COMPLETION_HPP_
|
||||||
#define COMPLETION_HPP_
|
#define COMPLETION_HPP_
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
|
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
namespace RestartIO {
|
|
||||||
struct RstConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DeckKeyword;
|
class DeckKeyword;
|
||||||
class DeckRecord;
|
class DeckRecord;
|
||||||
class ScheduleGrid;
|
class ScheduleGrid;
|
||||||
class FieldPropsManager;
|
class FieldPropsManager;
|
||||||
|
} // namespace Opm
|
||||||
|
|
||||||
class Connection {
|
namespace Opm { namespace RestartIO {
|
||||||
|
struct RstConnection;
|
||||||
|
}} // namespace Opm::RestartIO
|
||||||
|
|
||||||
|
namespace Opm {
|
||||||
|
|
||||||
|
class Connection
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
enum class State {
|
enum class State {
|
||||||
OPEN = 1,
|
OPEN = 1,
|
||||||
SHUT = 2,
|
SHUT = 2,
|
||||||
AUTO = 3 // Seems like the AUTO state can not be serialized to restart files.
|
AUTO = 3, // Seems like the AUTO state can not be serialized to restart files.
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string State2String( State enumValue );
|
static std::string State2String(State enumValue);
|
||||||
static State StateFromString( const std::string& stringValue );
|
static State StateFromString(std::string_view stringValue);
|
||||||
|
|
||||||
|
|
||||||
enum class Direction{
|
enum class Direction {
|
||||||
X = 1,
|
X = 1,
|
||||||
Y = 2,
|
Y = 2,
|
||||||
Z = 3
|
Z = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string Direction2String(const Direction enumValue);
|
static std::string Direction2String(const Direction enumValue);
|
||||||
static Direction DirectionFromString(const std::string& stringValue);
|
static Direction DirectionFromString(std::string_view stringValue);
|
||||||
|
|
||||||
|
|
||||||
enum class Order {
|
enum class Order {
|
||||||
DEPTH,
|
DEPTH,
|
||||||
INPUT,
|
INPUT,
|
||||||
TRACK
|
TRACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string Order2String( Order enumValue );
|
static std::string Order2String(Order enumValue);
|
||||||
static Order OrderFromString(const std::string& comporderStringValue);
|
static Order OrderFromString(std::string_view comporderStringValue);
|
||||||
|
|
||||||
|
|
||||||
enum class CTFKind {
|
enum class CTFKind {
|
||||||
DeckValue,
|
DeckValue,
|
||||||
Defaulted,
|
Defaulted,
|
||||||
};
|
};
|
||||||
|
|
||||||
Connection();
|
|
||||||
Connection(int i, int j , int k ,
|
|
||||||
std::size_t global_index,
|
|
||||||
int complnum,
|
|
||||||
double depth,
|
|
||||||
State state,
|
|
||||||
double CF,
|
|
||||||
double Kh,
|
|
||||||
double rw,
|
|
||||||
double r0,
|
|
||||||
double re,
|
|
||||||
double connection_length,
|
|
||||||
double skin_factor,
|
|
||||||
double d_factor,
|
|
||||||
double Ke,
|
|
||||||
const int satTableId,
|
|
||||||
const Direction direction,
|
|
||||||
const CTFKind ctf_kind,
|
|
||||||
const std::size_t sort_value,
|
|
||||||
const bool defaultSatTabId);
|
|
||||||
|
|
||||||
Connection(const RestartIO::RstConnection& rst_connection, const ScheduleGrid& grid, const FieldPropsManager& fp);
|
/// Quantities that go into calculating the connection
|
||||||
|
/// transmissibility factor.
|
||||||
|
struct CTFProperties
|
||||||
|
{
|
||||||
|
/// Static connection transmissibility factor calculated from
|
||||||
|
/// input quantities.
|
||||||
|
double CF{};
|
||||||
|
|
||||||
|
/// Static 'Kh' product
|
||||||
|
double Kh{};
|
||||||
|
|
||||||
|
/// Effective permeability.
|
||||||
|
double Ke{};
|
||||||
|
|
||||||
|
/// Connection's wellbore radius
|
||||||
|
double rw{};
|
||||||
|
|
||||||
|
/// Connection's pressure equivalent radius
|
||||||
|
double r0{};
|
||||||
|
|
||||||
|
/// Connection's area equivalent radius--mostly for use by the
|
||||||
|
/// polymer code.
|
||||||
|
double re{};
|
||||||
|
|
||||||
|
/// Length of connection's perfororation interval
|
||||||
|
double connection_length{};
|
||||||
|
|
||||||
|
/// Connection's skin factor.
|
||||||
|
double skin_factor{};
|
||||||
|
|
||||||
|
/// Connection's D factor-i.e., the flow-dependent skin factor
|
||||||
|
/// for gas.
|
||||||
|
double d_factor{};
|
||||||
|
|
||||||
|
/// Product of certain static elements of D-factor correlation
|
||||||
|
/// law (WDFACCOR keyword).
|
||||||
|
double static_dfac_corr_coeff{};
|
||||||
|
|
||||||
|
/// Denominator in peaceman's formula-i.e., log(r0/rw) + skin.
|
||||||
|
double peaceman_denom{};
|
||||||
|
|
||||||
|
/// Serialisation test object.
|
||||||
|
static CTFProperties serializationTestObject();
|
||||||
|
|
||||||
|
/// Equality operator
|
||||||
|
///
|
||||||
|
/// \param[in] that Property object to which \c *this will be compared.
|
||||||
|
bool operator==(const CTFProperties& that) const;
|
||||||
|
|
||||||
|
/// Inequality operator
|
||||||
|
///
|
||||||
|
/// \param[in] that Property object to which \c *this will be compared.
|
||||||
|
bool operator!=(const CTFProperties& that) const
|
||||||
|
{
|
||||||
|
return ! (*this == that);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialisation operator
|
||||||
|
///
|
||||||
|
/// \tparam Serializer Protocol for serialising and
|
||||||
|
/// deserialising objects between memory and character
|
||||||
|
/// buffers.
|
||||||
|
///
|
||||||
|
/// \param[in,out] serializer Serialisation object.
|
||||||
|
template <class Serializer>
|
||||||
|
void serializeOp(Serializer& serializer)
|
||||||
|
{
|
||||||
|
serializer(this->CF);
|
||||||
|
serializer(this->Kh);
|
||||||
|
serializer(this->Ke);
|
||||||
|
serializer(this->rw);
|
||||||
|
serializer(this->r0);
|
||||||
|
serializer(this->re);
|
||||||
|
serializer(this->connection_length);
|
||||||
|
serializer(this->skin_factor);
|
||||||
|
serializer(this->d_factor);
|
||||||
|
serializer(this->static_dfac_corr_coeff);
|
||||||
|
serializer(this->peaceman_denom);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Connection() = default;
|
||||||
|
Connection(int i, int j, int k,
|
||||||
|
std::size_t global_index,
|
||||||
|
int complnum,
|
||||||
|
State state,
|
||||||
|
Direction direction,
|
||||||
|
CTFKind ctf_kind,
|
||||||
|
const int satTableId,
|
||||||
|
double depth,
|
||||||
|
const CTFProperties& ctf_properties,
|
||||||
|
const std::size_t sort_value,
|
||||||
|
const bool defaultSatTabId);
|
||||||
|
|
||||||
|
Connection(const RestartIO::RstConnection& rst_connection,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const FieldPropsManager& fp);
|
||||||
|
|
||||||
static Connection serializationTestObject();
|
static Connection serializationTestObject();
|
||||||
|
|
||||||
@ -117,104 +198,105 @@ namespace RestartIO {
|
|||||||
int satTableId() const;
|
int satTableId() const;
|
||||||
int complnum() const;
|
int complnum() const;
|
||||||
int segment() const;
|
int segment() const;
|
||||||
double CF() const;
|
|
||||||
double wpimult() const;
|
double wpimult() const;
|
||||||
|
double CF() const;
|
||||||
double Kh() const;
|
double Kh() const;
|
||||||
|
double Ke() const;
|
||||||
double rw() const;
|
double rw() const;
|
||||||
double r0() const;
|
double r0() const;
|
||||||
double re() const;
|
double re() const;
|
||||||
double connectionLength() const;
|
double connectionLength() const;
|
||||||
double skinFactor() const;
|
double skinFactor() const;
|
||||||
double dFactor() const;
|
double dFactor() const;
|
||||||
double Ke() const;
|
|
||||||
CTFKind kind() const;
|
CTFKind kind() const;
|
||||||
const InjMult& injmult() const;
|
const InjMult& injmult() const;
|
||||||
bool activeInjMult() const;
|
bool activeInjMult() const;
|
||||||
void setInjMult(const InjMult& inj_mult);
|
|
||||||
void setFilterCake(const FilterCake& filter_cake);
|
|
||||||
const FilterCake& getFilterCake() const;
|
const FilterCake& getFilterCake() const;
|
||||||
bool filterCakeActive() const;
|
bool filterCakeActive() const;
|
||||||
double getFilterCakeRadius() const;
|
double getFilterCakeRadius() const;
|
||||||
double getFilterCakeArea() const;
|
double getFilterCakeArea() const;
|
||||||
|
|
||||||
|
const CTFProperties& ctfProperties() const
|
||||||
|
{
|
||||||
|
return this->ctf_properties_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t sort_value() const;
|
||||||
|
bool getDefaultSatTabId() const;
|
||||||
|
const std::optional<std::pair<double, double>>& perf_range() const;
|
||||||
|
std::string str() const;
|
||||||
|
|
||||||
|
bool ctfAssignedFromInput() const
|
||||||
|
{
|
||||||
|
return this->m_ctfkind == CTFKind::DeckValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Connection&) const;
|
||||||
|
bool operator!=(const Connection& that) const
|
||||||
|
{
|
||||||
|
return ! (*this == that);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setInjMult(const InjMult& inj_mult);
|
||||||
|
void setFilterCake(const FilterCake& filter_cake);
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
void setComplnum(int compnum);
|
void setComplnum(int compnum);
|
||||||
void setSkinFactor(double skin_factor);
|
void setSkinFactor(double skin_factor);
|
||||||
void setDFactor(double d_factor);
|
void setDFactor(double d_factor);
|
||||||
void setKe(double Ke);
|
void setKe(double Ke);
|
||||||
void setCF(double CF);
|
void setCF(double CF);
|
||||||
|
void setDefaultSatTabId(bool id);
|
||||||
|
void setStaticDFacCorrCoeff(const double c);
|
||||||
|
|
||||||
void scaleWellPi(double wellPi);
|
void scaleWellPi(double wellPi);
|
||||||
bool prepareWellPIScaling();
|
bool prepareWellPIScaling();
|
||||||
bool applyWellPIScaling(const double scaleFactor);
|
bool applyWellPIScaling(const double scaleFactor);
|
||||||
|
|
||||||
void updateSegmentRST(int segment_number_arg,
|
void updateSegmentRST(int segment_number_arg,
|
||||||
double center_depth_arg);
|
double center_depth_arg);
|
||||||
void updateSegment(int segment_number_arg,
|
void updateSegment(int segment_number_arg,
|
||||||
double center_depth_arg,
|
double center_depth_arg,
|
||||||
std::size_t compseg_insert_index,
|
std::size_t compseg_insert_index,
|
||||||
const std::optional<std::pair<double,double>>& perf_range);
|
const std::optional<std::pair<double,double>>& perf_range);
|
||||||
std::size_t sort_value() const;
|
|
||||||
const bool& getDefaultSatTabId() const;
|
|
||||||
void setDefaultSatTabId(bool id);
|
|
||||||
const std::optional<std::pair<double, double>>& perf_range() const;
|
|
||||||
std::string str() const;
|
|
||||||
bool ctfAssignedFromInput() const
|
|
||||||
{
|
|
||||||
return this->m_ctfkind == CTFKind::DeckValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==( const Connection& ) const;
|
|
||||||
bool operator!=( const Connection& ) const;
|
|
||||||
|
|
||||||
template<class Serializer>
|
template<class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
{
|
{
|
||||||
serializer(direction);
|
serializer(this->direction);
|
||||||
serializer(center_depth);
|
serializer(this->center_depth);
|
||||||
serializer(open_state);
|
serializer(this->open_state);
|
||||||
serializer(sat_tableId);
|
serializer(this->sat_tableId);
|
||||||
serializer(m_complnum);
|
serializer(this->m_complnum);
|
||||||
serializer(m_CF);
|
serializer(this->ctf_properties_);
|
||||||
serializer(m_Kh);
|
serializer(this->ijk);
|
||||||
serializer(m_rw);
|
serializer(this->m_ctfkind);
|
||||||
serializer(m_r0);
|
serializer(this->m_global_index);
|
||||||
serializer(m_re);
|
serializer(this->m_injmult);
|
||||||
serializer(m_connection_length);
|
serializer(this->m_sort_value);
|
||||||
serializer(m_skin_factor);
|
serializer(this->m_perf_range);
|
||||||
serializer(m_d_factor);
|
serializer(this->m_defaultSatTabId);
|
||||||
serializer(m_Ke);
|
serializer(this->segment_number);
|
||||||
serializer(ijk);
|
serializer(this->m_wpimult);
|
||||||
serializer(m_global_index);
|
serializer(this->m_subject_to_welpi);
|
||||||
serializer(m_ctfkind);
|
serializer(this->m_filter_cake);
|
||||||
serializer(m_injmult);
|
|
||||||
serializer(m_sort_value);
|
|
||||||
serializer(m_perf_range);
|
|
||||||
serializer(m_defaultSatTabId);
|
|
||||||
serializer(segment_number);
|
|
||||||
serializer(m_subject_to_welpi);
|
|
||||||
serializer(m_filter_cake);
|
|
||||||
serializer(m_wpimult);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Direction direction;
|
// Note to maintainer: If you add new members to this list, then
|
||||||
double center_depth;
|
// please also update the operator==(), serializeOp(), and
|
||||||
State open_state;
|
// serializationTestObject() member functions.
|
||||||
int sat_tableId;
|
Direction direction { Direction::Z };
|
||||||
int m_complnum;
|
double center_depth { 0.0 };
|
||||||
double m_CF;
|
State open_state { State::SHUT };
|
||||||
double m_Kh;
|
int sat_tableId { -1 };
|
||||||
double m_rw;
|
int m_complnum { -1 };
|
||||||
double m_r0;
|
CTFProperties ctf_properties_{};
|
||||||
double m_re;
|
|
||||||
double m_connection_length;
|
std::array<int,3> ijk{};
|
||||||
double m_skin_factor;
|
CTFKind m_ctfkind { CTFKind::DeckValue };
|
||||||
double m_d_factor;
|
std::optional<InjMult> m_injmult{};
|
||||||
double m_Ke;
|
std::size_t m_global_index{};
|
||||||
|
|
||||||
std::array<int,3> ijk;
|
|
||||||
CTFKind m_ctfkind;
|
|
||||||
std::optional<InjMult> m_injmult;
|
|
||||||
std::size_t m_global_index;
|
|
||||||
/*
|
/*
|
||||||
The sort_value member is a peculiar quantity. The connections are
|
The sort_value member is a peculiar quantity. The connections are
|
||||||
assembled in the WellConnections class. During the lifetime of the
|
assembled in the WellConnections class. During the lifetime of the
|
||||||
@ -266,26 +348,26 @@ namespace RestartIO {
|
|||||||
explicitly, so the truth is probably that the storage order
|
explicitly, so the truth is probably that the storage order
|
||||||
during simulation makes no difference?
|
during simulation makes no difference?
|
||||||
*/
|
*/
|
||||||
|
std::size_t m_sort_value{};
|
||||||
|
|
||||||
std::size_t m_sort_value;
|
std::optional<std::pair<double,double>> m_perf_range{};
|
||||||
std::optional<std::pair<double,double>> m_perf_range;
|
bool m_defaultSatTabId{true};
|
||||||
bool m_defaultSatTabId;
|
|
||||||
|
|
||||||
// related segment number
|
// Associate segment number
|
||||||
// 0 means the completion is not related to segment
|
//
|
||||||
int segment_number = 0;
|
// 0 means the connection is not associated to a segment.
|
||||||
|
int segment_number { 0 };
|
||||||
|
|
||||||
|
double m_wpimult { 1.0 };
|
||||||
|
|
||||||
// Whether or not this Connection is subject to WELPI scaling.
|
// Whether or not this Connection is subject to WELPI scaling.
|
||||||
bool m_subject_to_welpi = false;
|
bool m_subject_to_welpi { false };
|
||||||
|
|
||||||
// For applying last known WPIMULT to when calculating connection transmissibilty factor in CSKIN
|
std::optional<FilterCake> m_filter_cake{};
|
||||||
double m_wpimult = 1.0;
|
|
||||||
|
|
||||||
std::optional<FilterCake> m_filter_cake;
|
|
||||||
|
|
||||||
static std::string CTFKindToString(const CTFKind);
|
static std::string CTFKindToString(const CTFKind);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* COMPLETION_HPP_ */
|
} // namespace Opm
|
||||||
|
|
||||||
|
#endif // COMPLETION_HPP_
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define WDFAC_HPP_HEADER_INCLUDED
|
#define WDFAC_HPP_HEADER_INCLUDED
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
class Connection;
|
||||||
class DeckRecord;
|
class DeckRecord;
|
||||||
class WellConnections;
|
class WellConnections;
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
@ -31,49 +32,221 @@ namespace Opm { namespace RestartIO {
|
|||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
enum class WDFACTYPE {
|
|
||||||
NONE = 1,
|
|
||||||
DFACTOR = 2,
|
|
||||||
DAKEMODEL = 3,
|
|
||||||
CON_DFACTOR = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
class WDFAC
|
class WDFAC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/// Parameters for Dake's D-factor correlation model.
|
||||||
|
///
|
||||||
|
/// In particular, holds the coefficient 'A' and the exponents 'B'
|
||||||
|
/// and 'C' of the correlation relation
|
||||||
|
///
|
||||||
|
/// D = A * (Ke/K0)**B * porosity**C * Ke / (h * rw) * (sg_g/mu_g)
|
||||||
|
///
|
||||||
|
/// in which
|
||||||
|
///
|
||||||
|
/// * Ke is the connection's effective permeability (sqrt(Kx*Ky)
|
||||||
|
/// in the case of a vertical connection)
|
||||||
|
///
|
||||||
|
/// * K0 is a reference/background permeability scale (1mD)
|
||||||
|
///
|
||||||
|
/// * h is the effective length of the connection's perforation
|
||||||
|
/// interval (dz*ntg in the case of a vertical connection)
|
||||||
|
///
|
||||||
|
/// * rw is the connection's wellbore radius
|
||||||
|
///
|
||||||
|
/// * sg_g is the specific gravity of surface condition gas
|
||||||
|
/// relative to surface condition air
|
||||||
|
///
|
||||||
|
/// * mu_g is the reservoir condition viscosity of the free gas phase.
|
||||||
|
struct Correlation
|
||||||
|
{
|
||||||
|
/// Multiplicative coefficient 'A'.
|
||||||
|
double coeff_a{0.0};
|
||||||
|
|
||||||
|
/// Power coefficient 'B' for the effective permeability.
|
||||||
|
double exponent_b{0.0};
|
||||||
|
|
||||||
|
/// Power coefficient 'C' for the porosity term.
|
||||||
|
double exponent_c{0.0};
|
||||||
|
|
||||||
|
/// Serialisation test object.
|
||||||
|
static Correlation serializationTestObject();
|
||||||
|
|
||||||
|
/// Equality operator
|
||||||
|
///
|
||||||
|
/// \param[in] other Object to which \c *this will be compared.
|
||||||
|
bool operator==(const Correlation& other) const;
|
||||||
|
|
||||||
|
/// Inequality operator
|
||||||
|
///
|
||||||
|
/// \param[in] other Object to which \c *this will be compared.
|
||||||
|
bool operator!=(const Correlation& other) const
|
||||||
|
{
|
||||||
|
return ! (*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialisation operator
|
||||||
|
///
|
||||||
|
/// \tparam Serializer Protocol for serialising and
|
||||||
|
/// deserialising objects between memory and character
|
||||||
|
/// buffers.
|
||||||
|
///
|
||||||
|
/// \param[in,out] serializer Serialisation object.
|
||||||
|
template <class Serializer>
|
||||||
|
void serializeOp(Serializer& serializer)
|
||||||
|
{
|
||||||
|
serializer(this->coeff_a);
|
||||||
|
serializer(this->exponent_b);
|
||||||
|
serializer(this->exponent_c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Default constructor
|
||||||
|
WDFAC() = default;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
///
|
||||||
|
/// Creates an object from restart information
|
||||||
|
///
|
||||||
|
/// \param[in] rst_well Linearised well-level restart information,
|
||||||
|
/// including D-factor parameters.
|
||||||
|
explicit WDFAC(const RestartIO::RstWell& rst_well);
|
||||||
|
|
||||||
|
/// Serialisation test object
|
||||||
static WDFAC serializationTestObject();
|
static WDFAC serializationTestObject();
|
||||||
|
|
||||||
double getDFactor(const Connection& connection, double mu, double rho, double phi) const;
|
/// Configure D-factor calculation from well-level D-factor
|
||||||
|
/// description (keyword 'WDFAC')
|
||||||
|
///
|
||||||
|
/// \param[in] record Well-level D-factor description. Single
|
||||||
|
/// record from WDFAC keyword.
|
||||||
void updateWDFAC(const DeckRecord& record);
|
void updateWDFAC(const DeckRecord& record);
|
||||||
//void updateWDFAC(const RestartIO::RstWell& rst_well);
|
|
||||||
void updateWDFACCOR(const DeckRecord& record);
|
|
||||||
//void updateWDFACOR(const RestartIO::RstWell& rst_well);
|
|
||||||
|
|
||||||
|
/// Configure D-factor calculation from Dake correlation model
|
||||||
|
/// (keyword WDFACCOR).
|
||||||
|
///
|
||||||
|
/// \param[in] record Dake correlation model description. Single
|
||||||
|
/// record from WDFACCOR keyword.
|
||||||
|
void updateWDFACCOR(const DeckRecord& record);
|
||||||
|
|
||||||
|
/// Check if any input-level connctions have a non-trivial D-factor
|
||||||
|
/// and update this well's D-factor category accordingly.
|
||||||
|
///
|
||||||
|
/// \param[in] connections Connection set as defined by keyword
|
||||||
|
/// COMPDAT. This function will detect if any of the connections
|
||||||
|
/// created from COMPDAT define a non-trivial D-factor at the
|
||||||
|
/// connection level (item 12 of COMPDAT) and update the D-factor
|
||||||
|
/// category if so.
|
||||||
void updateWDFACType(const WellConnections& connections);
|
void updateWDFACType(const WellConnections& connections);
|
||||||
|
|
||||||
|
/// Capture sum of all CTFs for the purpose of translating
|
||||||
|
/// well-level D-factors to connection-level D-factors.
|
||||||
|
///
|
||||||
|
/// \param[in] connections Connection set as defined by keyword
|
||||||
|
/// COMPDAT.
|
||||||
void updateTotalCF(const WellConnections& connections);
|
void updateTotalCF(const WellConnections& connections);
|
||||||
|
|
||||||
|
/// Retrieve currently configured D-factor for single connection
|
||||||
|
///
|
||||||
|
/// \param[in] rhoGS Surface condition mass density of gas
|
||||||
|
///
|
||||||
|
/// \param[in] gas_visc Reservoir condition gas viscosity
|
||||||
|
///
|
||||||
|
/// \param[in] conn Reservoir connection for which to retrieve the
|
||||||
|
/// D-factor.
|
||||||
|
///
|
||||||
|
/// \return D-factor for connection \p conn.
|
||||||
|
double getDFactor(const double rhoGS,
|
||||||
|
const double gas_visc,
|
||||||
|
const Connection& conn) const;
|
||||||
|
|
||||||
|
/// Retrieve current D-factor correlation model coefficients.
|
||||||
|
const Correlation& getDFactorCorrelationCoefficients() const
|
||||||
|
{
|
||||||
|
return this->m_corr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether or not a flow-dependent skin factor ('D') has been
|
||||||
|
/// configured for the current well.
|
||||||
bool useDFactor() const;
|
bool useDFactor() const;
|
||||||
|
|
||||||
|
/// Equality operator
|
||||||
|
///
|
||||||
|
/// \param[in] other Object to which \c *this will be compared.
|
||||||
bool operator==(const WDFAC& other) const;
|
bool operator==(const WDFAC& other) const;
|
||||||
bool operator!=(const WDFAC& other) const;
|
|
||||||
|
|
||||||
template<class Serializer>
|
/// Inequality operator
|
||||||
|
///
|
||||||
|
/// \param[in] other Object to which \c *this will be compared.
|
||||||
|
bool operator!=(const WDFAC& other) const
|
||||||
|
{
|
||||||
|
return ! (*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialisation operator
|
||||||
|
///
|
||||||
|
/// \tparam Serializer Protocol for serialising and deserialising
|
||||||
|
/// objects between memory and character buffers.
|
||||||
|
///
|
||||||
|
/// \param[in,out] serializer Serialisation object.
|
||||||
|
template <class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
{
|
{
|
||||||
serializer(m_a);
|
serializer(this->m_type);
|
||||||
serializer(m_b);
|
serializer(this->m_d);
|
||||||
serializer(m_c);
|
serializer(this->m_total_cf);
|
||||||
serializer(m_d);
|
serializer(this->m_corr);
|
||||||
serializer(m_total_cf);
|
|
||||||
serializer(m_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double m_a{0.0};
|
/// D-factor categories.
|
||||||
double m_b{0.0};
|
enum class WDFacType
|
||||||
double m_c{0.0};
|
{
|
||||||
|
/// No flow-dependent skin factor is configured for this well.
|
||||||
|
NONE = 1,
|
||||||
|
|
||||||
|
/// Well-level D-factor.
|
||||||
|
DFACTOR = 2,
|
||||||
|
|
||||||
|
/// Use Dake's D-factor correlation model.
|
||||||
|
DAKEMODEL = 3,
|
||||||
|
|
||||||
|
/// Connection-level D-factor.
|
||||||
|
CON_DFACTOR = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// D-factor category for this well.
|
||||||
|
WDFacType m_type { WDFacType::NONE };
|
||||||
|
|
||||||
|
/// Well-level D-factor for this well.
|
||||||
double m_d{0.0};
|
double m_d{0.0};
|
||||||
|
|
||||||
|
/// Total CTF sum for this well.
|
||||||
double m_total_cf{-1.0};
|
double m_total_cf{-1.0};
|
||||||
WDFACTYPE m_type = WDFACTYPE::NONE;
|
|
||||||
|
/// Coefficients for Dake's correlation model.
|
||||||
|
Correlation m_corr{};
|
||||||
|
|
||||||
|
/// Retrieve connection-level D-Factor from COMPDAT entries
|
||||||
|
///
|
||||||
|
/// Possibly translated from well-level values.
|
||||||
|
///
|
||||||
|
/// \param[in] conn Reservoir connection for which to retrieve the
|
||||||
|
/// D-factor.
|
||||||
|
///
|
||||||
|
/// \return Connection-level D-factor.
|
||||||
|
double connectionLevelDFactor(const Connection& conn) const;
|
||||||
|
|
||||||
|
/// Translate well-level D-factor to connection level D-factor
|
||||||
|
///
|
||||||
|
/// \param[in] dfac Well-level D-factor.
|
||||||
|
///
|
||||||
|
/// \param[in] conn Reservoir connection for which to retrieve the
|
||||||
|
/// D-factor.
|
||||||
|
///
|
||||||
|
/// \return Connection-level D-factor, translated from well level.
|
||||||
|
double scaledWellLevelDFactor(const double dfac,
|
||||||
|
const Connection& conn) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
@ -527,7 +527,7 @@ public:
|
|||||||
bool handleWELSEGS(const DeckKeyword& keyword);
|
bool handleWELSEGS(const DeckKeyword& keyword);
|
||||||
bool handleCOMPSEGS(const DeckKeyword& keyword, const ScheduleGrid& grid, const ParseContext& parseContext, ErrorGuard& errors);
|
bool handleCOMPSEGS(const DeckKeyword& keyword, const ScheduleGrid& grid, const ParseContext& parseContext, ErrorGuard& errors);
|
||||||
bool handleWELOPENConnections(const DeckRecord& record, Connection::State status);
|
bool handleWELOPENConnections(const DeckRecord& record, Connection::State status);
|
||||||
bool handleCSKINConnections(const DeckRecord& record);
|
bool handleCSKIN(const DeckRecord& record, const KeywordLocation& location);
|
||||||
bool handleCOMPLUMP(const DeckRecord& record);
|
bool handleCOMPLUMP(const DeckRecord& record);
|
||||||
bool handleWPIMULT(const DeckRecord& record);
|
bool handleWPIMULT(const DeckRecord& record);
|
||||||
bool handleWINJCLN(const DeckRecord& record, const KeywordLocation& location);
|
bool handleWINJCLN(const DeckRecord& record, const KeywordLocation& location);
|
||||||
|
@ -23,9 +23,11 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
#include <external/resinsight/LibGeometry/cvfBoundingBoxTree.h>
|
#include <external/resinsight/LibGeometry/cvfBoundingBoxTree.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -33,10 +35,11 @@
|
|||||||
namespace Opm {
|
namespace Opm {
|
||||||
class ActiveGridCells;
|
class ActiveGridCells;
|
||||||
class DeckRecord;
|
class DeckRecord;
|
||||||
|
class EclipseGrid;
|
||||||
class FieldPropsManager;
|
class FieldPropsManager;
|
||||||
class KeywordLocation;
|
class KeywordLocation;
|
||||||
class ScheduleGrid;
|
class ScheduleGrid;
|
||||||
class EclipseGrid;
|
class WDFAC;
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
@ -67,19 +70,16 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add(const Connection& conn)
|
||||||
|
{
|
||||||
|
this->m_connections.push_back(conn);
|
||||||
|
}
|
||||||
|
|
||||||
void addConnection(const int i, const int j, const int k,
|
void addConnection(const int i, const int j, const int k,
|
||||||
const std::size_t global_index,
|
const std::size_t global_index,
|
||||||
const double depth,
|
|
||||||
const Connection::State state,
|
const Connection::State state,
|
||||||
const double CF,
|
const double depth,
|
||||||
const double Kh,
|
const Connection::CTFProperties& ctf_props,
|
||||||
const double rw,
|
|
||||||
const double r0,
|
|
||||||
const double re,
|
|
||||||
const double connection_length,
|
|
||||||
const double skin_factor,
|
|
||||||
const double d_factor,
|
|
||||||
const double Ke,
|
|
||||||
const int satTableId,
|
const int satTableId,
|
||||||
const Connection::Direction direction = Connection::Direction::Z,
|
const Connection::Direction direction = Connection::Direction::Z,
|
||||||
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
||||||
@ -89,16 +89,26 @@ namespace Opm {
|
|||||||
void loadCOMPDAT(const DeckRecord& record,
|
void loadCOMPDAT(const DeckRecord& record,
|
||||||
const ScheduleGrid& grid,
|
const ScheduleGrid& grid,
|
||||||
const std::string& wname,
|
const std::string& wname,
|
||||||
|
const WDFAC& wdfac,
|
||||||
const KeywordLocation& location);
|
const KeywordLocation& location);
|
||||||
|
|
||||||
void loadCOMPTRAJ(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, const KeywordLocation& location, external::cvf::ref<external::cvf::BoundingBoxTree>& cellSearchTree);
|
void loadCOMPTRAJ(const DeckRecord& record,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const std::string& wname,
|
||||||
|
const KeywordLocation& location,
|
||||||
|
external::cvf::ref<external::cvf::BoundingBoxTree>& cellSearchTree);
|
||||||
|
|
||||||
void loadWELTRAJ(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, const KeywordLocation& location);
|
void loadWELTRAJ(const DeckRecord& record,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const std::string& wname,
|
||||||
|
const KeywordLocation& location);
|
||||||
|
|
||||||
|
void applyDFactorCorrelation(const ScheduleGrid& grid,
|
||||||
|
const WDFAC& wdfac);
|
||||||
|
|
||||||
int getHeadI() const;
|
int getHeadI() const;
|
||||||
int getHeadJ() const;
|
int getHeadJ() const;
|
||||||
const std::vector<double>& getMD() const;
|
const std::vector<double>& getMD() const;
|
||||||
void add(Connection);
|
|
||||||
std::size_t size() const;
|
std::size_t size() const;
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
std::size_t num_open() const;
|
std::size_t num_open() const;
|
||||||
@ -165,39 +175,32 @@ namespace Opm {
|
|||||||
serializer(this->coord);
|
serializer(this->coord);
|
||||||
serializer(this->md);
|
serializer(this->md);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection::Order m_ordering { Connection::Order::TRACK };
|
Connection::Order m_ordering { Connection::Order::TRACK };
|
||||||
int headI{0};
|
int headI{0};
|
||||||
int headJ{0};
|
int headJ{0};
|
||||||
std::vector<Connection> m_connections{};
|
std::vector<Connection> m_connections{};
|
||||||
std::vector<std::vector<double>> coord{3, std::vector<double>(0, 0.0) };
|
|
||||||
|
std::array<std::vector<double>, 3> coord{};
|
||||||
std::vector<double> md{};
|
std::vector<double> md{};
|
||||||
|
|
||||||
void addConnection(const int i, const int j, const int k,
|
void addConnection(const int i, const int j, const int k,
|
||||||
const std::size_t global_index,
|
const std::size_t global_index,
|
||||||
const int complnum,
|
const int complnum,
|
||||||
const double depth,
|
|
||||||
const Connection::State state,
|
const Connection::State state,
|
||||||
const double CF,
|
const double depth,
|
||||||
const double Kh,
|
const Connection::CTFProperties& ctf_props,
|
||||||
const double rw,
|
|
||||||
const double r0,
|
|
||||||
const double re,
|
|
||||||
const double connection_length,
|
|
||||||
const double skin_factor,
|
|
||||||
const double d_factor,
|
|
||||||
const double Ke,
|
|
||||||
const int satTableId,
|
const int satTableId,
|
||||||
const Connection::Direction direction = Connection::Direction::Z,
|
const Connection::Direction direction,
|
||||||
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
const Connection::CTFKind ctf_kind,
|
||||||
const std::size_t seqIndex = 0,
|
const std::size_t seqIndex,
|
||||||
const bool defaultSatTabId = true);
|
const bool defaultSatTabId);
|
||||||
|
|
||||||
size_t findClosestConnection(int oi, int oj, double oz, size_t start_pos);
|
size_t findClosestConnection(int oi, int oj, double oz, size_t start_pos);
|
||||||
void orderTRACK();
|
void orderTRACK();
|
||||||
void orderMSW();
|
void orderMSW();
|
||||||
void orderDEPTH();
|
void orderDEPTH();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<int>
|
std::optional<int>
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
|
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
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
@ -19,19 +20,27 @@
|
|||||||
#ifndef RST_CONNECTION
|
#ifndef RST_CONNECTION
|
||||||
#define RST_CONNECTION
|
#define RST_CONNECTION
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
class UnitSystem;
|
class UnitSystem;
|
||||||
|
|
||||||
namespace RestartIO {
|
} // namespace Opm
|
||||||
|
|
||||||
class Header;
|
namespace Opm { namespace RestartIO {
|
||||||
|
|
||||||
|
struct RstConnection
|
||||||
|
{
|
||||||
|
RstConnection(const UnitSystem& unit_system,
|
||||||
|
std::size_t rst_index,
|
||||||
|
int nsconz,
|
||||||
|
const int* icon,
|
||||||
|
const float* scon,
|
||||||
|
const double *xcon);
|
||||||
|
|
||||||
struct RstConnection {
|
|
||||||
RstConnection(const ::Opm::UnitSystem& unit_system, std::size_t rst_index, int nsconz, const int* icon, const float* scon, const double *xcon);
|
|
||||||
static double inverse_peaceman(double cf, double kh, double rw, double skin);
|
static double inverse_peaceman(double cf, double kh, double rw, double skin);
|
||||||
|
|
||||||
std::size_t rst_index;
|
std::size_t rst_index;
|
||||||
@ -49,6 +58,9 @@ struct RstConnection {
|
|||||||
float depth;
|
float depth;
|
||||||
float diameter;
|
float diameter;
|
||||||
float kh;
|
float kh;
|
||||||
|
float denom;
|
||||||
|
float length;
|
||||||
|
float static_dfac_corr_coeff;
|
||||||
float segdist_end;
|
float segdist_end;
|
||||||
float segdist_start;
|
float segdist_start;
|
||||||
|
|
||||||
@ -60,11 +72,6 @@ struct RstConnection {
|
|||||||
double r0;
|
double r0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}} // namespace Opm::RestartIO
|
||||||
|
|
||||||
}
|
#endif // RST_CONNECTION
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -126,6 +126,9 @@ struct RstWell
|
|||||||
float glift_min_rate;
|
float glift_min_rate;
|
||||||
float glift_weight_factor;
|
float glift_weight_factor;
|
||||||
float glift_inc_weight_factor;
|
float glift_inc_weight_factor;
|
||||||
|
float dfac_corr_coeff_a{};
|
||||||
|
float dfac_corr_exponent_b{};
|
||||||
|
float dfac_corr_exponent_c{};
|
||||||
std::vector<float> tracer_concentration_injection;
|
std::vector<float> tracer_concentration_injection;
|
||||||
|
|
||||||
double oil_rate;
|
double oil_rate;
|
||||||
|
@ -36,9 +36,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm { namespace data {
|
||||||
|
|
||||||
namespace data {
|
|
||||||
|
|
||||||
class Rates {
|
class Rates {
|
||||||
/* Methods are defined inline for performance, as the actual *work* done
|
/* Methods are defined inline for performance, as the actual *work* done
|
||||||
@ -257,22 +255,25 @@ namespace Opm {
|
|||||||
double effective_Kh;
|
double effective_Kh;
|
||||||
double trans_factor;
|
double trans_factor;
|
||||||
double d_factor;
|
double d_factor;
|
||||||
|
double compact_mult{1.0}; // Rock compaction transmissibility multiplier (ROCKTAB)
|
||||||
|
|
||||||
ConnectionFiltrate filtrate;
|
ConnectionFiltrate filtrate;
|
||||||
|
|
||||||
bool operator==(const Connection& conn2) const
|
bool operator==(const Connection& conn2) const
|
||||||
{
|
{
|
||||||
return index == conn2.index &&
|
return (index == conn2.index)
|
||||||
rates == conn2.rates &&
|
&& (rates == conn2.rates)
|
||||||
pressure == conn2.pressure &&
|
&& (pressure == conn2.pressure)
|
||||||
reservoir_rate == conn2.reservoir_rate &&
|
&& (reservoir_rate == conn2.reservoir_rate)
|
||||||
cell_pressure == conn2.cell_pressure &&
|
&& (cell_pressure == conn2.cell_pressure)
|
||||||
cell_saturation_water == conn2.cell_saturation_water &&
|
&& (cell_saturation_water == conn2.cell_saturation_water)
|
||||||
cell_saturation_gas == conn2.cell_saturation_gas &&
|
&& (cell_saturation_gas == conn2.cell_saturation_gas)
|
||||||
effective_Kh == conn2.effective_Kh &&
|
&& (effective_Kh == conn2.effective_Kh)
|
||||||
trans_factor == conn2.trans_factor &&
|
&& (trans_factor == conn2.trans_factor)
|
||||||
d_factor == conn2.d_factor &&
|
&& (d_factor == conn2.d_factor)
|
||||||
filtrate == conn2.filtrate;
|
&& (compact_mult == conn2.compact_mult)
|
||||||
|
&& (filtrate == conn2.filtrate)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MessageBufferType>
|
template <class MessageBufferType>
|
||||||
@ -295,15 +296,18 @@ namespace Opm {
|
|||||||
serializer(effective_Kh);
|
serializer(effective_Kh);
|
||||||
serializer(trans_factor);
|
serializer(trans_factor);
|
||||||
serializer(d_factor);
|
serializer(d_factor);
|
||||||
|
serializer(compact_mult);
|
||||||
serializer(filtrate);
|
serializer(filtrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Connection serializationTestObject()
|
static Connection serializationTestObject()
|
||||||
{
|
{
|
||||||
return Connection{1, Rates::serializationTestObject(),
|
return Connection {
|
||||||
2.0, 3.0, 4.0, 5.0,
|
1, Rates::serializationTestObject(),
|
||||||
6.0, 7.0, 8.0, 9.0,
|
2.0, 3.0, 4.0, 5.0,
|
||||||
ConnectionFiltrate::serializationTestObject() };
|
6.0, 7.0, 8.0, 9.0, 0.987,
|
||||||
|
ConnectionFiltrate::serializationTestObject()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1187,6 +1191,7 @@ namespace Opm {
|
|||||||
buffer.write(this->effective_Kh);
|
buffer.write(this->effective_Kh);
|
||||||
buffer.write(this->trans_factor);
|
buffer.write(this->trans_factor);
|
||||||
buffer.write(this->d_factor);
|
buffer.write(this->d_factor);
|
||||||
|
buffer.write(this->compact_mult);
|
||||||
this->filtrate.write(buffer);
|
this->filtrate.write(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1203,6 +1208,7 @@ namespace Opm {
|
|||||||
json_data.add_item("Kh", this->effective_Kh);
|
json_data.add_item("Kh", this->effective_Kh);
|
||||||
json_data.add_item("trans_factor", this->trans_factor);
|
json_data.add_item("trans_factor", this->trans_factor);
|
||||||
json_data.add_item("d_factor", this->d_factor);
|
json_data.add_item("d_factor", this->d_factor);
|
||||||
|
json_data.add_item("compact_mult", this->compact_mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MessageBufferType>
|
template <class MessageBufferType>
|
||||||
@ -1349,6 +1355,7 @@ namespace Opm {
|
|||||||
buffer.read(this->effective_Kh);
|
buffer.read(this->effective_Kh);
|
||||||
buffer.read(this->trans_factor);
|
buffer.read(this->trans_factor);
|
||||||
buffer.read(this->d_factor);
|
buffer.read(this->d_factor);
|
||||||
|
buffer.read(this->compact_mult);
|
||||||
this->filtrate.read(buffer);
|
this->filtrate.read(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,19 +44,29 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
|
|||||||
|
|
||||||
namespace SConn {
|
namespace SConn {
|
||||||
enum index : std::vector<float>::size_type {
|
enum index : std::vector<float>::size_type {
|
||||||
ConnTrans = 0, // Connection transmissibility factor
|
EffConnTrans = 0, // Effective connection transmissibility factor (incl. ROCKTAB &c)
|
||||||
Depth = 1, // Connection centre depth
|
Depth = 1, // Connection centre depth
|
||||||
Diameter = 2, // Connection diameter
|
Diameter = 2, // Connection diameter
|
||||||
|
|
||||||
EffectiveKH = 3, // Effective Kh product of connection
|
EffectiveKH = 3, // Effective Kh product of connection
|
||||||
SkinFactor = 4, // Skinfactor - item 'SKIN' from COMPDAT
|
SkinFactor = 4, // Skinfactor - item 'SKIN' from COMPDAT
|
||||||
item12 = 11, // Connection transmissibility factor
|
|
||||||
|
CFDenom = 6, // Denominator in connection transmissibility
|
||||||
|
// factor expression
|
||||||
|
|
||||||
|
ConnTrans = 11, // Connection transmissibility factor
|
||||||
|
|
||||||
SegDistEnd = 20, // Distance to end of connection in segment
|
SegDistEnd = 20, // Distance to end of connection in segment
|
||||||
SegDistStart = 21, // Distance to start of connection in segment
|
SegDistStart = 21, // Distance to start of connection in segment
|
||||||
|
|
||||||
item30 = 29, // Unknown
|
item30 = 29, // Unknown
|
||||||
item31 = 30, // Unknown
|
item31 = 30, // Unknown
|
||||||
|
|
||||||
|
EffectiveLength = 31, // Effective length of connection's perforation interval.
|
||||||
|
|
||||||
|
StaticDFacCorrCoeff = 37, // Static component of Forchheimer
|
||||||
|
// D-factor correlation.
|
||||||
|
|
||||||
CFInDeck = 40, // = 0 for connection factor not defined, = 1 for connection factor defined
|
CFInDeck = 40, // = 0 for connection factor not defined, = 1 for connection factor defined
|
||||||
};
|
};
|
||||||
} // SConn
|
} // SConn
|
||||||
|
@ -331,6 +331,9 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
|
|||||||
VfpBhpScalingFact = 83, // Tubing pressure loss scaling factor (WVFPDP(3))
|
VfpBhpScalingFact = 83, // Tubing pressure loss scaling factor (WVFPDP(3))
|
||||||
WGrupConGRScaling = 84, // Guide rate scaling factor (WGRUPCON(5))
|
WGrupConGRScaling = 84, // Guide rate scaling factor (WGRUPCON(5))
|
||||||
|
|
||||||
|
DFacCorrCoeffA = 104, // Coefficient 'A' of D-factor correlation (WDFACCOR(2))
|
||||||
|
DFacCorrExpB = 105, // Exponent 'B' of D-factor correlation (WDFACCOR(3))
|
||||||
|
DFacCorrExpC = 106, // Exponent 'C' of D-factor correlation (WDFACCOR(4))
|
||||||
|
|
||||||
LOincFac = 115,
|
LOincFac = 115,
|
||||||
|
|
||||||
|
@ -19,50 +19,105 @@
|
|||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||||
|
|
||||||
|
bool Opm::CompletedCells::Cell::Props::operator==(const Props& other) const
|
||||||
|
{
|
||||||
|
return (this->active_index == other.active_index)
|
||||||
|
&& (this->permx == other.permx)
|
||||||
|
&& (this->permy == other.permy)
|
||||||
|
&& (this->permz == other.permz)
|
||||||
|
&& (this->poro == other.poro)
|
||||||
|
&& (this->satnum == other.satnum)
|
||||||
|
&& (this->pvtnum == other.pvtnum)
|
||||||
|
&& (this->ntg == other.ntg)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
Opm::CompletedCells::Cell::Props
|
||||||
|
Opm::CompletedCells::Cell::Props::serializationTestObject()
|
||||||
|
{
|
||||||
|
Props props;
|
||||||
|
|
||||||
|
props.permx = 10.0;
|
||||||
|
props.permy = 78.0;
|
||||||
|
props.permz = 45.4;
|
||||||
|
props.poro = 0.321;
|
||||||
|
props.satnum = 3;
|
||||||
|
props.pvtnum = 5;
|
||||||
|
props.ntg = 45.1;
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Opm::CompletedCells::Cell::operator==(const Cell& other) const
|
||||||
|
{
|
||||||
|
return (this->global_index == other.global_index)
|
||||||
|
&& (this->i == other.i)
|
||||||
|
&& (this->j == other.j)
|
||||||
|
&& (this->k == other.k)
|
||||||
|
&& (this->depth == other.depth)
|
||||||
|
&& (this->dimensions == other.dimensions)
|
||||||
|
&& (this->props == other.props)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
Opm::CompletedCells::Cell
|
||||||
|
Opm::CompletedCells::Cell::serializationTestObject()
|
||||||
|
{
|
||||||
|
Cell cell { 0, 1, 1, 1 };
|
||||||
|
|
||||||
|
cell.props = Props::serializationTestObject();
|
||||||
|
cell.depth = 12345;
|
||||||
|
cell.dimensions = {1.0,2.0,3.0};
|
||||||
|
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
Opm::CompletedCells::CompletedCells(std::size_t nx, std::size_t ny, std::size_t nz)
|
Opm::CompletedCells::CompletedCells(std::size_t nx, std::size_t ny, std::size_t nz)
|
||||||
: dims(nx,ny,nz)
|
: dims(nx, ny, nz)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
Opm::CompletedCells::CompletedCells(const Opm::GridDims& dims_)
|
Opm::CompletedCells::CompletedCells(const Opm::GridDims& dims_)
|
||||||
:dims(dims_)
|
: dims(dims_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
const Opm::CompletedCells::Cell&
|
||||||
const Opm::CompletedCells::Cell& Opm::CompletedCells::get(std::size_t i, std::size_t j, std::size_t k) const {
|
Opm::CompletedCells::get(std::size_t i, std::size_t j, std::size_t k) const
|
||||||
auto g = this->dims.getGlobalIndex(i,j,k);
|
{
|
||||||
return this->cells.at(g);
|
return this->cells.at(this->dims.getGlobalIndex(i, j, k));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool, Opm::CompletedCells::Cell&>
|
||||||
|
Opm::CompletedCells::try_get(std::size_t i, std::size_t j, std::size_t k)
|
||||||
|
{
|
||||||
|
const auto g = this->dims.getGlobalIndex(i, j, k);
|
||||||
|
|
||||||
std::pair<bool, Opm::CompletedCells::Cell&> Opm::CompletedCells::try_get(std::size_t i, std::size_t j, std::size_t k) {
|
const auto& [pos, inserted] = this->cells.try_emplace(g, g, i, j, k);
|
||||||
auto g = this->dims.getGlobalIndex(i,j,k);
|
|
||||||
auto iter = this->cells.find(g);
|
|
||||||
if (iter != this->cells.end())
|
|
||||||
return {true, iter->second};
|
|
||||||
|
|
||||||
this->cells.emplace(g, Cell{g,i,j,k});
|
return { !inserted, pos->second };
|
||||||
return {false, this->cells.at(g)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Opm::CompletedCells::operator==(const Opm::CompletedCells& other) const
|
||||||
bool Opm::CompletedCells::operator==(const Opm::CompletedCells& other) const {
|
{
|
||||||
return this->dims == other.dims &&
|
return (this->dims == other.dims)
|
||||||
this->cells == other.cells;
|
&& (this->cells == other.cells)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Opm::CompletedCells
|
||||||
Opm::CompletedCells Opm::CompletedCells::serializationTestObject() {
|
Opm::CompletedCells::serializationTestObject()
|
||||||
|
{
|
||||||
Opm::CompletedCells cells(2,3,4);
|
Opm::CompletedCells cells(2,3,4);
|
||||||
cells.cells.emplace(7, Opm::CompletedCells::Cell::serializationTestObject());
|
cells.cells.emplace(7, Opm::CompletedCells::Cell::serializationTestObject());
|
||||||
|
|
||||||
return cells;
|
return cells;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t Opm::CompletedCells::Cell::active_index() const{
|
std::size_t Opm::CompletedCells::Cell::active_index() const
|
||||||
|
{
|
||||||
return this->props.value().active_index;
|
return this->props.value().active_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Opm::CompletedCells::Cell::is_active() const{
|
bool Opm::CompletedCells::Cell::is_active() const
|
||||||
|
{
|
||||||
return this->props.has_value();
|
return this->props.has_value();
|
||||||
}
|
}
|
||||||
|
@ -196,37 +196,51 @@ namespace {
|
|||||||
this->snapshots.back().network.update( std::move( ext_network ));
|
this->snapshots.back().network.update( std::move( ext_network ));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handleCOMPDAT(HandlerContext& handlerContext) {
|
void Schedule::handleCOMPDAT(HandlerContext& handlerContext) {
|
||||||
std::unordered_set<std::string> wells;
|
std::unordered_set<std::string> wells;
|
||||||
for (const auto& record : handlerContext.keyword) {
|
for (const auto& record : handlerContext.keyword) {
|
||||||
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
|
const auto wellNamePattern = record.getItem("WELL").getTrimmedString(0);
|
||||||
auto wellnames = this->wellNames(wellNamePattern, handlerContext,
|
const auto wellnames =
|
||||||
isWList(handlerContext.currentStep,
|
this->wellNames(wellNamePattern, handlerContext,
|
||||||
wellNamePattern));
|
isWList(handlerContext.currentStep, wellNamePattern));
|
||||||
|
|
||||||
for (const auto& name : wellnames) {
|
for (const auto& name : wellnames) {
|
||||||
auto well2 = this->snapshots.back().wells.get(name);
|
auto well2 = this->snapshots.back().wells.get(name);
|
||||||
auto connections = std::shared_ptr<WellConnections>( new WellConnections( well2.getConnections()));
|
|
||||||
connections->loadCOMPDAT(record, handlerContext.grid, name, handlerContext.keyword.location());
|
|
||||||
|
|
||||||
if (well2.updateConnections(connections, handlerContext.grid)) {
|
auto connections = std::make_shared<WellConnections>(well2.getConnections());
|
||||||
|
const auto origWellConnSetIsEmpty = connections->empty();
|
||||||
|
|
||||||
|
connections->loadCOMPDAT(record, handlerContext.grid, name,
|
||||||
|
well2.getWDFAC(), handlerContext.keyword.location());
|
||||||
|
const auto newWellConnSetIsEmpty = connections->empty();
|
||||||
|
|
||||||
|
if (well2.updateConnections(std::move(connections), handlerContext.grid)) {
|
||||||
auto wdfac = std::make_shared<WDFAC>(well2.getWDFAC());
|
auto wdfac = std::make_shared<WDFAC>(well2.getWDFAC());
|
||||||
wdfac->updateWDFACType(*connections);
|
wdfac->updateWDFACType(well2.getConnections());
|
||||||
|
|
||||||
well2.updateWDFAC(std::move(wdfac));
|
well2.updateWDFAC(std::move(wdfac));
|
||||||
this->snapshots.back().wells.update( well2 );
|
this->snapshots.back().wells.update(well2);
|
||||||
wells.insert( name );
|
|
||||||
|
wells.insert(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connections->empty() && well2.getConnections().empty()) {
|
if (origWellConnSetIsEmpty && newWellConnSetIsEmpty) {
|
||||||
const auto& location = handlerContext.keyword.location();
|
const auto& location = handlerContext.keyword.location();
|
||||||
auto msg = fmt::format("Problem with COMPDAT/{}\n"
|
|
||||||
"In {} line {}\n"
|
const auto msg = fmt::format(R"(Problem with COMPDAT/{}
|
||||||
"Well {} is not connected to grid - will remain SHUT", name, location.filename, location.lineno, name);
|
In {} line {}
|
||||||
|
Well {} is not connected to grid - will remain SHUT)",
|
||||||
|
name, location.filename,
|
||||||
|
location.lineno, name);
|
||||||
|
|
||||||
OpmLog::warning(msg);
|
OpmLog::warning(msg);
|
||||||
}
|
}
|
||||||
this->snapshots.back().wellgroup_events().addEvent( name, ScheduleEvents::COMPLETION_CHANGE);
|
|
||||||
|
this->snapshots.back().wellgroup_events()
|
||||||
|
.addEvent(name, ScheduleEvents::COMPLETION_CHANGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
||||||
|
|
||||||
// In the case the wells reference depth has been defaulted in the
|
// In the case the wells reference depth has been defaulted in the
|
||||||
@ -234,9 +248,10 @@ namespace {
|
|||||||
// reference depth exactly when the COMPDAT keyword has been completely
|
// reference depth exactly when the COMPDAT keyword has been completely
|
||||||
// processed.
|
// processed.
|
||||||
for (const auto& wname : wells) {
|
for (const auto& wname : wells) {
|
||||||
auto& well = this->snapshots.back().wells.get( wname );
|
auto well = this->snapshots.back().wells.get(wname);
|
||||||
well.updateRefDepth();
|
well.updateRefDepth();
|
||||||
this->snapshots.back().wells.update( std::move(well));
|
|
||||||
|
this->snapshots.back().wells.update(std::move(well));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! wells.empty()) {
|
if (! wells.empty()) {
|
||||||
@ -268,20 +283,30 @@ namespace {
|
|||||||
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handleCOMPTRAJ(HandlerContext& handlerContext) {
|
void Schedule::handleCOMPTRAJ(HandlerContext& handlerContext)
|
||||||
|
{
|
||||||
// Keyword WELTRAJ must be read first
|
// Keyword WELTRAJ must be read first
|
||||||
std::unordered_set<std::string> wells;
|
std::unordered_set<std::string> wells;
|
||||||
external::cvf::ref<external::cvf::BoundingBoxTree> cellSearchTree = nullptr;
|
external::cvf::ref<external::cvf::BoundingBoxTree> cellSearchTree = nullptr;
|
||||||
|
|
||||||
for (const auto& record : handlerContext.keyword) {
|
for (const auto& record : handlerContext.keyword) {
|
||||||
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
|
const auto wellNamePattern = record.getItem("WELL").getTrimmedString(0);
|
||||||
auto wellnames = this->wellNames(wellNamePattern, handlerContext );
|
const auto wellnames = this->wellNames(wellNamePattern, handlerContext);
|
||||||
|
|
||||||
for (const auto& name : wellnames) {
|
for (const auto& name : wellnames) {
|
||||||
auto well2 = this->snapshots.back().wells.get(name);
|
auto well2 = this->snapshots.back().wells.get(name);
|
||||||
auto connections = std::make_shared<WellConnections>(WellConnections(well2.getConnections()));
|
auto connections = std::make_shared<WellConnections>(well2.getConnections());
|
||||||
// cellsearchTree is calculated only once and is used to calculated cell intersections of the perforations specified in COMPTRAJ
|
|
||||||
connections->loadCOMPTRAJ(record, handlerContext.grid, name, handlerContext.keyword.location(), cellSearchTree);
|
// cellsearchTree is calculated only once and is used to
|
||||||
// In the case that defaults are used in WELSPECS for headI/J the headI/J are calculated based on the well trajectory data
|
// calculated cell intersections of the perforations
|
||||||
|
// specified in COMPTRAJ
|
||||||
|
connections->loadCOMPTRAJ(record, handlerContext.grid, name,
|
||||||
|
handlerContext.keyword.location(),
|
||||||
|
cellSearchTree);
|
||||||
|
|
||||||
|
// In the case that defaults are used in WELSPECS for
|
||||||
|
// headI/J the headI/J are calculated based on the well
|
||||||
|
// trajectory data
|
||||||
well2.updateHead(connections->getHeadI(), connections->getHeadJ());
|
well2.updateHead(connections->getHeadI(), connections->getHeadJ());
|
||||||
if (well2.updateConnections(connections, handlerContext.grid)) {
|
if (well2.updateConnections(connections, handlerContext.grid)) {
|
||||||
this->snapshots.back().wells.update( well2 );
|
this->snapshots.back().wells.update( well2 );
|
||||||
@ -295,19 +320,23 @@ namespace {
|
|||||||
"Well {} is not connected to grid - will remain SHUT", name, location.filename, location.lineno, name);
|
"Well {} is not connected to grid - will remain SHUT", name, location.filename, location.lineno, name);
|
||||||
OpmLog::warning(msg);
|
OpmLog::warning(msg);
|
||||||
}
|
}
|
||||||
this->snapshots.back().wellgroup_events().addEvent( name, ScheduleEvents::COMPLETION_CHANGE);
|
|
||||||
|
this->snapshots.back().wellgroup_events()
|
||||||
|
.addEvent(name, ScheduleEvents::COMPLETION_CHANGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
this->snapshots.back().events().addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
||||||
|
|
||||||
// In the case the wells reference depth has been defaulted in the
|
// In the case the wells reference depth has been defaulted in the
|
||||||
// WELSPECS keyword we need to force a calculation of the wells
|
// WELSPECS keyword we need to force a calculation of the wells
|
||||||
// reference depth exactly when the WELCOML keyword has been completely
|
// reference depth exactly when the WELCOML keyword has been
|
||||||
// processed.
|
// completely processed.
|
||||||
for (const auto& wname : wells) {
|
for (const auto& wname : wells) {
|
||||||
auto& well = this->snapshots.back().wells.get( wname );
|
auto& well = this->snapshots.back().wells.get(wname);
|
||||||
well.updateRefDepth();
|
well.updateRefDepth();
|
||||||
this->snapshots.back().wells.update( std::move(well));
|
|
||||||
|
this->snapshots.back().wells.update(std::move(well));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! wells.empty()) {
|
if (! wells.empty()) {
|
||||||
@ -377,23 +406,29 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
|||||||
handlerContext.compsegs_handled(wname);
|
handlerContext.compsegs_handled(wname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handleCSKIN(HandlerContext& handlerContext) {
|
void Schedule::handleCSKIN(HandlerContext& handlerContext)
|
||||||
|
{
|
||||||
|
using Kw = ParserKeywords::CSKIN;
|
||||||
|
|
||||||
// Get CSKIN keyword info and current step
|
// Get CSKIN keyword info and current step
|
||||||
const auto& keyword = handlerContext.keyword;
|
const auto& keyword = handlerContext.keyword;
|
||||||
const auto& currentStep = handlerContext.currentStep;
|
const auto& currentStep = handlerContext.currentStep;
|
||||||
|
|
||||||
// Loop over records in CSKIN
|
// Loop over records in CSKIN
|
||||||
for (const auto& record: keyword) {
|
for (const auto& record : keyword) {
|
||||||
// Get well names
|
// Get well names
|
||||||
const auto& wellNamePattern = record.getItem( "WELL" ).getTrimmedString(0);
|
const auto wellNamePattern = record.getItem<Kw::WELL>().getTrimmedString(0);
|
||||||
const auto well_names = this->wellNames(wellNamePattern, handlerContext);
|
const auto well_names = this->wellNames(wellNamePattern, handlerContext);
|
||||||
|
|
||||||
// Loop over well(s) in record
|
// Loop over well(s) in record
|
||||||
for (const auto& wname : well_names) {
|
for (const auto& wname : well_names) {
|
||||||
// Get well information, modify connection skin factor, and update well
|
// Get well information, modify connection skin factor, and
|
||||||
|
// update well.
|
||||||
auto well = this->snapshots[currentStep].wells.get(wname);
|
auto well = this->snapshots[currentStep].wells.get(wname);
|
||||||
well.handleCSKINConnections(record);
|
|
||||||
this->snapshots[currentStep].wells.update( std::move(well) );
|
if (well.handleCSKIN(record, handlerContext.keyword.location())) {
|
||||||
|
this->snapshots[currentStep].wells.update(std::move(well));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1635,25 +1670,55 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
|||||||
auto wdfac = std::make_shared<WDFAC>(well.getWDFAC());
|
auto wdfac = std::make_shared<WDFAC>(well.getWDFAC());
|
||||||
wdfac->updateWDFAC( record );
|
wdfac->updateWDFAC( record );
|
||||||
wdfac->updateTotalCF(well.getConnections());
|
wdfac->updateTotalCF(well.getConnections());
|
||||||
if (well.updateWDFAC(std::move(wdfac)))
|
|
||||||
this->snapshots.back().wells.update( std::move(well) );
|
if (well.updateWDFAC(std::move(wdfac))) {
|
||||||
|
this->snapshots.back().wells.update(std::move(well));
|
||||||
|
|
||||||
|
handlerContext.affected_well(well_name);
|
||||||
|
handlerContext.record_well_structure_change();
|
||||||
|
|
||||||
|
this->snapshots.back().events()
|
||||||
|
.addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
||||||
|
|
||||||
|
this->snapshots.back().wellgroup_events()
|
||||||
|
.addEvent(well_name, ScheduleEvents::COMPLETION_CHANGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handleWDFACCOR(HandlerContext& handlerContext) {
|
void Schedule::handleWDFACCOR(HandlerContext& handlerContext) {
|
||||||
for (const auto& record : handlerContext.keyword) {
|
for (const auto& record : handlerContext.keyword) {
|
||||||
const std::string& wellNamePattern = record.getItem("WELLNAME").getTrimmedString(0);
|
const std::string wellNamePattern = record.getItem("WELLNAME").getTrimmedString(0);
|
||||||
const auto well_names = wellNames(wellNamePattern, handlerContext.currentStep);
|
const auto well_names = wellNames(wellNamePattern, handlerContext.currentStep);
|
||||||
if (well_names.empty())
|
if (well_names.empty())
|
||||||
this->invalidNamePattern(wellNamePattern, handlerContext);
|
this->invalidNamePattern(wellNamePattern, handlerContext);
|
||||||
|
|
||||||
for (const auto& well_name : well_names) {
|
for (const auto& well_name : well_names) {
|
||||||
auto well = this->snapshots.back().wells.get(well_name);
|
auto well = this->snapshots.back().wells.get(well_name);
|
||||||
|
auto conns = std::make_shared<WellConnections>(well.getConnections());
|
||||||
|
|
||||||
auto wdfac = std::make_shared<WDFAC>(well.getWDFAC());
|
auto wdfac = std::make_shared<WDFAC>(well.getWDFAC());
|
||||||
wdfac->updateWDFACCOR( record );
|
wdfac->updateWDFACCOR(record);
|
||||||
if (well.updateWDFAC(std::move(wdfac)))
|
|
||||||
this->snapshots.back().wells.update( std::move(well) );
|
conns->applyDFactorCorrelation(handlerContext.grid, *wdfac);
|
||||||
|
const auto updateConns =
|
||||||
|
well.updateConnections(std::move(conns), handlerContext.grid);
|
||||||
|
|
||||||
|
if (well.updateWDFAC(std::move(wdfac)) || updateConns) {
|
||||||
|
this->snapshots.back().wells.update(std::move(well));
|
||||||
|
|
||||||
|
handlerContext.affected_well(well_name);
|
||||||
|
handlerContext.record_well_structure_change();
|
||||||
|
|
||||||
|
if (updateConns) {
|
||||||
|
this->snapshots.back().events()
|
||||||
|
.addEvent(ScheduleEvents::COMPLETION_CHANGE);
|
||||||
|
|
||||||
|
this->snapshots.back().wellgroup_events()
|
||||||
|
.addEvent(well_name, ScheduleEvents::COMPLETION_CHANGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,16 +17,24 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
|
|
||||||
Opm::ScheduleGrid::ScheduleGrid(const Opm::EclipseGrid& ecl_grid, const Opm::FieldPropsManager& fpm, Opm::CompletedCells& completed_cells)
|
#include <cstddef>
|
||||||
: grid(&ecl_grid)
|
#include <string>
|
||||||
, fp(&fpm)
|
|
||||||
, cells(completed_cells)
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
Opm::ScheduleGrid::ScheduleGrid(const Opm::EclipseGrid& ecl_grid,
|
||||||
|
const Opm::FieldPropsManager& fpm,
|
||||||
|
Opm::CompletedCells& completed_cells)
|
||||||
|
: grid { &ecl_grid }
|
||||||
|
, fp { &fpm }
|
||||||
|
, cells { completed_cells }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Opm::ScheduleGrid::ScheduleGrid(Opm::CompletedCells& completed_cells)
|
Opm::ScheduleGrid::ScheduleGrid(Opm::CompletedCells& completed_cells)
|
||||||
@ -34,45 +42,58 @@ Opm::ScheduleGrid::ScheduleGrid(Opm::CompletedCells& completed_cells)
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
double try_get_value(const Opm::FieldPropsManager& fp, const std::string& kw, std::size_t active_index) {
|
double try_get_value(const Opm::FieldPropsManager& fp,
|
||||||
if (fp.has_double(kw))
|
const std::string& kw,
|
||||||
return fp.try_get<double>(kw)->at(active_index);
|
const std::size_t active_index)
|
||||||
else
|
{
|
||||||
|
if (! fp.has_double(kw)) {
|
||||||
throw std::logic_error(fmt::format("FieldPropsManager is missing keyword '{}'", kw));
|
throw std::logic_error(fmt::format("FieldPropsManager is missing keyword '{}'", kw));
|
||||||
}
|
|
||||||
|
|
||||||
double try_get_ntg_value(const Opm::FieldPropsManager& fp, const std::string& kw, std::size_t active_index){
|
|
||||||
if (fp.has_double(kw))
|
|
||||||
return fp.try_get<double>(kw)->at(active_index);
|
|
||||||
else
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Opm::CompletedCells::Cell& Opm::ScheduleGrid::get_cell(std::size_t i, std::size_t j, std::size_t k) const {
|
|
||||||
if (this->grid) {
|
|
||||||
auto [valid, cell] = this->cells.try_get(i,j,k);
|
|
||||||
if (!valid) {
|
|
||||||
cell.depth = this->grid->getCellDepth(i,j,k);
|
|
||||||
cell.dimensions = this->grid->getCellDimensions(i,j,k);
|
|
||||||
if (this->grid->cellActive(i,j,k)){
|
|
||||||
CompletedCells::Cell::Props props;
|
|
||||||
|
|
||||||
props.active_index = this->grid->getActiveIndex(i,j,k);
|
|
||||||
props.permx = try_get_value(*this->fp, "PERMX", props.active_index);
|
|
||||||
props.permy = try_get_value(*this->fp, "PERMY", props.active_index);
|
|
||||||
props.permz = try_get_value(*this->fp, "PERMZ", props.active_index);
|
|
||||||
props.satnum = this->fp->get_int("SATNUM").at(props.active_index);
|
|
||||||
props.pvtnum = this->fp->get_int("PVTNUM").at(props.active_index);
|
|
||||||
props.ntg = try_get_ntg_value(*this->fp, "NTG", props.active_index);
|
|
||||||
cell.props = props;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cell;
|
|
||||||
} else
|
return fp.try_get<double>(kw)->at(active_index);
|
||||||
return this->cells.get(i,j,k);
|
}
|
||||||
|
|
||||||
|
double try_get_ntg_value(const Opm::FieldPropsManager& fp,
|
||||||
|
const std::string& kw,
|
||||||
|
const std::size_t active_index)
|
||||||
|
{
|
||||||
|
return fp.has_double(kw)
|
||||||
|
? fp.try_get<double>(kw)->at(active_index)
|
||||||
|
: 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Opm::EclipseGrid* Opm::ScheduleGrid::get_grid() const {
|
const Opm::CompletedCells::Cell&
|
||||||
return this->grid;
|
Opm::ScheduleGrid::get_cell(std::size_t i, std::size_t j, std::size_t k) const
|
||||||
|
{
|
||||||
|
if (this->grid == nullptr) {
|
||||||
|
return this->cells.get(i, j, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [valid, cellRef] = this->cells.try_get(i, j, k);
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
cellRef.depth = this->grid->getCellDepth(i, j, k);
|
||||||
|
cellRef.dimensions = this->grid->getCellDimensions(i, j, k);
|
||||||
|
|
||||||
|
if (this->grid->cellActive(i, j, k)) {
|
||||||
|
auto& props = cellRef.props.emplace(CompletedCells::Cell::Props{});
|
||||||
|
|
||||||
|
props.active_index = this->grid->getActiveIndex(i, j, k);
|
||||||
|
props.permx = try_get_value(*this->fp, "PERMX", props.active_index);
|
||||||
|
props.permy = try_get_value(*this->fp, "PERMY", props.active_index);
|
||||||
|
props.permz = try_get_value(*this->fp, "PERMZ", props.active_index);
|
||||||
|
props.poro = try_get_value(*this->fp, "PORO", props.active_index);
|
||||||
|
props.satnum = this->fp->get_int("SATNUM").at(props.active_index);
|
||||||
|
props.pvtnum = this->fp->get_int("PVTNUM").at(props.active_index);
|
||||||
|
props.ntg = try_get_ntg_value(*this->fp, "NTG", props.active_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cellRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Opm::EclipseGrid* Opm::ScheduleGrid::get_grid() const
|
||||||
|
{
|
||||||
|
return this->grid;
|
||||||
}
|
}
|
||||||
|
@ -17,125 +17,164 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
#include <cassert>
|
|
||||||
#include <exception>
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <opm/io/eclipse/rst/connection.hpp>
|
#include <opm/io/eclipse/rst/connection.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
|
||||||
|
|
||||||
namespace Opm {
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
Connection::Connection(int i, int j , int k ,
|
#include <cstddef>
|
||||||
std::size_t global_index,
|
#include <exception>
|
||||||
int compnum,
|
#include <sstream>
|
||||||
double depth,
|
#include <stdexcept>
|
||||||
State stateArg ,
|
#include <string>
|
||||||
double CF,
|
#include <string_view>
|
||||||
double Kh,
|
#include <utility>
|
||||||
double rw,
|
#include <vector>
|
||||||
double r0,
|
|
||||||
double re,
|
|
||||||
double connection_length,
|
|
||||||
double skin_factor,
|
|
||||||
double d_factor,
|
|
||||||
double Ke,
|
|
||||||
const int satTableId,
|
|
||||||
const Direction directionArg,
|
|
||||||
const CTFKind ctf_kind,
|
|
||||||
const std::size_t sort_value,
|
|
||||||
const bool defaultSatTabId)
|
|
||||||
: direction(directionArg),
|
|
||||||
center_depth(depth),
|
|
||||||
open_state(stateArg),
|
|
||||||
sat_tableId(satTableId),
|
|
||||||
m_complnum( compnum ),
|
|
||||||
m_CF(CF),
|
|
||||||
m_Kh(Kh),
|
|
||||||
m_rw(rw),
|
|
||||||
m_r0(r0),
|
|
||||||
m_re(re),
|
|
||||||
m_connection_length(connection_length),
|
|
||||||
m_skin_factor(skin_factor),
|
|
||||||
m_d_factor(d_factor),
|
|
||||||
m_Ke(Ke),
|
|
||||||
ijk({i,j,k}),
|
|
||||||
m_ctfkind(ctf_kind),
|
|
||||||
m_global_index(global_index),
|
|
||||||
m_sort_value(sort_value),
|
|
||||||
m_defaultSatTabId(defaultSatTabId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr bool defaultSatTabId = true;
|
constexpr bool restartDefaultSatTabId = true;
|
||||||
|
|
||||||
|
Opm::Connection::CTFProperties
|
||||||
|
collectCTFProps(const Opm::RestartIO::RstConnection& rst_conn)
|
||||||
|
{
|
||||||
|
auto props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
props.CF = rst_conn.cf;
|
||||||
|
props.Kh = rst_conn.kh;
|
||||||
|
props.Ke = 0.0;
|
||||||
|
props.rw = rst_conn.diameter / 2;
|
||||||
|
props.r0 = rst_conn.r0;
|
||||||
|
props.re = 0.0;
|
||||||
|
props.connection_length = rst_conn.length;
|
||||||
|
props.skin_factor = rst_conn.skin_factor;
|
||||||
|
props.d_factor = 0.0;
|
||||||
|
props.static_dfac_corr_coeff = rst_conn.static_dfac_corr_coeff;
|
||||||
|
props.peaceman_denom = rst_conn.denom;
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection(const RestartIO::RstConnection& rst_connection, const ScheduleGrid& grid, const FieldPropsManager& fp) :
|
namespace Opm
|
||||||
direction(rst_connection.dir),
|
{
|
||||||
center_depth(rst_connection.depth),
|
|
||||||
open_state(rst_connection.state),
|
|
||||||
sat_tableId(rst_connection.drain_sat_table),
|
|
||||||
m_complnum(rst_connection.completion),
|
|
||||||
m_CF(rst_connection.cf),
|
|
||||||
m_Kh(rst_connection.kh),
|
|
||||||
m_rw(rst_connection.diameter / 2),
|
|
||||||
m_r0(rst_connection.r0),
|
|
||||||
m_re(0.0),
|
|
||||||
m_connection_length(0.0),
|
|
||||||
m_skin_factor(rst_connection.skin_factor),
|
|
||||||
m_d_factor(0.0),
|
|
||||||
m_Ke(0.0),
|
|
||||||
ijk(rst_connection.ijk),
|
|
||||||
m_ctfkind(rst_connection.cf_kind),
|
|
||||||
m_global_index(grid.get_cell(this->ijk[0], this->ijk[1], this->ijk[2]).global_index),
|
|
||||||
m_sort_value(rst_connection.rst_index),
|
|
||||||
m_defaultSatTabId(defaultSatTabId),
|
|
||||||
segment_number(rst_connection.segment)
|
|
||||||
{
|
|
||||||
if (this->m_defaultSatTabId) {
|
|
||||||
const auto& satnum = fp.get_int("SATNUM");
|
|
||||||
auto active_index = grid.get_cell(this->ijk[0], this->ijk[1], this->ijk[2]).active_index();
|
|
||||||
this->sat_tableId = satnum[active_index];
|
|
||||||
}
|
|
||||||
if (this->segment_number > 0)
|
|
||||||
this->m_perf_range = std::make_pair(rst_connection.segdist_start, rst_connection.segdist_end);
|
|
||||||
|
|
||||||
//TODO recompute re and perf_length from the grid
|
Connection::CTFProperties
|
||||||
|
Connection::CTFProperties::serializationTestObject()
|
||||||
|
{
|
||||||
|
auto props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
props.CF = 1.0;
|
||||||
|
props.Kh = 2.0;
|
||||||
|
props.Ke = 3.0;
|
||||||
|
props.rw = 4.0;
|
||||||
|
props.r0 = 5.0;
|
||||||
|
props.re = 6.0;
|
||||||
|
props.connection_length = 7.0;
|
||||||
|
props.skin_factor = 8.0;
|
||||||
|
props.d_factor = 9.0;
|
||||||
|
props.static_dfac_corr_coeff = 10.0;
|
||||||
|
props.peaceman_denom = 11.0;
|
||||||
|
|
||||||
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection()
|
bool Connection::CTFProperties::operator==(const CTFProperties& that) const
|
||||||
: Connection(0, 0, 0, 0, 0, 0.0, State::SHUT, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
{
|
||||||
0, Direction::X, CTFKind::DeckValue, 0, false)
|
return (this->CF == that.CF)
|
||||||
|
&& (this->Kh == that.Kh)
|
||||||
|
&& (this->Ke == that.Ke)
|
||||||
|
&& (this->rw == that.rw)
|
||||||
|
&& (this->r0 == that.r0)
|
||||||
|
&& (this->re == that.re)
|
||||||
|
&& (this->connection_length == that.connection_length)
|
||||||
|
&& (this->skin_factor == that.skin_factor)
|
||||||
|
&& (this->d_factor == that.d_factor)
|
||||||
|
&& (this->static_dfac_corr_coeff == that.static_dfac_corr_coeff)
|
||||||
|
&& (this->peaceman_denom == that.peaceman_denom)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
Connection::Connection(const int i, const int j, const int k,
|
||||||
|
const std::size_t global_index,
|
||||||
|
const int complnum,
|
||||||
|
const State stateArg,
|
||||||
|
const Direction directionArg,
|
||||||
|
const CTFKind ctf_kind,
|
||||||
|
const int satTableId,
|
||||||
|
const double depth,
|
||||||
|
const CTFProperties& ctf_props,
|
||||||
|
const std::size_t sort_value,
|
||||||
|
const bool defaultSatTabId)
|
||||||
|
: direction (directionArg)
|
||||||
|
, center_depth (depth)
|
||||||
|
, open_state (stateArg)
|
||||||
|
, sat_tableId (satTableId)
|
||||||
|
, m_complnum (complnum)
|
||||||
|
, ctf_properties_ { ctf_props }
|
||||||
|
, ijk { i, j, k }
|
||||||
|
, m_ctfkind (ctf_kind)
|
||||||
|
, m_global_index (global_index)
|
||||||
|
, m_sort_value (sort_value)
|
||||||
|
, m_defaultSatTabId(defaultSatTabId)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Connection::Connection(const RestartIO::RstConnection& rst_connection,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const FieldPropsManager& fp)
|
||||||
|
: direction (rst_connection.dir)
|
||||||
|
, center_depth (rst_connection.depth)
|
||||||
|
, open_state (rst_connection.state)
|
||||||
|
, sat_tableId (rst_connection.drain_sat_table)
|
||||||
|
, m_complnum (rst_connection.completion)
|
||||||
|
, ctf_properties_ (collectCTFProps(rst_connection))
|
||||||
|
, ijk (rst_connection.ijk)
|
||||||
|
, m_ctfkind (rst_connection.cf_kind)
|
||||||
|
, m_global_index (grid.get_cell(this->ijk[0], this->ijk[1], this->ijk[2]).global_index)
|
||||||
|
, m_sort_value (rst_connection.rst_index)
|
||||||
|
, m_defaultSatTabId(restartDefaultSatTabId)
|
||||||
|
, segment_number (rst_connection.segment)
|
||||||
|
{
|
||||||
|
if (this->m_defaultSatTabId) {
|
||||||
|
const auto active_index = grid
|
||||||
|
.get_cell(this->ijk[0], this->ijk[1], this->ijk[2])
|
||||||
|
.active_index();
|
||||||
|
|
||||||
|
this->sat_tableId = fp.get_int("SATNUM")[active_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->segment_number > 0) {
|
||||||
|
this->m_perf_range = std::make_pair(rst_connection.segdist_start,
|
||||||
|
rst_connection.segdist_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: recompute re from the grid
|
||||||
|
}
|
||||||
|
|
||||||
Connection Connection::serializationTestObject()
|
Connection Connection::serializationTestObject()
|
||||||
{
|
{
|
||||||
Connection result;
|
Connection result;
|
||||||
|
|
||||||
result.direction = Direction::Y;
|
result.direction = Direction::Y;
|
||||||
result.center_depth = 1.0;
|
result.center_depth = 1.0;
|
||||||
result.open_state = State::OPEN;
|
result.open_state = State::OPEN;
|
||||||
result.sat_tableId = 2;
|
result.sat_tableId = 2;
|
||||||
result.m_complnum = 3;
|
result.m_complnum = 3;
|
||||||
result.m_CF = 4.0;
|
|
||||||
result.m_Kh = 5.0;
|
result.ctf_properties_ = CTFProperties::serializationTestObject();
|
||||||
result.m_rw = 6.0;
|
|
||||||
result.m_r0 = 7.0;
|
|
||||||
result.m_re = 7.1;
|
|
||||||
result.m_connection_length = 7.2;
|
|
||||||
result.m_skin_factor = 8.0;
|
|
||||||
result.m_d_factor = 8.5;
|
|
||||||
result.m_Ke = 8.9;
|
|
||||||
result.ijk = {9, 10, 11};
|
result.ijk = {9, 10, 11};
|
||||||
result.m_ctfkind = CTFKind::Defaulted;
|
result.m_ctfkind = CTFKind::Defaulted;
|
||||||
result.m_global_index = 12;
|
result.m_global_index = 12;
|
||||||
@ -144,144 +183,181 @@ Connection::Connection(const RestartIO::RstConnection& rst_connection, const Sch
|
|||||||
result.m_sort_value = 14;
|
result.m_sort_value = 14;
|
||||||
result.m_defaultSatTabId = true;
|
result.m_defaultSatTabId = true;
|
||||||
result.segment_number = 16;
|
result.segment_number = 16;
|
||||||
|
result.m_wpimult = 0.123;
|
||||||
result.m_subject_to_welpi = true;
|
result.m_subject_to_welpi = true;
|
||||||
result.m_filter_cake = FilterCake::serializationTestObject();
|
result.m_filter_cake = FilterCake::serializationTestObject();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::sameCoordinate(const int i, const int j, const int k) const {
|
bool Connection::sameCoordinate(const int i, const int j, const int k) const
|
||||||
if ((ijk[0] == i) && (ijk[1] == j) && (ijk[2] == k)) {
|
{
|
||||||
return true;
|
return this->ijk == std::array { i, j, k };
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::getI() const {
|
int Connection::getI() const
|
||||||
|
{
|
||||||
return ijk[0];
|
return ijk[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::getJ() const {
|
int Connection::getJ() const
|
||||||
|
{
|
||||||
return ijk[1];
|
return ijk[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::getK() const {
|
int Connection::getK() const
|
||||||
|
{
|
||||||
return ijk[2];
|
return ijk[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t Connection::global_index() const {
|
std::size_t Connection::global_index() const
|
||||||
|
{
|
||||||
return this->m_global_index;
|
return this->m_global_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::attachedToSegment() const {
|
bool Connection::attachedToSegment() const
|
||||||
return (segment_number > 0);
|
{
|
||||||
|
return this->segment_number > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t Connection::sort_value() const {
|
std::size_t Connection::sort_value() const
|
||||||
|
{
|
||||||
return m_sort_value;
|
return m_sort_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool& Connection::getDefaultSatTabId() const {
|
bool Connection::getDefaultSatTabId() const
|
||||||
|
{
|
||||||
return m_defaultSatTabId;
|
return m_defaultSatTabId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Direction Connection::dir() const {
|
Connection::Direction Connection::dir() const
|
||||||
|
{
|
||||||
return this->direction;
|
return this->direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<std::pair<double, double>>& Connection::perf_range() const {
|
const std::optional<std::pair<double, double>>&
|
||||||
|
Connection::perf_range() const
|
||||||
|
{
|
||||||
return this->m_perf_range;
|
return this->m_perf_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setDefaultSatTabId(bool id) {
|
void Connection::setDefaultSatTabId(bool id)
|
||||||
|
{
|
||||||
m_defaultSatTabId = id;
|
m_defaultSatTabId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::depth() const {
|
double Connection::depth() const
|
||||||
|
{
|
||||||
return this->center_depth;
|
return this->center_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::State Connection::state() const {
|
Connection::State Connection::state() const
|
||||||
|
{
|
||||||
return this->open_state;
|
return this->open_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::satTableId() const {
|
int Connection::satTableId() const
|
||||||
|
{
|
||||||
return this->sat_tableId;
|
return this->sat_tableId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::complnum() const {
|
int Connection::complnum() const
|
||||||
|
{
|
||||||
return this->m_complnum;
|
return this->m_complnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setComplnum(int complnum) {
|
void Connection::setComplnum(int complnum)
|
||||||
|
{
|
||||||
this->m_complnum = complnum;
|
this->m_complnum = complnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setSkinFactor(double skin_factor) {
|
void Connection::setSkinFactor(double skin_factor)
|
||||||
this->m_skin_factor = skin_factor;
|
{
|
||||||
|
auto& ctf_p = this->ctf_properties_;
|
||||||
|
|
||||||
|
const auto peaceman_denom = ctf_p.peaceman_denom
|
||||||
|
- ctf_p.skin_factor + skin_factor;
|
||||||
|
|
||||||
|
ctf_p.skin_factor = skin_factor;
|
||||||
|
ctf_p.CF *= ctf_p.peaceman_denom / peaceman_denom;
|
||||||
|
ctf_p.peaceman_denom = peaceman_denom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setDFactor(double d_factor) {
|
void Connection::setDFactor(double d_factor)
|
||||||
this->m_d_factor = d_factor;
|
{
|
||||||
|
this->ctf_properties_.d_factor = d_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setKe(double Ke) {
|
void Connection::setKe(double Ke)
|
||||||
this->m_Ke = Ke;
|
{
|
||||||
|
this->ctf_properties_.Ke = Ke;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setCF(double CF) {
|
void Connection::setCF(double CF)
|
||||||
this->m_CF = CF;
|
{
|
||||||
|
this->ctf_properties_.CF = CF;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::CF() const {
|
double Connection::wpimult() const
|
||||||
return this->m_CF;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
double Connection::wpimult() const {
|
|
||||||
return this->m_wpimult;
|
return this->m_wpimult;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::Kh() const {
|
double Connection::CF() const
|
||||||
return this->m_Kh;
|
{
|
||||||
|
return this->ctf_properties_.CF;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::rw() const {
|
double Connection::Kh() const
|
||||||
return this->m_rw;
|
{
|
||||||
|
return this->ctf_properties_.Kh;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::r0() const {
|
double Connection::rw() const
|
||||||
return this->m_r0;
|
{
|
||||||
|
return this->ctf_properties_.rw;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::re() const {
|
double Connection::r0() const
|
||||||
return this->m_re;
|
{
|
||||||
|
return this->ctf_properties_.r0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::connectionLength() const {
|
double Connection::re() const
|
||||||
return this->m_connection_length;
|
{
|
||||||
|
return this->ctf_properties_.re;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::skinFactor() const {
|
double Connection::connectionLength() const
|
||||||
return this->m_skin_factor;
|
{
|
||||||
|
return this->ctf_properties_.connection_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::dFactor() const {
|
double Connection::skinFactor() const
|
||||||
return this->m_d_factor;
|
{
|
||||||
|
return this->ctf_properties_.skin_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::Ke() const {
|
double Connection::dFactor() const
|
||||||
return this->m_Ke;
|
{
|
||||||
|
return this->ctf_properties_.d_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setState(State state) {
|
double Connection::Ke() const
|
||||||
|
{
|
||||||
|
return this->ctf_properties_.Ke;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::setState(State state)
|
||||||
|
{
|
||||||
this->open_state = state;
|
this->open_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::updateSegment(int segment_number_arg,
|
void Connection::updateSegment(const int segment_number_arg,
|
||||||
double center_depth_arg,
|
const double center_depth_arg,
|
||||||
std::size_t compseg_insert_index,
|
const std::size_t compseg_insert_index,
|
||||||
const std::optional<std::pair<double, double>>& perf_range) {
|
const std::optional<std::pair<double, double>>& perf_range)
|
||||||
|
{
|
||||||
this->segment_number = segment_number_arg;
|
this->segment_number = segment_number_arg;
|
||||||
this->center_depth = center_depth_arg;
|
this->center_depth = center_depth_arg;
|
||||||
this->m_sort_value = compseg_insert_index;
|
this->m_sort_value = compseg_insert_index;
|
||||||
@ -289,124 +365,142 @@ const std::optional<std::pair<double, double>>& Connection::perf_range() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Connection::updateSegmentRST(int segment_number_arg,
|
void Connection::updateSegmentRST(int segment_number_arg,
|
||||||
double center_depth_arg) {
|
double center_depth_arg)
|
||||||
|
{
|
||||||
this->segment_number = segment_number_arg;
|
this->segment_number = segment_number_arg;
|
||||||
this->center_depth = center_depth_arg;
|
this->center_depth = center_depth_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::segment() const {
|
int Connection::segment() const
|
||||||
|
{
|
||||||
return this->segment_number;
|
return this->segment_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::scaleWellPi(double wellPi) {
|
void Connection::scaleWellPi(double wellPi)
|
||||||
|
{
|
||||||
this->m_wpimult *= wellPi;
|
this->m_wpimult *= wellPi;
|
||||||
this->m_CF *= wellPi;
|
this->ctf_properties_.CF *= wellPi;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::prepareWellPIScaling() {
|
bool Connection::prepareWellPIScaling()
|
||||||
|
{
|
||||||
const auto update = !this->m_subject_to_welpi;
|
const auto update = !this->m_subject_to_welpi;
|
||||||
|
|
||||||
this->m_subject_to_welpi = true;
|
this->m_subject_to_welpi = true;
|
||||||
|
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Connection::applyWellPIScaling(const double scaleFactor) {
|
bool Connection::applyWellPIScaling(const double scaleFactor)
|
||||||
if (! this->m_subject_to_welpi)
|
{
|
||||||
|
if (! this->m_subject_to_welpi) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this->scaleWellPi(scaleFactor);
|
this->scaleWellPi(scaleFactor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Connection::str() const {
|
void Connection::setStaticDFacCorrCoeff(const double c)
|
||||||
|
{
|
||||||
|
this->ctf_properties_.static_dfac_corr_coeff = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Connection::str() const
|
||||||
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "ijk: " << this->ijk[0] << "," << this->ijk[1] << "," << this->ijk[2] << std::endl;
|
|
||||||
ss << "COMPLNUM " << this->m_complnum << std::endl;
|
ss << "ijk: " << this->ijk[0] << ',' << this->ijk[1] << ',' << this->ijk[2] << '\n'
|
||||||
ss << "CF " << this->m_CF << std::endl;
|
<< "COMPLNUM " << this->m_complnum << '\n'
|
||||||
ss << "RW " << this->m_rw << std::endl;
|
<< "CF " << this->CF() << '\n'
|
||||||
ss << "R0 " << this->m_r0 << std::endl;
|
<< "RW " << this->rw() << '\n'
|
||||||
ss << "Re " << this->m_re << std::endl;
|
<< "R0 " << this->r0() << '\n'
|
||||||
ss << "connection length " << this->m_connection_length << std::endl;
|
<< "Re " << this->re() << '\n'
|
||||||
ss << "skinf " << this->m_skin_factor << std::endl;
|
<< "connection length " << this->connectionLength() << '\n'
|
||||||
ss << "dfactor " << this->m_d_factor << std::endl;
|
<< "skinf " << this->skinFactor() << '\n'
|
||||||
ss << "Ke " << this->m_Ke << std::endl;
|
<< "dfactor " << this->dFactor() << '\n'
|
||||||
ss << "kh " << this->m_Kh << std::endl;
|
<< "Ke " << this->Ke() << '\n'
|
||||||
ss << "sat_tableId " << this->sat_tableId << std::endl;
|
<< "kh " << this->Kh() << '\n'
|
||||||
ss << "open_state " << Connection::State2String(this->open_state) << std::endl;
|
<< "sat_tableId " << this->sat_tableId << '\n'
|
||||||
ss << "direction " << Connection::Direction2String(this->direction) << std::endl;
|
<< "open_state " << Connection::State2String(this->open_state) << '\n'
|
||||||
ss << "CTF Source " << Connection::CTFKindToString(this->m_ctfkind) << '\n';
|
<< "direction " << Connection::Direction2String(this->direction) << '\n'
|
||||||
ss << "segment_nr " << this->segment_number << std::endl;
|
<< "CTF Source " << Connection::CTFKindToString(this->m_ctfkind) << '\n'
|
||||||
ss << "center_depth " << this->center_depth << std::endl;
|
<< "segment_nr " << this->segment_number << '\n'
|
||||||
ss << "sort_value" << this->m_sort_value<< std::endl;
|
<< "center_depth " << this->center_depth << '\n'
|
||||||
|
<< "sort_value" << this->m_sort_value<< '\n';
|
||||||
|
|
||||||
if (this->m_injmult.has_value()) {
|
if (this->m_injmult.has_value()) {
|
||||||
ss << "INJMULT " << InjMult::InjMultToString(this->m_injmult.value()) << std::endl;
|
ss << "INJMULT " << InjMult::InjMultToString(this->m_injmult.value()) << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->m_filter_cake.has_value()) {
|
if (this->m_filter_cake.has_value()) {
|
||||||
ss << "FilterCake " << FilterCake::filterCakeToString(this->m_filter_cake.value()) << std::endl;
|
ss << "FilterCake " << FilterCake::filterCakeToString(this->m_filter_cake.value()) << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
|
||||||
|
|
||||||
bool Connection::operator==( const Connection& rhs ) const {
|
|
||||||
return this->ijk == rhs.ijk
|
|
||||||
&& this->m_global_index == rhs.m_global_index
|
|
||||||
&& this->m_complnum == rhs.m_complnum
|
|
||||||
&& this->m_CF == rhs.m_CF
|
|
||||||
&& this->m_rw == rhs.m_rw
|
|
||||||
&& this->m_r0 == rhs.m_r0
|
|
||||||
&& this->m_re == rhs.m_re
|
|
||||||
&& this->m_connection_length == rhs.m_connection_length
|
|
||||||
&& this->m_skin_factor == rhs.m_skin_factor
|
|
||||||
&& this->m_d_factor == rhs.m_d_factor
|
|
||||||
&& this->m_Ke == rhs.m_Ke
|
|
||||||
&& this->m_injmult == rhs.m_injmult
|
|
||||||
&& this->m_Kh == rhs.m_Kh
|
|
||||||
&& this->sat_tableId == rhs.sat_tableId
|
|
||||||
&& this->open_state == rhs.open_state
|
|
||||||
&& this->direction == rhs.direction
|
|
||||||
&& this->segment_number == rhs.segment_number
|
|
||||||
&& this->center_depth == rhs.center_depth
|
|
||||||
&& this->m_sort_value == rhs.m_sort_value
|
|
||||||
&& this->m_subject_to_welpi == rhs.m_subject_to_welpi
|
|
||||||
&& this->m_filter_cake == rhs.m_filter_cake;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::operator!=( const Connection& rhs ) const {
|
bool Connection::operator==(const Connection& that) const
|
||||||
return !( *this == rhs );
|
{
|
||||||
|
return (this->direction == that.direction)
|
||||||
|
&& (this->open_state == that.open_state)
|
||||||
|
&& (this->sat_tableId == that.sat_tableId)
|
||||||
|
&& (this->m_complnum == that.m_complnum)
|
||||||
|
&& (this->m_ctfkind == that.m_ctfkind)
|
||||||
|
&& (this->m_global_index == that.m_global_index)
|
||||||
|
&& (this->m_sort_value == that.m_sort_value)
|
||||||
|
&& (this->m_defaultSatTabId == that.m_defaultSatTabId)
|
||||||
|
&& (this->segment_number == that.segment_number)
|
||||||
|
&& (this->m_subject_to_welpi == that.m_subject_to_welpi)
|
||||||
|
&& (this->ijk == that.ijk)
|
||||||
|
&& (this->m_injmult == that.m_injmult)
|
||||||
|
&& (this->center_depth == that.center_depth)
|
||||||
|
&& (this->m_perf_range == that.m_perf_range)
|
||||||
|
&& (this->ctf_properties_ == that.ctf_properties_)
|
||||||
|
&& (this->m_filter_cake == that.m_filter_cake)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string Connection::State2String(State enumValue)
|
||||||
const std::string Connection::State2String( State enumValue ) {
|
{
|
||||||
switch( enumValue ) {
|
switch (enumValue) {
|
||||||
case State::OPEN:
|
case State::OPEN:
|
||||||
return "OPEN";
|
return "OPEN";
|
||||||
|
|
||||||
case State::AUTO:
|
case State::AUTO:
|
||||||
return "AUTO";
|
return "AUTO";
|
||||||
|
|
||||||
case State::SHUT:
|
case State::SHUT:
|
||||||
return "SHUT";
|
return "SHUT";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::invalid_argument("Unhandled enum value");
|
throw std::invalid_argument {
|
||||||
|
"Unhandled Connection::State value " +
|
||||||
|
std::to_string(static_cast<int>(enumValue))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connection::State
|
||||||
Connection::State Connection::StateFromString( const std::string& stringValue ) {
|
Connection::StateFromString(std::string_view stringValue)
|
||||||
|
{
|
||||||
if (stringValue == "OPEN")
|
if (stringValue == "OPEN")
|
||||||
return State::OPEN;
|
return State::OPEN;
|
||||||
else if (stringValue == "SHUT")
|
|
||||||
return State::SHUT;
|
|
||||||
else if (stringValue == "STOP")
|
|
||||||
return State::SHUT;
|
|
||||||
else if (stringValue == "AUTO")
|
|
||||||
return State::AUTO;
|
|
||||||
else
|
|
||||||
throw std::invalid_argument("Unknown enum state string: " + stringValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (stringValue == "SHUT")
|
||||||
|
return State::SHUT;
|
||||||
|
|
||||||
|
if (stringValue == "STOP")
|
||||||
|
return State::SHUT;
|
||||||
|
|
||||||
|
if (stringValue == "AUTO")
|
||||||
|
return State::AUTO;
|
||||||
|
|
||||||
|
throw std::invalid_argument {
|
||||||
|
"Unknown Connection::State string: " + std::string { stringValue }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Connection::Direction2String(const Direction enumValue)
|
std::string Connection::Direction2String(const Direction enumValue)
|
||||||
@ -434,8 +528,7 @@ std::string Connection::Direction2String(const Direction enumValue)
|
|||||||
return stringValue;
|
return stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connection::Direction Connection::DirectionFromString(std::string_view s)
|
||||||
Connection::Direction Connection::DirectionFromString(const std::string& s )
|
|
||||||
{
|
{
|
||||||
Direction direction;
|
Direction direction;
|
||||||
|
|
||||||
@ -443,47 +536,61 @@ Connection::Direction Connection::DirectionFromString(const std::string& s )
|
|||||||
else if ((s == "Y") || (s == "y")) { direction = Direction::Y; }
|
else if ((s == "Y") || (s == "y")) { direction = Direction::Y; }
|
||||||
else if ((s == "Z") || (s == "z")) { direction = Direction::Z; }
|
else if ((s == "Z") || (s == "z")) { direction = Direction::Z; }
|
||||||
else {
|
else {
|
||||||
std::string msg = "Unsupported completion direction " + s;
|
throw std::invalid_argument {
|
||||||
throw std::invalid_argument(msg);
|
"Unsupported completion direction "
|
||||||
|
+ std::string { s }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string Connection::Order2String( Order enumValue ) {
|
std::string Connection::Order2String(Order enumValue)
|
||||||
switch( enumValue ) {
|
{
|
||||||
|
switch (enumValue) {
|
||||||
case Order::DEPTH:
|
case Order::DEPTH:
|
||||||
return "DEPTH";
|
return "DEPTH";
|
||||||
|
|
||||||
case Order::INPUT:
|
case Order::INPUT:
|
||||||
return "INPUT";
|
return "INPUT";
|
||||||
|
|
||||||
case Order::TRACK:
|
case Order::TRACK:
|
||||||
return "TRACK";
|
return "TRACK";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::invalid_argument("Unhandled enum value");
|
throw std::invalid_argument {
|
||||||
|
"Unhandled Connection::Order value " +
|
||||||
|
std::to_string(static_cast<int>(enumValue))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connection::Order Connection::OrderFromString(std::string_view stringValue)
|
||||||
Connection::Order Connection::OrderFromString(const std::string& stringValue ) {
|
{
|
||||||
if (stringValue == "DEPTH")
|
if (stringValue == "DEPTH")
|
||||||
return Order::DEPTH;
|
return Order::DEPTH;
|
||||||
else if (stringValue == "INPUT")
|
|
||||||
|
if (stringValue == "INPUT")
|
||||||
return Order::INPUT;
|
return Order::INPUT;
|
||||||
else if (stringValue == "TRACK")
|
|
||||||
|
if (stringValue == "TRACK")
|
||||||
return Order::TRACK;
|
return Order::TRACK;
|
||||||
else
|
|
||||||
throw std::invalid_argument("Unknown enum state string: " + stringValue );
|
throw std::invalid_argument {
|
||||||
|
"Unknown Connection::Order string: " + std::string { stringValue }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Connection::CTFKindToString(const CTFKind ctf_kind)
|
std::string Connection::CTFKindToString(const CTFKind ctf_kind)
|
||||||
{
|
{
|
||||||
switch (ctf_kind) {
|
switch (ctf_kind) {
|
||||||
case CTFKind::DeckValue:
|
case CTFKind::DeckValue:
|
||||||
return "DeckValue";
|
return "DeckValue";
|
||||||
|
|
||||||
case CTFKind::Defaulted:
|
case CTFKind::Defaulted:
|
||||||
return "Defaulted";
|
return "Defaulted";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::invalid_argument {
|
throw std::invalid_argument {
|
||||||
@ -492,58 +599,62 @@ std::string Connection::CTFKindToString(const CTFKind ctf_kind)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::CTFKind Connection::kind() const {
|
Connection::CTFKind Connection::kind() const
|
||||||
|
{
|
||||||
return m_ctfkind;
|
return m_ctfkind;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InjMult& Connection::injmult() const {
|
const InjMult& Connection::injmult() const
|
||||||
|
{
|
||||||
assert(this->activeInjMult());
|
assert(this->activeInjMult());
|
||||||
return m_injmult.value();
|
return m_injmult.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::activeInjMult() const {
|
bool Connection::activeInjMult() const
|
||||||
|
{
|
||||||
return this->m_injmult.has_value();
|
return this->m_injmult.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setInjMult(const InjMult& inj_mult) {
|
void Connection::setInjMult(const InjMult& inj_mult)
|
||||||
|
{
|
||||||
m_injmult = inj_mult;
|
m_injmult = inj_mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Connection::setFilterCake(const FilterCake& filter_cake)
|
||||||
void Connection::setFilterCake(const FilterCake& filter_cake) {
|
{
|
||||||
this->m_filter_cake = filter_cake;
|
this->m_filter_cake = filter_cake;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::filterCakeActive() const {
|
bool Connection::filterCakeActive() const
|
||||||
|
{
|
||||||
return this->m_filter_cake.has_value();
|
return this->m_filter_cake.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilterCake& Connection::getFilterCake() const {
|
const FilterCake& Connection::getFilterCake() const
|
||||||
assert(this->filterCakeActive());
|
{
|
||||||
return this->m_filter_cake.value();
|
assert(this->filterCakeActive());
|
||||||
|
return this->m_filter_cake.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Connection::getFilterCakeRadius() const
|
||||||
double Connection::getFilterCakeRadius() const {
|
{
|
||||||
if (this->getFilterCake().radius.has_value()) {
|
if (const auto& radius = this->getFilterCake().radius; radius.has_value()) {
|
||||||
return this->getFilterCake().radius.value();
|
return *radius;
|
||||||
} else {
|
}
|
||||||
return this->m_rw;
|
else {
|
||||||
|
return this->rw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Connection::getFilterCakeArea() const
|
||||||
double Connection::getFilterCakeArea() const {
|
{
|
||||||
if (this->getFilterCake().flow_area.has_value()) {
|
if (const auto& flow_area = this->getFilterCake().flow_area; flow_area.has_value()) {
|
||||||
return this->getFilterCake().flow_area.value();
|
return *flow_area;
|
||||||
} else {
|
}
|
||||||
const double radius = this->getFilterCakeRadius();
|
else {
|
||||||
const double length = this->m_connection_length;
|
constexpr double two_pi = 2 * 3.14159265358979323846264;
|
||||||
constexpr double pi = 3.14159265;
|
return two_pi * this->getFilterCakeRadius() * this->connectionLength();
|
||||||
return 2. * pi * radius * length;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace Opm
|
} // end of namespace Opm
|
||||||
|
@ -17,126 +17,180 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WDFAC.hpp>
|
||||||
|
|
||||||
#include <opm/io/eclipse/rst/well.hpp>
|
#include <opm/io/eclipse/rst/well.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/well.hpp>
|
#include <opm/output/eclipse/VectorItems/well.hpp>
|
||||||
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
|
||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/Dimension.hpp>
|
#include <opm/input/eclipse/Units/Dimension.hpp>
|
||||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
#include <opm/input/eclipse/Units/Units.hpp>
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WDFAC.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
||||||
#include <vector>
|
|
||||||
#include <cmath>
|
#include <algorithm>
|
||||||
#include <iostream>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
double dakeModelDFactor(const double rhoGS,
|
||||||
|
const double gas_visc,
|
||||||
|
const Opm::Connection::CTFProperties& ctf_props)
|
||||||
|
{
|
||||||
|
using namespace Opm::unit;
|
||||||
|
|
||||||
|
// Specific gravity of gas relative to air at standard conditions.
|
||||||
|
constexpr auto rho_air = 1.22*kilogram / cubic(meter);
|
||||||
|
const auto specific_gravity = rhoGS / rho_air;
|
||||||
|
|
||||||
|
return ctf_props.static_dfac_corr_coeff * specific_gravity / gas_visc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
|
WDFAC::Correlation WDFAC::Correlation::serializationTestObject()
|
||||||
|
{
|
||||||
|
return { 1.23, 0.456, 0.457 };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WDFAC::Correlation::operator==(const Correlation& other) const
|
||||||
|
{
|
||||||
|
return (this->coeff_a == other.coeff_a)
|
||||||
|
&& (this->exponent_b == other.exponent_b)
|
||||||
|
&& (this->exponent_c == other.exponent_c)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
WDFAC::WDFAC(const RestartIO::RstWell& rst_well)
|
||||||
|
: m_type { WDFacType::NONE }
|
||||||
|
, m_d { 0.0 }
|
||||||
|
, m_corr { rst_well.dfac_corr_coeff_a ,
|
||||||
|
rst_well.dfac_corr_exponent_b ,
|
||||||
|
rst_well.dfac_corr_exponent_c }
|
||||||
|
{
|
||||||
|
if (m_corr.coeff_a > 0.0) {
|
||||||
|
this->m_type = WDFacType::DAKEMODEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WDFAC WDFAC::serializationTestObject()
|
WDFAC WDFAC::serializationTestObject()
|
||||||
{
|
{
|
||||||
WDFAC result;
|
WDFAC result;
|
||||||
result.m_a = 1.23;
|
|
||||||
result.m_b = 0.456;
|
result.m_type = WDFacType::DAKEMODEL;
|
||||||
result.m_c = 0.457;
|
|
||||||
result.m_d = 0.458;
|
result.m_d = 0.458;
|
||||||
result.m_total_cf = 1.0;
|
result.m_total_cf = 1.0;
|
||||||
result.m_type = WDFACTYPE::NONE;
|
result.m_corr = Correlation::serializationTestObject();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WDFAC::operator==(const WDFAC& other) const {
|
void WDFAC::updateWDFAC(const DeckRecord& record)
|
||||||
return (m_a == other.m_a)
|
{
|
||||||
&& (m_b == other.m_b)
|
|
||||||
&& (m_c == other.m_c)
|
|
||||||
&& (m_d == other.m_d)
|
|
||||||
&& (m_total_cf == other.m_total_cf)
|
|
||||||
&& (m_type == other.m_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WDFAC::updateWDFAC(const DeckRecord& record) {
|
|
||||||
m_d = record.getItem<ParserKeywords::WDFAC::DFACTOR>().getSIDouble(0);
|
m_d = record.getItem<ParserKeywords::WDFAC::DFACTOR>().getSIDouble(0);
|
||||||
m_type = WDFACTYPE::DFACTOR;
|
|
||||||
|
m_type = WDFacType::DFACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WDFAC::updateWDFACCOR(const DeckRecord& record) {
|
void WDFAC::updateWDFACCOR(const DeckRecord& record)
|
||||||
m_a = record.getItem<ParserKeywords::WDFACCOR::A>().getSIDouble(0);
|
{
|
||||||
m_b = record.getItem<ParserKeywords::WDFACCOR::B>().getSIDouble(0);
|
this->m_corr.coeff_a = record.getItem<ParserKeywords::WDFACCOR::A>().getSIDouble(0);
|
||||||
m_c = record.getItem<ParserKeywords::WDFACCOR::C>().getSIDouble(0);
|
this->m_corr.exponent_b = record.getItem<ParserKeywords::WDFACCOR::B>().getSIDouble(0);
|
||||||
m_type = WDFACTYPE::DAKEMODEL;
|
this->m_corr.exponent_c = record.getItem<ParserKeywords::WDFACCOR::C>().getSIDouble(0);
|
||||||
|
|
||||||
|
m_type = WDFacType::DAKEMODEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WDFAC::updateWDFACType(const WellConnections& connections) {
|
void WDFAC::updateWDFACType(const WellConnections& connections)
|
||||||
|
{
|
||||||
const auto non_trivial_dfactor =
|
const auto non_trivial_dfactor =
|
||||||
std::any_of(connections.begin(), connections.end(),
|
std::any_of(connections.begin(), connections.end(),
|
||||||
[](const auto& conn) { return conn.dFactor() != 0.0; });
|
[](const auto& conn) { return conn.dFactor() != 0.0; });
|
||||||
|
|
||||||
// non-trivial dfactors detected use connection D factors
|
|
||||||
if (non_trivial_dfactor) {
|
if (non_trivial_dfactor) {
|
||||||
m_type = WDFACTYPE::CON_DFACTOR;
|
// Non-trivial D-factors detected. Use connection D-factors.
|
||||||
updateTotalCF(connections);
|
m_type = WDFacType::CON_DFACTOR;
|
||||||
|
this->updateTotalCF(connections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WDFAC::updateTotalCF(const WellConnections& connections) {
|
void WDFAC::updateTotalCF(const WellConnections& connections)
|
||||||
m_total_cf = std::accumulate(connections.begin(), connections.end(), 0.0,
|
{
|
||||||
[](const double tot_cf, const auto& conn) { return tot_cf + conn.CF(); });
|
this->m_total_cf = std::accumulate(connections.begin(), connections.end(), 0.0,
|
||||||
|
[](const double tot_cf, const auto& conn) { return tot_cf + conn.CF(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
double WDFAC::getDFactor(const Connection& connection, double mu, double rho, double phi) const {
|
double WDFAC::getDFactor(const double rhoGS,
|
||||||
|
const double gas_visc,
|
||||||
switch (m_type)
|
const Connection& conn) const
|
||||||
{
|
{
|
||||||
case WDFACTYPE::NONE:
|
switch (this->m_type) {
|
||||||
|
case WDFacType::NONE:
|
||||||
return 0.0;
|
return 0.0;
|
||||||
case WDFACTYPE::DFACTOR: {
|
|
||||||
if (m_total_cf < 0.0) {
|
|
||||||
throw std::invalid_argument { "Total connection factor is not set" };
|
|
||||||
}
|
|
||||||
return m_d * m_total_cf / connection.CF();
|
|
||||||
}
|
|
||||||
case WDFACTYPE::CON_DFACTOR: {
|
|
||||||
double d = connection.dFactor();
|
|
||||||
// If a negative d factor is set in COMPDAT individual connection d factors should be used directly.
|
|
||||||
if (d < 0)
|
|
||||||
return -d;
|
|
||||||
// If a positive d factor is set in COMPDAT the connection d factors is treated like a well d factor.
|
|
||||||
// and thus scaled with the connection index
|
|
||||||
if (m_total_cf < 0.0) {
|
|
||||||
throw std::invalid_argument { "Total connection factor is not set" };
|
|
||||||
}
|
|
||||||
|
|
||||||
return d * m_total_cf / connection.CF();
|
case WDFacType::DFACTOR:
|
||||||
}
|
return this->scaledWellLevelDFactor(this->m_d, conn);
|
||||||
case WDFACTYPE::DAKEMODEL:
|
|
||||||
{
|
case WDFacType::DAKEMODEL:
|
||||||
double Kh = connection.Kh();
|
return dakeModelDFactor(rhoGS, gas_visc, conn.ctfProperties());
|
||||||
double Ke = connection.Ke();
|
|
||||||
double h = Kh / Ke;
|
case WDFacType::CON_DFACTOR:
|
||||||
double rw = connection.rw();
|
return this->connectionLevelDFactor(conn);
|
||||||
const auto k_md = unit::convert::to(Ke, prefix::milli*unit::darcy);
|
|
||||||
double beta = m_a * (std::pow(k_md, m_b) * std::pow(phi, m_c));
|
|
||||||
double specific_gravity = rho / 1.225; // divide by density of air at standard conditions.
|
|
||||||
return beta * specific_gravity * Ke / (h * mu * rw );
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WDFAC::useDFactor() const {
|
bool WDFAC::useDFactor() const
|
||||||
return m_type != WDFACTYPE::NONE;
|
{
|
||||||
|
return m_type != WDFacType::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WDFAC::operator!=(const WDFAC& other) const {
|
bool WDFAC::operator==(const WDFAC& other) const
|
||||||
return !(*this == other);
|
{
|
||||||
|
return (this->m_type == other.m_type)
|
||||||
|
&& (this->m_d == other.m_d)
|
||||||
|
&& (this->m_total_cf == other.m_total_cf)
|
||||||
|
&& (this->m_corr == other.m_corr)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
double WDFAC::connectionLevelDFactor(const Connection& conn) const
|
||||||
|
{
|
||||||
|
const double d = conn.dFactor();
|
||||||
|
|
||||||
|
// Negative D-factor values in COMPDAT should be used directly as
|
||||||
|
// connection-level D-factors.
|
||||||
|
if (d < 0.0) {
|
||||||
|
return -d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Positive D-factor values in COMPDAT are treated as well-level
|
||||||
|
// values and scaled with the CTF for translation to connection
|
||||||
|
// level.
|
||||||
|
return this->scaledWellLevelDFactor(d, conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
double WDFAC::scaledWellLevelDFactor(const double dfac,
|
||||||
|
const Connection& conn) const
|
||||||
|
{
|
||||||
|
if (this->m_total_cf < 0.0) {
|
||||||
|
throw std::invalid_argument {
|
||||||
|
"Total well-level connection factor is not set"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return dfac * this->m_total_cf / conn.CF();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,12 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Well/WVFPDP.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WVFPDP.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WVFPEXP.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WVFPEXP.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/Units.hpp>
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
|
||||||
#include <opm/common/utility/OpmInputError.hpp>
|
#include <opm/common/utility/OpmInputError.hpp>
|
||||||
#include <opm/common/utility/shmatch.hpp>
|
#include <opm/common/utility/shmatch.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeywords/C.hpp>
|
||||||
#include <opm/input/eclipse/Parser/ParserKeywords/S.hpp>
|
#include <opm/input/eclipse/Parser/ParserKeywords/S.hpp>
|
||||||
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
||||||
|
|
||||||
@ -314,7 +313,7 @@ Well::Well(const RestartIO::RstWell& rst_well,
|
|||||||
injection(std::make_shared<WellInjectionProperties>(unit_system_arg, wname)),
|
injection(std::make_shared<WellInjectionProperties>(unit_system_arg, wname)),
|
||||||
wvfpdp(std::make_shared<WVFPDP>()),
|
wvfpdp(std::make_shared<WVFPDP>()),
|
||||||
wvfpexp(explicitTHPOptions(rst_well)),
|
wvfpexp(explicitTHPOptions(rst_well)),
|
||||||
wdfac(std::make_shared<WDFAC>()),
|
wdfac(std::make_shared<WDFAC>(rst_well)),
|
||||||
status(status_from_int(rst_well.well_status)),
|
status(status_from_int(rst_well.well_status)),
|
||||||
well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue),
|
well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue),
|
||||||
well_inj_mult(std::nullopt)
|
well_inj_mult(std::nullopt)
|
||||||
@ -1300,42 +1299,60 @@ bool Well::handleWELOPENConnections(const DeckRecord& record, Connection::State
|
|||||||
return this->updateConnections(std::move(new_connections), false);
|
return this->updateConnections(std::move(new_connections), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Well::handleCSKINConnections(const DeckRecord& record) {
|
bool Well::handleCSKIN(const DeckRecord& record,
|
||||||
// Lambda expression to check if record coordinates match connection coordinates
|
const KeywordLocation& location)
|
||||||
auto match = [=]( const Connection &c) -> bool {
|
{
|
||||||
if (!match_eq(c.getI(), record, "I" , -1)) return false;
|
using Kw = ParserKeywords::CSKIN;
|
||||||
if (!match_eq(c.getJ(), record, "J" , -1)) return false;
|
|
||||||
if (!match_ge(c.getK(), record, "K_UPPER", -1)) return false;
|
|
||||||
if (!match_le(c.getK(), record, "K_LOWER", -1)) return false;
|
|
||||||
|
|
||||||
return true;
|
auto need_skin_adjustment = [&record](const Connection &c) {
|
||||||
|
const auto value_shift = -1;
|
||||||
|
|
||||||
|
return match_eq(c.getI(), record, Kw::I::itemName, value_shift)
|
||||||
|
&& match_eq(c.getJ(), record, Kw::J::itemName, value_shift)
|
||||||
|
&& match_ge(c.getK(), record, Kw::K_UPPER::itemName, value_shift)
|
||||||
|
&& match_le(c.getK(), record, Kw::K_LOWER::itemName, value_shift);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate a new connection which will be updated with new connection skin factor
|
// New connection set which will be updated with new connection level
|
||||||
auto new_connections = std::make_shared<WellConnections>(this->connections->ordering(), this->headI, this->headJ);
|
// skin factors.
|
||||||
|
auto new_connections = std::make_shared<WellConnections>
|
||||||
|
(this->connections->ordering(), this->headI, this->headJ);
|
||||||
|
|
||||||
// Update skin factor
|
const auto skin_factor = record.getItem<Kw::CONNECTION_SKIN_FACTOR>().getSIDouble(0);
|
||||||
double skin_factor = record.getItem("CONNECTION_SKIN_FACTOR").get<double>(0);
|
for (const auto& connection : *this->connections) {
|
||||||
const double angle = 6.2831853071795864769252867665590057683943387987502116419498;
|
if (! need_skin_adjustment(connection)) {
|
||||||
for (auto c : *this->connections) {
|
// No CSKIN adjustment needed here. Include connection as-is
|
||||||
if (match(c)) {
|
// into new connection set.
|
||||||
// Check for potential negative new CF
|
new_connections->add(connection);
|
||||||
if ((std::log(c.r0() / std::min(c.rw(), c.r0())) + skin_factor) < 0.0) {
|
continue;
|
||||||
throw std::runtime_error("Negative connection transmissibility factor produced by CSKIN for well "
|
|
||||||
+ name());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate new connection transmissibility factor
|
|
||||||
double CF = angle * c.Kh() / (std::log(c.r0() / std::min(c.rw(), c.r0())) + skin_factor);
|
|
||||||
|
|
||||||
// Apply last known WPIMULT (defaulted to 1.0)
|
|
||||||
CF *= c.wpimult();
|
|
||||||
|
|
||||||
// Set skin factor and connection factor
|
|
||||||
c.setSkinFactor(skin_factor);
|
|
||||||
c.setCF(CF);
|
|
||||||
}
|
}
|
||||||
new_connections->add(c);
|
|
||||||
|
// If we get here, we must make the connection's skin factor be
|
||||||
|
// 'skin_factor'.
|
||||||
|
//
|
||||||
|
// First guard against this adjustment making the CTF go negative,
|
||||||
|
// typically because the 'skin_factor' value is large and negative
|
||||||
|
// itself.
|
||||||
|
if (const auto& ctf_props = connection.ctfProperties();
|
||||||
|
ctf_props.peaceman_denom + skin_factor - ctf_props.skin_factor < 0.0)
|
||||||
|
{
|
||||||
|
throw OpmInputError {
|
||||||
|
fmt::format("Negative connection transmissibility "
|
||||||
|
"factor generated by skin factor {} "
|
||||||
|
"in connection ({},{},{}) for well {}.",
|
||||||
|
skin_factor,
|
||||||
|
connection.getI() + 1,
|
||||||
|
connection.getJ() + 1,
|
||||||
|
connection.getK() + 1,
|
||||||
|
this->name()),
|
||||||
|
location
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto connection_copy = connection;
|
||||||
|
connection_copy.setSkinFactor(skin_factor);
|
||||||
|
|
||||||
|
new_connections->add(connection_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->updateConnections(std::move(new_connections), false);
|
return this->updateConnections(std::move(new_connections), false);
|
||||||
@ -1390,6 +1407,7 @@ bool Well::handleWPIMULT(const DeckRecord& record) {
|
|||||||
|
|
||||||
new_connections->add(c);
|
new_connections->add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->updateConnections(std::move(new_connections), false);
|
return this->updateConnections(std::move(new_connections), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
|
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
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
@ -16,99 +17,129 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <opm/io/eclipse/rst/header.hpp>
|
|
||||||
#include <opm/io/eclipse/rst/connection.hpp>
|
#include <opm/io/eclipse/rst/connection.hpp>
|
||||||
|
|
||||||
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
||||||
|
|
||||||
namespace Opm {
|
|
||||||
namespace RestartIO {
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T from_int(int);
|
T from_int(int);
|
||||||
|
|
||||||
template <>
|
template<> Opm::Connection::State from_int(int int_state)
|
||||||
Connection::State from_int(int int_state) {
|
{
|
||||||
if (int_state == 1)
|
return (int_state == 1)
|
||||||
return Connection::State::OPEN;
|
? Opm::Connection::State::OPEN
|
||||||
|
: Opm::Connection::State::SHUT;
|
||||||
return Connection::State::SHUT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template<> Opm::Connection::Direction from_int(int int_dir)
|
||||||
Connection::Direction from_int(int int_dir) {
|
{
|
||||||
switch (int_dir) {
|
switch (int_dir) {
|
||||||
case 1:
|
case 1: return Opm::Connection::Direction::X;
|
||||||
return Connection::Direction::X;
|
case 2: return Opm::Connection::Direction::Y;
|
||||||
case 2:
|
case 3: return Opm::Connection::Direction::Z;
|
||||||
return Connection::Direction::Y;
|
|
||||||
case 3:
|
|
||||||
return Connection::Direction::Z;
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument("Can not convert: " + std::to_string(int_dir) + " to string");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw std::invalid_argument {
|
||||||
|
"Unable to convert direction value: " +
|
||||||
|
std::to_string(int_dir) + " to Direction category"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Note: CTFKind originates in SCON and is indeed a float.
|
||||||
That the CTFKind variable comes from a float looks extremely suspicious; but
|
Opm::Connection::CTFKind from_float(float float_kind)
|
||||||
it has been double checked ...
|
{
|
||||||
*/
|
return (float_kind == 0.0f)
|
||||||
Connection::CTFKind from_float(float float_kind) {
|
? Opm::Connection::CTFKind::Defaulted
|
||||||
if (float_kind == 0)
|
: Opm::Connection::CTFKind::DeckValue;
|
||||||
return Connection::CTFKind::Defaulted;
|
|
||||||
|
|
||||||
return Connection::CTFKind::DeckValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double RstConnection::inverse_peaceman(double cf, double kh, double rw, double skin) {
|
float as_float(const double x)
|
||||||
|
{
|
||||||
|
return static_cast<float>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float staticDFactorCorrCoeff(const Opm::UnitSystem& usys,
|
||||||
|
const float coeff)
|
||||||
|
{
|
||||||
|
using M = ::Opm::UnitSystem::measure;
|
||||||
|
|
||||||
|
// Coefficient's units are [D] * [viscosity]
|
||||||
|
return as_float(usys.to_si(M::viscosity, usys.to_si(M::dfactor, coeff)));
|
||||||
|
}
|
||||||
|
|
||||||
|
double pressEquivRadius(const float denom,
|
||||||
|
const float skin,
|
||||||
|
const float rw)
|
||||||
|
{
|
||||||
|
// Recall: denom = log(r0 / rw) + skin
|
||||||
|
return rw * std::exp(denom - skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
double Opm::RestartIO::RstConnection::inverse_peaceman(double cf, double kh, double rw, double skin)
|
||||||
|
{
|
||||||
auto alpha = 3.14159265 * 2 * kh / cf - skin;
|
auto alpha = 3.14159265 * 2 * kh / cf - skin;
|
||||||
return rw * std::exp(alpha);
|
return rw * std::exp(alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
using M = ::Opm::UnitSystem::measure;
|
using M = ::Opm::UnitSystem::measure;
|
||||||
|
|
||||||
RstConnection::RstConnection(const ::Opm::UnitSystem& unit_system, std::size_t rst_index_, int nsconz, const int* icon, const float* scon, const double* xcon) :
|
Opm::RestartIO::RstConnection::RstConnection(const UnitSystem& unit_system,
|
||||||
rst_index( rst_index_),
|
const std::size_t rst_index_,
|
||||||
ijk( {icon[VI::IConn::CellI] - 1, icon[VI::IConn::CellJ] - 1, icon[VI::IConn::CellK] - 1}),
|
const int nsconz,
|
||||||
state( from_int<Connection::State>(icon[VI::IConn::ConnStat])),
|
const int* icon,
|
||||||
drain_sat_table( icon[VI::IConn::Drainage]),
|
const float* scon,
|
||||||
imb_sat_table( icon[VI::IConn::Imbibition]),
|
const double* xcon)
|
||||||
completion( icon[VI::IConn::ComplNum]),
|
: rst_index { rst_index_ }
|
||||||
dir( from_int<Connection::Direction>(icon[VI::IConn::ConnDir])),
|
// -----------------------------------------------------------------
|
||||||
segment( icon[VI::IConn::Segment]),
|
// Integer values (ICON)
|
||||||
cf_kind( from_float(1.0)),
|
, ijk { icon[VI::IConn::CellI] - 1 ,
|
||||||
skin_factor( scon[VI::SConn::SkinFactor]),
|
icon[VI::IConn::CellJ] - 1 ,
|
||||||
cf( unit_system.to_si(M::transmissibility, scon[VI::SConn::ConnTrans])),
|
icon[VI::IConn::CellK] - 1 }
|
||||||
depth( unit_system.to_si(M::length, scon[VI::SConn::Depth])),
|
, state { from_int<Connection::State>(icon[VI::IConn::ConnStat]) }
|
||||||
diameter( unit_system.to_si(M::length, scon[VI::SConn::Diameter])),
|
, drain_sat_table { icon[VI::IConn::Drainage] }
|
||||||
kh( unit_system.to_si(M::effective_Kh, scon[VI::SConn::EffectiveKH])),
|
, imb_sat_table { icon[VI::IConn::Imbibition] }
|
||||||
segdist_end( unit_system.to_si(M::length, scon[VI::SConn::SegDistEnd])),
|
, completion { icon[VI::IConn::ComplNum] }
|
||||||
segdist_start( unit_system.to_si(M::length, scon[VI::SConn::SegDistStart])),
|
, dir { from_int<Connection::Direction>(icon[VI::IConn::ConnDir]) }
|
||||||
oil_rate( unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::OilRate])),
|
, segment { icon[VI::IConn::Segment] }
|
||||||
water_rate( unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::WaterRate])),
|
// -----------------------------------------------------------------
|
||||||
gas_rate( unit_system.to_si(M::gas_surface_rate, xcon[VI::XConn::GasRate])),
|
// Float values (SCON)
|
||||||
pressure( unit_system.to_si(M::pressure, xcon[VI::XConn::Pressure])),
|
, cf_kind { from_float(1.0f) }
|
||||||
resv_rate( unit_system.to_si(M::rate, xcon[VI::XConn::ResVRate])),
|
, skin_factor { scon[VI::SConn::SkinFactor] }
|
||||||
r0( RstConnection::inverse_peaceman(this->cf, this->kh, this->diameter/2, this->skin_factor) )
|
, cf { as_float(unit_system.to_si(M::transmissibility, scon[VI::SConn::ConnTrans])) }
|
||||||
/*
|
, depth { as_float(unit_system.to_si(M::length, scon[VI::SConn::Depth])) }
|
||||||
r0: The r0 quantity is currently not written or read from the restart
|
, diameter { as_float(unit_system.to_si(M::length, scon[VI::SConn::Diameter])) }
|
||||||
file. If the r0 value is given explicitly in the deck it is possible
|
, kh { as_float(unit_system.to_si(M::effective_Kh, scon[VI::SConn::EffectiveKH])) }
|
||||||
to give a value which is not consistent with the Peaceman formula -
|
, denom { scon[VI::SConn::CFDenom] }
|
||||||
that value will be lost when loading back from a restart file.
|
, length { as_float(unit_system.to_si(M::length, scon[VI::SConn::EffectiveLength])) }
|
||||||
*/
|
, static_dfac_corr_coeff { staticDFactorCorrCoeff(unit_system, scon[VI::SConn::StaticDFacCorrCoeff]) }
|
||||||
|
, segdist_end { as_float(unit_system.to_si(M::length, scon[VI::SConn::SegDistEnd])) }
|
||||||
|
, segdist_start { as_float(unit_system.to_si(M::length, scon[VI::SConn::SegDistStart])) }
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Double values (XCON)
|
||||||
|
, oil_rate { unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::OilRate]) }
|
||||||
|
, water_rate { unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::WaterRate]) }
|
||||||
|
, gas_rate { unit_system.to_si(M::gas_surface_rate, xcon[VI::XConn::GasRate]) }
|
||||||
|
, pressure { unit_system.to_si(M::pressure, xcon[VI::XConn::Pressure]) }
|
||||||
|
, resv_rate { unit_system.to_si(M::rate, xcon[VI::XConn::ResVRate]) }
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Derived quantities
|
||||||
|
, r0 { pressEquivRadius(this->denom, this->skin_factor, this->diameter / 2) }
|
||||||
{
|
{
|
||||||
if (static_cast<std::size_t>(nsconz) > VI::SConn::CFInDeck)
|
if (static_cast<std::size_t>(nsconz) > VI::SConn::CFInDeck) {
|
||||||
this->cf_kind = from_float(scon[VI::SConn::CFInDeck]);
|
this->cf_kind = from_float(scon[VI::SConn::CFInDeck]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
This file is part of the Open Porous Media project (OPM).
|
||||||
|
|
||||||
OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
|
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
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
|
@ -17,17 +17,24 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <opm/common/utility/String.hpp>
|
#include <opm/io/eclipse/rst/well.hpp>
|
||||||
|
|
||||||
#include <opm/io/eclipse/rst/header.hpp>
|
#include <opm/io/eclipse/rst/header.hpp>
|
||||||
#include <opm/io/eclipse/rst/connection.hpp>
|
#include <opm/io/eclipse/rst/connection.hpp>
|
||||||
#include <opm/io/eclipse/rst/well.hpp>
|
|
||||||
|
|
||||||
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/msw.hpp>
|
#include <opm/output/eclipse/VectorItems/msw.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/well.hpp>
|
#include <opm/output/eclipse/VectorItems/well.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
|
#include <opm/common/utility/String.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/ParserItem.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeyword.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserRecord.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -54,28 +61,34 @@ namespace {
|
|||||||
{
|
{
|
||||||
return is_sentinel(raw_value) ? raw_value : convert(raw_value);
|
return is_sentinel(raw_value) ? raw_value : convert(raw_value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
float dfactor_correlation_coefficient_a(const Opm::UnitSystem& unit_system,
|
||||||
|
const float coeff_a)
|
||||||
|
{
|
||||||
|
const auto dimension = Opm::ParserKeywords::WDFACCOR{}
|
||||||
|
.getRecord(0).get(Opm::ParserKeywords::WDFACCOR::A::itemName)
|
||||||
|
.dimensions().front();
|
||||||
|
|
||||||
|
return static_cast<float>(unit_system.to_si(dimension, coeff_a));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int def_ecl_phase = 1;
|
||||||
|
constexpr int def_pvt_table = 0;
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
||||||
|
using M = ::Opm::UnitSystem::measure;
|
||||||
|
|
||||||
namespace Opm {
|
Opm::RestartIO::RstWell::RstWell(const UnitSystem& unit_system,
|
||||||
namespace RestartIO {
|
const RstHeader& header,
|
||||||
|
const std::string& group_arg,
|
||||||
constexpr int def_ecl_phase = 1;
|
const std::string* zwel,
|
||||||
constexpr int def_pvt_table = 0;
|
const int* iwel,
|
||||||
|
const float* swel,
|
||||||
using M = ::Opm::UnitSystem::measure;
|
const double* xwel,
|
||||||
|
const int* icon,
|
||||||
RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
const float* scon,
|
||||||
const RstHeader& header,
|
const double* xcon) :
|
||||||
const std::string& group_arg,
|
|
||||||
const std::string* zwel,
|
|
||||||
const int * iwel,
|
|
||||||
const float * swel,
|
|
||||||
const double * xwel,
|
|
||||||
const int * icon,
|
|
||||||
const float * scon,
|
|
||||||
const double * xcon) :
|
|
||||||
name(rtrim_copy(zwel[0])),
|
name(rtrim_copy(zwel[0])),
|
||||||
group(group_arg),
|
group(group_arg),
|
||||||
ij( {iwel[VI::IWell::IHead] - 1, iwel[VI::IWell::JHead] - 1}),
|
ij( {iwel[VI::IWell::IHead] - 1, iwel[VI::IWell::JHead] - 1}),
|
||||||
@ -139,6 +152,9 @@ RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
|||||||
glift_min_rate( unit_system.to_si(M::gas_surface_rate, swel[VI::SWell::LOminRate])),
|
glift_min_rate( unit_system.to_si(M::gas_surface_rate, swel[VI::SWell::LOminRate])),
|
||||||
glift_weight_factor( swel[VI::SWell::LOweightFac]),
|
glift_weight_factor( swel[VI::SWell::LOweightFac]),
|
||||||
glift_inc_weight_factor( swel[VI::SWell::LOincFac]),
|
glift_inc_weight_factor( swel[VI::SWell::LOincFac]),
|
||||||
|
dfac_corr_coeff_a(dfactor_correlation_coefficient_a(unit_system, swel[VI::SWell::DFacCorrCoeffA])),
|
||||||
|
dfac_corr_exponent_b( swel[VI::SWell::DFacCorrExpB]),
|
||||||
|
dfac_corr_exponent_c( swel[VI::SWell::DFacCorrExpC]),
|
||||||
//
|
//
|
||||||
oil_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::OilPrRate])),
|
oil_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::OilPrRate])),
|
||||||
water_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::WatPrRate])),
|
water_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::WatPrRate])),
|
||||||
@ -167,66 +183,81 @@ RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
|||||||
gas_void_rate( unit_system.to_si(M::gas_surface_volume, xwel[VI::XWell::GasVoidPrRate]))
|
gas_void_rate( unit_system.to_si(M::gas_surface_volume, xwel[VI::XWell::GasVoidPrRate]))
|
||||||
{
|
{
|
||||||
|
|
||||||
for (std::size_t tracer_index = 0; tracer_index < static_cast<std::size_t>(header.runspec.tracers().water_tracers()); tracer_index++)
|
for (std::size_t tracer_index = 0;
|
||||||
this->tracer_concentration_injection.push_back( swel[VI::SWell::TracerOffset + tracer_index] );
|
tracer_index < static_cast<std::size_t>(header.runspec.tracers().water_tracers());
|
||||||
|
++tracer_index)
|
||||||
|
{
|
||||||
|
this->tracer_concentration_injection.push_back(swel[VI::SWell::TracerOffset + tracer_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int ic = 0; ic < iwel[VI::IWell::NConn]; ++ic) {
|
||||||
|
const std::size_t icon_offset = ic * header.niconz;
|
||||||
|
const std::size_t scon_offset = ic * header.nsconz;
|
||||||
|
const std::size_t xcon_offset = ic * header.nxconz;
|
||||||
|
|
||||||
for (int ic = 0; ic < iwel[VI::IWell::NConn]; ic++) {
|
this->connections.emplace_back(unit_system, ic, header.nsconz,
|
||||||
std::size_t icon_offset = ic * header.niconz;
|
icon + icon_offset,
|
||||||
std::size_t scon_offset = ic * header.nsconz;
|
scon + scon_offset,
|
||||||
std::size_t xcon_offset = ic * header.nxconz;
|
xcon + xcon_offset);
|
||||||
this->connections.emplace_back( unit_system, ic, header.nsconz, icon + icon_offset, scon + scon_offset, xcon + xcon_offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
Opm::RestartIO::RstWell::RstWell(const UnitSystem& unit_system,
|
||||||
const RstHeader& header,
|
const RstHeader& header,
|
||||||
const std::string& group_arg,
|
const std::string& group_arg,
|
||||||
const std::string* zwel,
|
const std::string* zwel,
|
||||||
const int * iwel,
|
const int* iwel,
|
||||||
const float * swel,
|
const float* swel,
|
||||||
const double * xwel,
|
const double* xwel,
|
||||||
const int * icon,
|
const int* icon,
|
||||||
const float * scon,
|
const float* scon,
|
||||||
const double * xcon,
|
const double* xcon,
|
||||||
const std::vector<int>& iseg,
|
const std::vector<int>& iseg,
|
||||||
const std::vector<double>& rseg) :
|
const std::vector<double>& rseg)
|
||||||
RstWell(unit_system, header, group_arg, zwel, iwel, swel, xwel, icon, scon, xcon)
|
: RstWell { unit_system, header, group_arg,
|
||||||
|
zwel, iwel, swel, xwel,
|
||||||
|
icon, scon, xcon }
|
||||||
{
|
{
|
||||||
|
if (this->msw_index == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->msw_index) {
|
std::unordered_map<int, std::size_t> segment_map;
|
||||||
std::unordered_map<int, std::size_t> segment_map;
|
for (int is = 0; is < header.nsegmx; ++is) {
|
||||||
for (int is=0; is < header.nsegmx; is++) {
|
const std::size_t iseg_offset = header.nisegz * (is + (this->msw_index - 1)*header.nsegmx);
|
||||||
std::size_t iseg_offset = header.nisegz * (is + (this->msw_index - 1) * header.nsegmx);
|
const std::size_t rseg_offset = header.nrsegz * (is + (this->msw_index - 1)*header.nsegmx);
|
||||||
std::size_t rseg_offset = header.nrsegz * (is + (this->msw_index - 1) * header.nsegmx);
|
const auto other_segment_number = iseg[iseg_offset + VI::ISeg::SegNo];
|
||||||
auto other_segment_number = iseg[iseg_offset + VI::ISeg::SegNo];
|
|
||||||
if (other_segment_number != 0) {
|
if (other_segment_number != 0) {
|
||||||
auto segment_number = is + 1;
|
auto segment_number = is + 1;
|
||||||
segment_map.insert({segment_number, this->segments.size()});
|
segment_map.insert({segment_number, this->segments.size()});
|
||||||
this->segments.emplace_back( unit_system, segment_number, iseg.data() + iseg_offset, rseg.data() + rseg_offset);
|
this->segments.emplace_back(unit_system, segment_number,
|
||||||
}
|
iseg.data() + iseg_offset,
|
||||||
|
rseg.data() + rseg_offset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& segment : this->segments) {
|
for (auto& segment : this->segments) {
|
||||||
if (segment.outlet_segment != 0) {
|
if (segment.outlet_segment != 0) {
|
||||||
auto& outlet_segment = this->segments[ segment_map[segment.outlet_segment] ];
|
auto& outlet_segment = this->segments[ segment_map[segment.outlet_segment] ];
|
||||||
outlet_segment.inflow_segments.push_back(segment.segment);
|
outlet_segment.inflow_segments.push_back(segment.segment);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RstSegment&
|
|
||||||
RstWell::segment(int segment_number) const
|
|
||||||
{
|
|
||||||
const auto& iter = std::find_if(this->segments.begin(), this->segments.end(), [segment_number](const RstSegment& segment) { return segment.segment == segment_number; });
|
|
||||||
|
|
||||||
if (iter == this->segments.end())
|
const Opm::RestartIO::RstSegment&
|
||||||
|
Opm::RestartIO::RstWell::segment(int segment_number) const
|
||||||
|
{
|
||||||
|
auto iter = std::find_if(this->segments.begin(), this->segments.end(),
|
||||||
|
[segment_number](const RstSegment& segment)
|
||||||
|
{ return segment.segment == segment_number; });
|
||||||
|
|
||||||
|
if (iter == this->segments.end()) {
|
||||||
throw std::invalid_argument("No such segment");
|
throw std::invalid_argument("No such segment");
|
||||||
|
}
|
||||||
|
|
||||||
return *iter;
|
return *iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namepace Opm::RestartIO
|
|
||||||
|
@ -167,6 +167,16 @@ namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double staticDFacCorrCoeff(const Opm::Connection::CTFProperties& ctf_props,
|
||||||
|
const Opm::UnitSystem& units)
|
||||||
|
{
|
||||||
|
using M = Opm::UnitSystem::measure;
|
||||||
|
|
||||||
|
// Coefficient's units are [D] * [viscosity]
|
||||||
|
|
||||||
|
return units.from_si(M::viscosity, units.from_si(M::dfactor, ctf_props.static_dfac_corr_coeff));
|
||||||
|
}
|
||||||
|
|
||||||
template <class SConnArray>
|
template <class SConnArray>
|
||||||
void staticContrib(const Opm::Connection& conn,
|
void staticContrib(const Opm::Connection& conn,
|
||||||
const Opm::UnitSystem& units,
|
const Opm::UnitSystem& units,
|
||||||
@ -180,7 +190,7 @@ namespace {
|
|||||||
return static_cast<float>(units.from_si(u, x));
|
return static_cast<float>(units.from_si(u, x));
|
||||||
};
|
};
|
||||||
|
|
||||||
sConn[Ix::ConnTrans] =
|
sConn[Ix::EffConnTrans] = sConn[Ix::ConnTrans] =
|
||||||
scprop(M::transmissibility, conn.CF());
|
scprop(M::transmissibility, conn.CF());
|
||||||
|
|
||||||
sConn[Ix::Depth] = scprop(M::length, conn.depth());
|
sConn[Ix::Depth] = scprop(M::length, conn.depth());
|
||||||
@ -191,8 +201,7 @@ namespace {
|
|||||||
|
|
||||||
sConn[Ix::SkinFactor] = conn.skinFactor();
|
sConn[Ix::SkinFactor] = conn.skinFactor();
|
||||||
|
|
||||||
sConn[Ix::item12] = sConn[Ix::ConnTrans];
|
sConn[Ix::CFDenom] = conn.ctfProperties().peaceman_denom;
|
||||||
|
|
||||||
|
|
||||||
if (conn.attachedToSegment()) {
|
if (conn.attachedToSegment()) {
|
||||||
const auto& [start, end] = *conn.perf_range();
|
const auto& [start, end] = *conn.perf_range();
|
||||||
@ -202,7 +211,14 @@ namespace {
|
|||||||
|
|
||||||
sConn[Ix::item30] = -1.0e+20f;
|
sConn[Ix::item30] = -1.0e+20f;
|
||||||
sConn[Ix::item31] = -1.0e+20f;
|
sConn[Ix::item31] = -1.0e+20f;
|
||||||
sConn[Ix::CFInDeck] = (conn.ctfAssignedFromInput()) ? 1 : 0;
|
|
||||||
|
sConn[Ix::EffectiveLength] =
|
||||||
|
scprop(M::length, conn.connectionLength());
|
||||||
|
|
||||||
|
sConn[Ix::StaticDFacCorrCoeff] =
|
||||||
|
staticDFacCorrCoeff(conn.ctfProperties(), units);
|
||||||
|
|
||||||
|
sConn[Ix::CFInDeck] = conn.ctfAssignedFromInput() ? 1.0f : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class SConnArray>
|
template <class SConnArray>
|
||||||
@ -218,8 +234,15 @@ namespace {
|
|||||||
return static_cast<float>(units.from_si(u, x));
|
return static_cast<float>(units.from_si(u, x));
|
||||||
};
|
};
|
||||||
|
|
||||||
sConn[Ix::item12] = sConn[Ix::ConnTrans] =
|
sConn[Ix::EffConnTrans] = sConn[Ix::ConnTrans] =
|
||||||
scprop(M::transmissibility, xconn.trans_factor);
|
scprop(M::transmissibility, xconn.trans_factor);
|
||||||
|
|
||||||
|
// xconn.trans_factor == CTFAC == CF * rock compaction. Divide
|
||||||
|
// out the rock compaction contribution to infer the "real"
|
||||||
|
// connection transmissibility factor. No additional unit
|
||||||
|
// conversion needed since the rock compaction effect (keyword
|
||||||
|
// ROCKTAB) is imparted through a dimensionless multiplier.
|
||||||
|
sConn[Ix::ConnTrans] /= xconn.compact_mult;
|
||||||
}
|
}
|
||||||
} // SConn
|
} // SConn
|
||||||
|
|
||||||
@ -314,12 +337,12 @@ AggregateConnectionData(const std::vector<int>& inteHead)
|
|||||||
|
|
||||||
void
|
void
|
||||||
Opm::RestartIO::Helpers::AggregateConnectionData::
|
Opm::RestartIO::Helpers::AggregateConnectionData::
|
||||||
captureDeclaredConnData(const Schedule& sched,
|
captureDeclaredConnData(const Schedule& sched,
|
||||||
const EclipseGrid& grid,
|
const EclipseGrid& grid,
|
||||||
const UnitSystem& units,
|
const UnitSystem& units,
|
||||||
const data::Wells& xw,
|
const data::Wells& xw,
|
||||||
const SummaryState& summary_state,
|
const SummaryState& summary_state,
|
||||||
const std::size_t sim_step)
|
const std::size_t sim_step)
|
||||||
{
|
{
|
||||||
wellConnectionLoop(sched, sim_step, grid, xw, [&units, &summary_state, this]
|
wellConnectionLoop(sched, sim_step, grid, xw, [&units, &summary_state, this]
|
||||||
(const std::string& wellName,
|
(const std::string& wellName,
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/VFPProdTable.hpp>
|
#include <opm/input/eclipse/Schedule/VFPProdTable.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WDFAC.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellEconProductionLimits.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellEconProductionLimits.hpp>
|
||||||
@ -49,6 +50,11 @@
|
|||||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
#include <opm/input/eclipse/Units/Units.hpp>
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/ParserItem.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeyword.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserRecord.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -1028,6 +1034,26 @@ namespace {
|
|||||||
sWell[Ix::EfficiencyFactor2] = sWell[Ix::EfficiencyFactor1];
|
sWell[Ix::EfficiencyFactor2] = sWell[Ix::EfficiencyFactor1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class SWellArray>
|
||||||
|
void assignDFactorCorrelation(const Opm::Well& well,
|
||||||
|
const Opm::UnitSystem& units,
|
||||||
|
SWellArray& sWell)
|
||||||
|
{
|
||||||
|
using Ix = VI::SWell::index;
|
||||||
|
|
||||||
|
const auto& corr = well.getWDFAC().getDFactorCorrelationCoefficients();
|
||||||
|
|
||||||
|
// D-Factor correlation exponents don't need unit conversion.
|
||||||
|
sWell[Ix::DFacCorrExpB] = corr.exponent_b;
|
||||||
|
sWell[Ix::DFacCorrExpC] = corr.exponent_c;
|
||||||
|
|
||||||
|
const auto dimension = Opm::ParserKeywords::WDFACCOR{}
|
||||||
|
.getRecord(0).get(Opm::ParserKeywords::WDFACCOR::A::itemName)
|
||||||
|
.dimensions().front();
|
||||||
|
|
||||||
|
sWell[Ix::DFacCorrCoeffA] = units.from_si(dimension, corr.coeff_a);
|
||||||
|
}
|
||||||
|
|
||||||
template <class SWProp, class SWellArray>
|
template <class SWProp, class SWellArray>
|
||||||
void assignBhpVfpAdjustment(const Opm::Well& well,
|
void assignBhpVfpAdjustment(const Opm::Well& well,
|
||||||
SWProp&& swprop,
|
SWProp&& swprop,
|
||||||
@ -1094,6 +1120,7 @@ namespace {
|
|||||||
|
|
||||||
assignWGrupCon(well, sWell);
|
assignWGrupCon(well, sWell);
|
||||||
assignEfficiencyFactors(well, sWell);
|
assignEfficiencyFactors(well, sWell);
|
||||||
|
assignDFactorCorrelation(well, units, sWell);
|
||||||
assignEconomicLimits(well, swprop, sWell);
|
assignEconomicLimits(well, swprop, sWell);
|
||||||
assignWellTest(well.name(), sched, wtest_state, sim_step, swprop, sWell);
|
assignWellTest(well.name(), sched, wtest_state, sim_step, swprop, sWell);
|
||||||
assignTracerData(tracers, smry, well.name(), sWell);
|
assignTracerData(tracers, smry, well.name(), sWell);
|
||||||
|
@ -17,32 +17,39 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
#define BOOST_TEST_MODULE CompletionTests
|
#define BOOST_TEST_MODULE CompletionTests
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <opm/common/utility/ActiveGridCells.hpp>
|
|
||||||
#include <opm/input/eclipse/Python/Python.hpp>
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
#include <opm/common/utility/ActiveGridCells.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Python/Python.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WDFAC.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||||
|
|
||||||
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/Units.hpp>
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
double cp_rm3_per_db()
|
double cp_rm3_per_db()
|
||||||
@ -51,20 +58,32 @@ namespace {
|
|||||||
/ (Opm::unit::day * Opm::unit::barsa);
|
/ (Opm::unit::day * Opm::unit::barsa);
|
||||||
}
|
}
|
||||||
|
|
||||||
Opm::WellConnections loadCOMPDAT(const std::string& compdat_keyword) {
|
Opm::WellConnections
|
||||||
Opm::EclipseGrid grid(10,10,10);
|
loadCOMPDAT(const std::string& compdat_keyword)
|
||||||
Opm::TableManager tables;
|
{
|
||||||
Opm::Parser parser;
|
Opm::WellConnections connections {
|
||||||
const auto deck = parser.parseString(compdat_keyword);
|
Opm::Connection::Order::TRACK, 10, 10
|
||||||
Opm::FieldPropsManager field_props(deck, Opm::Phases{true, true, true}, grid, Opm::TableManager());
|
};
|
||||||
const auto& keyword = deck["COMPDAT"][0];
|
|
||||||
Opm::WellConnections connections(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::CompletedCells cells(grid);
|
|
||||||
for (const auto& rec : keyword)
|
|
||||||
connections.loadCOMPDAT(rec, Opm::ScheduleGrid(grid, field_props, cells), "WELL", {});
|
|
||||||
|
|
||||||
return connections;
|
const auto deck = Opm::Parser{}.parseString(compdat_keyword);
|
||||||
}
|
const auto wdfac = Opm::WDFAC{};
|
||||||
|
const auto loc = Opm::KeywordLocation{};
|
||||||
|
|
||||||
|
const Opm::EclipseGrid grid { 10, 10, 10 };
|
||||||
|
const Opm::FieldPropsManager field_props {
|
||||||
|
deck, Opm::Phases{true, true, true}, grid, Opm::TableManager{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Must be mutable.
|
||||||
|
Opm::CompletedCells completed_cells(grid);
|
||||||
|
const auto sg = Opm::ScheduleGrid { grid, field_props, completed_cells };
|
||||||
|
|
||||||
|
for (const auto& rec : deck["COMPDAT"][0]) {
|
||||||
|
connections.loadCOMPDAT(rec, sg, "WELL", wdfac, loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
@ -94,12 +113,22 @@ BOOST_AUTO_TEST_CASE(CreateWellConnectionsOK) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
|
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
|
const auto depth = 0.0;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 10,10,10, 100, 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 10,10,11, 102, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
||||||
Opm::Connection completion1( 10,10,10, 100, 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion2( 10,10,11, 102, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
completionSet.add( completion1 );
|
completionSet.add( completion1 );
|
||||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||||
BOOST_CHECK_MESSAGE( !completionSet.empty(), "Non-empty completion set must not be empty" );
|
BOOST_CHECK_MESSAGE( !completionSet.empty(), "Non-empty completion set must not be empty" );
|
||||||
@ -111,11 +140,21 @@ BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows) {
|
BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::Connection completion1( 10,10,10, 100, 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0,true);
|
const auto depth = 0.0;
|
||||||
Opm::Connection completion2( 10,10,11, 102, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0,true);
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 10,10,10, 100, 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 10,10,11, 102, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
||||||
completionSet.add( completion1 );
|
completionSet.add( completion1 );
|
||||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||||
@ -148,15 +187,23 @@ BOOST_AUTO_TEST_CASE(Compdat_Direction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
BOOST_AUTO_TEST_CASE(AddCompletionCopy)
|
||||||
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 10,10);
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
|
const auto depth = 0.0;
|
||||||
|
|
||||||
Opm::Connection completion1( 10,10,10, 100, 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
Opm::Connection completion2( 10,10,11, 101, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion3( 10,10,12, 102, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 10,10,10, 100, 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 10,10,11, 101, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion3 = Opm::Connection { 10,10,12, 102, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
|
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 10,10);
|
||||||
completionSet.add( completion1 );
|
completionSet.add( completion1 );
|
||||||
completionSet.add( completion2 );
|
completionSet.add( completion2 );
|
||||||
completionSet.add( completion3 );
|
completionSet.add( completion3 );
|
||||||
@ -171,31 +218,43 @@ BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(ActiveCompletions) {
|
BOOST_AUTO_TEST_CASE(ActiveCompletions)
|
||||||
Opm::EclipseGrid grid(10,20,20);
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::Defaulted;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections completions(Opm::Connection::Order::TRACK, 10,10);
|
const auto depth = 0.0;
|
||||||
Opm::Connection completion1( 0,0,0, grid.getGlobalIndex(0,0,0), 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion2( 0,0,1, grid.getGlobalIndex(0,0,1), 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion3( 0,0,2, grid.getGlobalIndex(0,0,2), 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::EclipseGrid grid { 10, 20, 20 };
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 0,0,0, grid.getGlobalIndex(0,0,0), 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 0,0,1, grid.getGlobalIndex(0,0,1), 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion3 = Opm::Connection { 0,0,2, grid.getGlobalIndex(0,0,2), 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
|
Opm::WellConnections completions(Opm::Connection::Order::TRACK, 10,10);
|
||||||
completions.add( completion1 );
|
completions.add( completion1 );
|
||||||
completions.add( completion2 );
|
completions.add( completion2 );
|
||||||
completions.add( completion3 );
|
completions.add( completion3 );
|
||||||
|
|
||||||
std::vector<int> actnum(grid.getCartesianSize(), 1);
|
std::vector<int> actnum(grid.getCartesianSize(), 1);
|
||||||
actnum[0] = 0;
|
actnum[0] = 0;
|
||||||
grid.resetACTNUM( actnum);
|
grid.resetACTNUM(actnum);
|
||||||
|
|
||||||
Opm::WellConnections active_completions(completions, grid);
|
const Opm::WellConnections active_completions(completions, grid);
|
||||||
BOOST_CHECK_EQUAL( active_completions.size() , 2U);
|
BOOST_CHECK_EQUAL( active_completions.size() , 2U);
|
||||||
BOOST_CHECK_EQUAL( completion2, active_completions.get(0));
|
BOOST_CHECK_EQUAL( completion2, active_completions.get(0));
|
||||||
BOOST_CHECK_EQUAL( completion3, active_completions.get(1));
|
BOOST_CHECK_EQUAL( completion3, active_completions.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(loadCOMPDATTEST) {
|
BOOST_AUTO_TEST_CASE(loadCOMPDATTEST)
|
||||||
Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA.
|
{
|
||||||
|
const Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA.
|
||||||
|
|
||||||
{
|
{
|
||||||
const std::string deck = R"(GRID
|
const std::string deck = R"(GRID
|
||||||
|
|
||||||
@ -206,13 +265,18 @@ COPY
|
|||||||
'PERMX' 'PERMZ' /
|
'PERMX' 'PERMZ' /
|
||||||
'PERMX' 'PERMY' /
|
'PERMX' 'PERMY' /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
COMPDAT
|
COMPDAT
|
||||||
-- CF Diam Kh Skin Df
|
-- CF Diam Kh Skin Df
|
||||||
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 /
|
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 /
|
||||||
/)";
|
/)";
|
||||||
Opm::WellConnections connections = loadCOMPDAT(deck);
|
|
||||||
|
const Opm::WellConnections connections = loadCOMPDAT(deck);
|
||||||
const auto& conn0 = connections[0];
|
const auto& conn0 = connections[0];
|
||||||
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
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));
|
BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 107.872));
|
||||||
@ -230,13 +294,17 @@ COPY
|
|||||||
'PERMX' 'PERMY' /
|
'PERMX' 'PERMY' /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
COMPDAT
|
COMPDAT
|
||||||
-- CF Diam Kh Skin Df
|
-- CF Diam Kh Skin Df
|
||||||
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 0 1* 1* 'Z' 21.925 /
|
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 0 1* 1* 'Z' 21.925 /
|
||||||
/)";
|
/)";
|
||||||
Opm::WellConnections connections = loadCOMPDAT(deck);
|
|
||||||
|
const Opm::WellConnections connections = loadCOMPDAT(deck);
|
||||||
const auto& conn0 = connections[0];
|
const auto& conn0 = connections[0];
|
||||||
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
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_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 0.10 * 1.0));
|
||||||
@ -460,20 +528,16 @@ END
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset CF -- simulating COMPDAT record (inactive cell)
|
// Reset CF -- simulating COMPDAT record (inactive cell)
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
ctf_props.CF = 50.0*cp_rm3_per_db();
|
||||||
|
ctf_props.Kh = 0.123;
|
||||||
|
ctf_props.rw = 0.234;
|
||||||
|
ctf_props.r0 = 0.157;
|
||||||
|
|
||||||
connP.addConnection(9, 9, 1, // 10, 10, 2
|
connP.addConnection(9, 9, 1, // 10, 10, 2
|
||||||
199,
|
199,
|
||||||
2015.0,
|
Opm::Connection::State::OPEN,
|
||||||
Opm::Connection::State::OPEN,
|
2015.0, ctf_props, 1);
|
||||||
50.0*cp_rm3_per_db(),
|
|
||||||
0.123,
|
|
||||||
0.234,
|
|
||||||
0.157,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
1);
|
|
||||||
|
|
||||||
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{3});
|
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{3});
|
||||||
|
|
||||||
@ -506,19 +570,9 @@ END
|
|||||||
|
|
||||||
// Reset CF -- simulating COMPDAT record (active cell)
|
// Reset CF -- simulating COMPDAT record (active cell)
|
||||||
connP.addConnection(8, 9, 1, // 10, 10, 2
|
connP.addConnection(8, 9, 1, // 10, 10, 2
|
||||||
198,
|
198,
|
||||||
2015.0,
|
Opm::Connection::State::OPEN,
|
||||||
Opm::Connection::State::OPEN,
|
2015.0, ctf_props, 1);
|
||||||
50.0*cp_rm3_per_db(),
|
|
||||||
0.123,
|
|
||||||
0.234,
|
|
||||||
0.157,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
1);
|
|
||||||
|
|
||||||
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{4});
|
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{4});
|
||||||
|
|
||||||
|
@ -55,20 +55,32 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AICDWellTest) {
|
BOOST_AUTO_TEST_CASE(AICDWellTest)
|
||||||
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25.0, 2500.0);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0,grid.getGlobalIndex(19,0,0), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1,grid.getGlobalIndex(19,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2,grid.getGlobalIndex(19,0,2), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1,grid.getGlobalIndex(18,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1,grid.getGlobalIndex(17,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1,grid.getGlobalIndex(16,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1,grid.getGlobalIndex(15,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -212,23 +224,33 @@ WSEGAICD
|
|||||||
const double center_depth_connection7 = connection7.depth();
|
const double center_depth_connection7 = connection7.depth();
|
||||||
BOOST_CHECK_EQUAL(segment_number_connection7, 8);
|
BOOST_CHECK_EQUAL(segment_number_connection7, 8);
|
||||||
BOOST_CHECK_EQUAL(center_depth_connection7, 2534.5);
|
BOOST_CHECK_EQUAL(center_depth_connection7, 2534.5);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(MultisegmentWellTest) {
|
BOOST_AUTO_TEST_CASE(MultisegmentWellTest)
|
||||||
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25.0, 2500.0);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0,grid.getGlobalIndex(19,0,0), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1,grid.getGlobalIndex(19,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2,grid.getGlobalIndex(19,0,2), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1,grid.getGlobalIndex(18,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1,grid.getGlobalIndex(17,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1,grid.getGlobalIndex(16,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1,grid.getGlobalIndex(15,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -383,19 +405,32 @@ WSEGSICD
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS) {
|
BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25., 2500.);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0, grid.getGlobalIndex(19,0,0),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1, grid.getGlobalIndex(19,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2, grid.getGlobalIndex(19,0,2),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1, grid.getGlobalIndex(18,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25., 2500.0 };
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1, grid.getGlobalIndex(17,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1, grid.getGlobalIndex(16,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1, grid.getGlobalIndex(15,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -452,19 +487,32 @@ BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS) {
|
|||||||
BOOST_CHECK_NO_THROW(Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard));
|
BOOST_CHECK_NO_THROW(Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(NegativeDepthCOMPSEGS) {
|
BOOST_AUTO_TEST_CASE(NegativeDepthCOMPSEGS)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25., 2500.);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0, grid.getGlobalIndex(19,0,0),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1, grid.getGlobalIndex(19,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2, grid.getGlobalIndex(19,0,2),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1, grid.getGlobalIndex(18,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1, grid.getGlobalIndex(17,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1, grid.getGlobalIndex(16,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1, grid.getGlobalIndex(15,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -521,19 +569,31 @@ BOOST_AUTO_TEST_CASE(NegativeDepthCOMPSEGS) {
|
|||||||
BOOST_CHECK_NO_THROW( Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard) );
|
BOOST_CHECK_NO_THROW( Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard) );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(testwsegvalv) {
|
BOOST_AUTO_TEST_CASE(testwsegvalv)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25., 2500.);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,192 +22,219 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Python/Python.hpp>
|
#include <opm/input/eclipse/Python/Python.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
||||||
|
|
||||||
using namespace Opm;
|
using namespace Opm;
|
||||||
|
|
||||||
static Deck createDeckWithOutSolvent() {
|
namespace {
|
||||||
Opm::Parser parser;
|
|
||||||
std::string input =
|
|
||||||
"GRID\n"
|
|
||||||
"PERMX\n"
|
|
||||||
" 1000*0.25/\n"
|
|
||||||
"COPY\n"
|
|
||||||
" PERMX PERMY /\n"
|
|
||||||
" PERMX PERMZ /\n"
|
|
||||||
"/\n"
|
|
||||||
"SCHEDULE\n"
|
|
||||||
"WELSPECS\n"
|
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/\n/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
Deck createDeckWithOutSolvent()
|
||||||
|
{
|
||||||
|
return Parser{}.parseString(R"(
|
||||||
|
GRID
|
||||||
|
PERMX
|
||||||
|
1000*0.25/
|
||||||
|
COPY
|
||||||
|
PERMX PERMY /
|
||||||
|
PERMX PERMZ /
|
||||||
|
/
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 2 2 1* 'OIL' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithGasInjector() {
|
Deck createDeckWithGasInjector()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
PORO
|
||||||
"WELSPECS\n"
|
1000*0.3 /
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
|
||||||
"WSOLVENT\n"
|
|
||||||
" 'W_1' 1 / \n "
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
WSOLVENT
|
||||||
|
'W_1' 1 /
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithDynamicWSOLVENT() {
|
Deck createDeckWithDynamicWSOLVENT()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"START -- 0 \n"
|
START -- 0
|
||||||
"1 JAN 2000 / \n"
|
1 JAN 2000 /
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
PORO
|
||||||
"WELSPECS\n"
|
1000*0.3 /
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
|
||||||
"DATES -- 2\n"
|
|
||||||
" 1 MAY 2000 / \n"
|
|
||||||
"/\n"
|
|
||||||
"WSOLVENT\n"
|
|
||||||
" 'W_1' 1 / \n "
|
|
||||||
"/\n"
|
|
||||||
"DATES -- 3,4\n"
|
|
||||||
" 1 JUL 2000 / \n"
|
|
||||||
" 1 AUG 2000 / \n"
|
|
||||||
"/\n"
|
|
||||||
"WSOLVENT\n"
|
|
||||||
" 'W_1' 0 / \n "
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
DATES -- 2
|
||||||
|
1 MAY 2000 /
|
||||||
|
/
|
||||||
|
WSOLVENT
|
||||||
|
'W_1' 1 /
|
||||||
|
/
|
||||||
|
DATES -- 3,4
|
||||||
|
1 JUL 2000 /
|
||||||
|
1 AUG 2000 /
|
||||||
|
/
|
||||||
|
WSOLVENT
|
||||||
|
'W_1' 0 /
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithOilInjector() {
|
Deck createDeckWithOilInjector()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
SCHEDULE
|
||||||
"WELSPECS\n"
|
WELSPECS
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
'W_1' 'OP' 2 2 1* 'OIL' 7* /
|
||||||
"/\n"
|
/
|
||||||
"COMPDAT\n"
|
COMPDAT
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
"/\n"
|
/
|
||||||
"WCONINJE\n"
|
WCONINJE
|
||||||
" 'W_1' 'OIL' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
'W_1' 'OIL' 'OPEN' 'BHP' 1 2 3/
|
||||||
"WSOLVENT\n"
|
/
|
||||||
" 'W_1' 1 / \n "
|
WSOLVENT
|
||||||
"/\n";
|
'W_1' 1 /
|
||||||
|
/
|
||||||
return parser.parseString(input);
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithWaterInjector() {
|
Deck createDeckWithWaterInjector()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
SCHEDULE
|
||||||
"WELSPECS\n"
|
WELSPECS
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
'W_1' 'OP' 2 2 1* \'OIL\' 7* /
|
||||||
"/\n"
|
/
|
||||||
"COMPDAT\n"
|
COMPDAT
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
"/\n"
|
/
|
||||||
"WCONINJE\n"
|
WCONINJE
|
||||||
" 'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/
|
||||||
"WSOLVENT\n"
|
/
|
||||||
" 'W_1' 1 / \n "
|
WSOLVENT
|
||||||
"/\n";
|
'W_1' 1 /
|
||||||
|
/
|
||||||
return parser.parseString(input);
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
BOOST_AUTO_TEST_CASE(TestNoSolvent) {
|
|
||||||
auto deck = createDeckWithOutSolvent();
|
} // Anonymous namespace
|
||||||
auto python = std::make_shared<Python>();
|
|
||||||
EclipseGrid grid(10,10,10);
|
BOOST_AUTO_TEST_CASE(TestNoSolvent)
|
||||||
TableManager table ( deck );
|
{
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const auto deck = createDeckWithOutSolvent();
|
||||||
Runspec runspec(deck);
|
const EclipseGrid grid(10,10,10);
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
const TableManager table (deck);
|
||||||
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
|
const Runspec runspec(deck);
|
||||||
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_CHECK(!deck.hasKeyword("WSOLVENT"));
|
BOOST_CHECK(!deck.hasKeyword("WSOLVENT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestGasInjector) {
|
BOOST_AUTO_TEST_CASE(TestGasInjector) {
|
||||||
auto deck = createDeckWithGasInjector();
|
const auto deck = createDeckWithGasInjector();
|
||||||
auto python = std::make_shared<Python>();
|
const EclipseGrid grid(10,10,10);
|
||||||
EclipseGrid grid(10,10,10);
|
const TableManager table (deck);
|
||||||
TableManager table ( deck );
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const Runspec runspec(deck);
|
||||||
Runspec runspec(deck);
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
|
||||||
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT) {
|
BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT)
|
||||||
auto deck = createDeckWithDynamicWSOLVENT();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithDynamicWSOLVENT();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table (deck);
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec(deck);
|
const Runspec runspec(deck);
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
||||||
|
|
||||||
const auto& keyword = deck["WSOLVENT"].back();
|
const auto& keyword = deck["WSOLVENT"].back();
|
||||||
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
||||||
|
|
||||||
const auto& record = keyword.getRecord(0);
|
const auto& record = keyword.getRecord(0);
|
||||||
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
||||||
BOOST_CHECK_EQUAL(well_name, "W_1");
|
BOOST_CHECK_EQUAL(well_name, "W_1");
|
||||||
@ -217,22 +244,24 @@ BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT) {
|
|||||||
BOOST_CHECK_EQUAL(schedule.getWell("W_1", 3).getSolventFraction(),0);
|
BOOST_CHECK_EQUAL(schedule.getWell("W_1", 3).getSolventFraction(),0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestOilInjector) {
|
BOOST_AUTO_TEST_CASE(TestOilInjector)
|
||||||
auto deck = createDeckWithOilInjector();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithOilInjector();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table (deck);
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec(deck);
|
const Runspec runspec(deck);
|
||||||
BOOST_CHECK_THROW (Schedule(deck , grid , fp, runspec, python), std::exception);
|
|
||||||
|
BOOST_CHECK_THROW (Schedule(deck, grid, fp, runspec, std::make_shared<Python>()), std::exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestWaterInjector) {
|
BOOST_AUTO_TEST_CASE(TestWaterInjector)
|
||||||
auto deck = createDeckWithWaterInjector();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithWaterInjector();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table ( deck );
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec(deck);
|
const Runspec runspec(deck);
|
||||||
BOOST_CHECK_THROW (Schedule(deck, grid , fp, runspec, python), std::exception);
|
|
||||||
|
BOOST_CHECK_THROW (Schedule(deck, grid , fp, runspec, std::make_shared<Python>()), std::exception);
|
||||||
}
|
}
|
||||||
|
@ -22,141 +22,166 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <opm/common/utility/OpmInputError.hpp>
|
#include <opm/common/utility/OpmInputError.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Python/Python.hpp>
|
#include <opm/input/eclipse/Python/Python.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellTracerProperties.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellTracerProperties.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
|
|
||||||
using namespace Opm;
|
using namespace Opm;
|
||||||
|
|
||||||
static Deck createDeckWithOutTracer() {
|
namespace {
|
||||||
Opm::Parser parser;
|
|
||||||
std::string input =
|
|
||||||
"GRID\n"
|
|
||||||
"PERMX\n"
|
|
||||||
" 1000*0.25/\n"
|
|
||||||
"COPY\n"
|
|
||||||
" PERMX PERMY /\n"
|
|
||||||
" PERMX PERMZ /\n"
|
|
||||||
"/\n"
|
|
||||||
"SCHEDULE\n"
|
|
||||||
"WELSPECS\n"
|
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/\n/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
Deck createDeckWithOutTracer()
|
||||||
|
{
|
||||||
|
return Parser{}.parseString(R"(
|
||||||
|
GRID
|
||||||
|
PERMX
|
||||||
|
1000*0.25/
|
||||||
|
COPY
|
||||||
|
PERMX PERMY /
|
||||||
|
PERMX PERMZ /
|
||||||
|
/
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 2 2 1* 'OIL' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Deck createDeckWithDynamicWTRACER()
|
||||||
|
{
|
||||||
|
return Parser{}.parseString(R"(
|
||||||
|
START -- 0
|
||||||
|
1 JAN 2000 /
|
||||||
|
GRID
|
||||||
|
PERMX
|
||||||
|
1000*0.25/
|
||||||
|
COPY
|
||||||
|
PERMX PERMY /
|
||||||
|
PERMX PERMZ /
|
||||||
|
/
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
static Deck createDeckWithDynamicWTRACER() {
|
SCHEDULE
|
||||||
Opm::Parser parser;
|
WELSPECS
|
||||||
std::string input =
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
"START -- 0 \n"
|
/
|
||||||
"1 JAN 2000 / \n"
|
COMPDAT
|
||||||
"GRID\n"
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
"PERMX\n"
|
/
|
||||||
" 1000*0.25/\n"
|
WCONINJE
|
||||||
"COPY\n"
|
'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/
|
||||||
" PERMX PERMY /\n"
|
/
|
||||||
" PERMX PERMZ /\n"
|
DATES -- 1
|
||||||
"/\n"
|
1 MAY 2000 /
|
||||||
"SCHEDULE\n"
|
/
|
||||||
"WELSPECS\n"
|
WTRACER
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
'W_1' 'I1' 1 /
|
||||||
"/\n"
|
'W_1' 'I2' 1 /
|
||||||
"COMPDAT\n"
|
/
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
DATES -- 2, 3
|
||||||
"/\n"
|
1 JUL 2000 /
|
||||||
"WCONINJE\n"
|
1 AUG 2000 /
|
||||||
" 'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
/
|
||||||
"DATES -- 1\n"
|
WTRACER
|
||||||
" 1 MAY 2000 / \n"
|
'W_1' 'I1' 0 /
|
||||||
"/\n"
|
/
|
||||||
"WTRACER\n"
|
DATES -- 4
|
||||||
" 'W_1' 'I1' 1 / \n "
|
1 SEP 2000 /
|
||||||
" 'W_1' 'I2' 1 / \n "
|
/
|
||||||
"/\n"
|
|
||||||
"DATES -- 2, 3\n"
|
|
||||||
" 1 JUL 2000 / \n"
|
|
||||||
" 1 AUG 2000 / \n"
|
|
||||||
"/\n"
|
|
||||||
"WTRACER\n"
|
|
||||||
" 'W_1' 'I1' 0 / \n "
|
|
||||||
"/\n"
|
|
||||||
"DATES -- 4\n"
|
|
||||||
" 1 SEP 2000 / \n"
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithTracerInProducer() {
|
Deck createDeckWithTracerInProducer()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"START -- 0 \n"
|
START -- 0
|
||||||
"1 JAN 2000 / \n"
|
1 JAN 2000 /
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
PORO
|
||||||
"WELSPECS\n"
|
1000*0.3 /
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONPROD\n"
|
|
||||||
"'W_1' 'OPEN' 'ORAT' 20000 4* 1000 /\n"
|
|
||||||
"WTRACER\n"
|
|
||||||
" 'W_1' 'I1' 1 / \n "
|
|
||||||
" 'W_1' 'I2' 1 / \n "
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONPROD
|
||||||
|
'W_1' 'OPEN' 'ORAT' 20000 4* 1000 /
|
||||||
|
WTRACER
|
||||||
|
'W_1' 'I1' 1 /
|
||||||
|
'W_1' 'I2' 1 /
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(TestNoTracer)
|
||||||
|
{
|
||||||
|
const auto deck = createDeckWithOutTracer();
|
||||||
|
|
||||||
|
const EclipseGrid grid(10,10,10);
|
||||||
|
const TableManager table (deck);
|
||||||
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
|
const Runspec runspec (deck);
|
||||||
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestNoTracer) {
|
|
||||||
auto deck = createDeckWithOutTracer();
|
|
||||||
EclipseGrid grid(10,10,10);
|
|
||||||
TableManager table ( deck );
|
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
|
||||||
auto python = std::make_shared<Python>();
|
|
||||||
Runspec runspec ( deck );
|
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
|
||||||
BOOST_CHECK(!deck.hasKeyword("WTRACER"));
|
BOOST_CHECK(!deck.hasKeyword("WTRACER"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestDynamicWTRACER) {
|
BOOST_AUTO_TEST_CASE(TestDynamicWTRACER)
|
||||||
auto deck = createDeckWithDynamicWTRACER();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithDynamicWTRACER();
|
||||||
EclipseGrid grid(10,10,10);
|
|
||||||
TableManager table ( deck );
|
const EclipseGrid grid(10,10,10);
|
||||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
const TableManager table (deck);
|
||||||
Runspec runspec ( deck );
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
const Runspec runspec (deck);
|
||||||
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_CHECK(deck.hasKeyword("WTRACER"));
|
BOOST_CHECK(deck.hasKeyword("WTRACER"));
|
||||||
|
|
||||||
const auto& keyword = deck["WTRACER"].back();
|
const auto& keyword = deck["WTRACER"].back();
|
||||||
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
||||||
|
|
||||||
const auto& record = keyword.getRecord(0);
|
const auto& record = keyword.getRecord(0);
|
||||||
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
||||||
BOOST_CHECK_EQUAL(well_name, "W_1");
|
BOOST_CHECK_EQUAL(well_name, "W_1");
|
||||||
@ -169,13 +194,13 @@ BOOST_AUTO_TEST_CASE(TestDynamicWTRACER) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestTracerInProducerTHROW) {
|
BOOST_AUTO_TEST_CASE(TestTracerInProducerTHROW)
|
||||||
auto deck = createDeckWithTracerInProducer();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithTracerInProducer();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table (deck);
|
||||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec ( deck );
|
const Runspec runspec (deck);
|
||||||
|
|
||||||
BOOST_CHECK_THROW(Schedule(deck, grid, fp, runspec, python), OpmInputError);
|
BOOST_CHECK_THROW(Schedule(deck, grid, fp, runspec, std::make_shared<Python>()), OpmInputError);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ COPY
|
|||||||
PERMX PERMZ /
|
PERMX PERMZ /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
DX
|
DX
|
||||||
1000*1 /
|
1000*1 /
|
||||||
|
@ -16,6 +16,9 @@ COPY
|
|||||||
PERMX PERMZ /
|
PERMX PERMZ /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
48000*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
WELSPECS
|
WELSPECS
|
||||||
|
@ -17,6 +17,9 @@ COPY
|
|||||||
PERMX PERMZ /
|
PERMX PERMZ /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
27000*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,6 +15,9 @@ COPY
|
|||||||
PERMX PERMZ /
|
PERMX PERMZ /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
27000*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ COPY
|
|||||||
PERMX PERMZ /
|
PERMX PERMZ /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
800*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ COPY
|
|||||||
PERMX PERMZ /
|
PERMX PERMZ /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
27000*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@ COPY
|
|||||||
PERMX PERMZ /
|
PERMX PERMZ /
|
||||||
/
|
/
|
||||||
|
|
||||||
|
PORO
|
||||||
|
72000*0.3 /
|
||||||
|
|
||||||
SCHEDULE
|
SCHEDULE
|
||||||
|
|
||||||
-- 0
|
-- 0
|
||||||
|
@ -518,34 +518,39 @@ BOOST_AUTO_TEST_CASE(WellTestWGRUPCONWellPropertiesSet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestDefaultedCOMPDATIJ) {
|
BOOST_AUTO_TEST_CASE(TestDefaultedCOMPDATIJ)
|
||||||
Parser parser;
|
{
|
||||||
const char * deckString = "\n\
|
const auto deck = Parser{}.parseString(R"(
|
||||||
START\n\
|
START
|
||||||
\n\
|
|
||||||
10 MAI 2007 /\n\
|
10 MAI 2007 /
|
||||||
\n\
|
|
||||||
GRID\n\
|
GRID
|
||||||
PERMX\n\
|
PERMX
|
||||||
9000*0.25 /\n\
|
9000*0.25 /
|
||||||
COPY \n\
|
COPY
|
||||||
PERMX PERMY /\n\
|
PERMX PERMY /
|
||||||
PERMX PERMZ /\n\
|
PERMX PERMZ /
|
||||||
/\n\
|
/
|
||||||
SCHEDULE\n\
|
PORO
|
||||||
WELSPECS \n\
|
9000*0.3 /
|
||||||
'W1' 'OP' 11 21 3.33 'OIL' 7* / \n\
|
|
||||||
/\n\
|
SCHEDULE
|
||||||
COMPDAT \n\
|
WELSPECS
|
||||||
'W1' 2* 1 1 'OPEN' 1* 32.948 0.311 3047.839 2* 'X' 22.100 /\n\
|
'W1' 'OP' 11 21 3.33 'OIL' 7* /
|
||||||
/\n";
|
/
|
||||||
auto deck = parser.parseString(deckString);
|
COMPDAT
|
||||||
auto python = std::make_shared<Python>();
|
'W1' 2* 1 1 'OPEN' 1* 32.948 0.311 3047.839 2* 'X' 22.100 /
|
||||||
EclipseGrid grid(30,30,10);
|
/
|
||||||
TableManager table ( deck );
|
END
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
)");
|
||||||
Runspec runspec (deck);
|
|
||||||
Schedule sched(deck, grid , fp, runspec, python);
|
const EclipseGrid grid(30,30,10);
|
||||||
|
const TableManager table (deck);
|
||||||
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
|
const Runspec runspec (deck);
|
||||||
|
const Schedule sched(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
const auto& connections = sched.getWell("W1", 0).getConnections();
|
const auto& connections = sched.getWell("W1", 0).getConnections();
|
||||||
BOOST_CHECK_EQUAL( 10 , connections.get(0).getI() );
|
BOOST_CHECK_EQUAL( 10 , connections.get(0).getI() );
|
||||||
BOOST_CHECK_EQUAL( 20 , connections.get(0).getJ() );
|
BOOST_CHECK_EQUAL( 20 , connections.get(0).getJ() );
|
||||||
@ -907,4 +912,3 @@ BOOST_AUTO_TEST_CASE(TestWellEvents) {
|
|||||||
BOOST_CHECK( sched[0].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
BOOST_CHECK( sched[0].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
||||||
BOOST_CHECK( sched[5].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
BOOST_CHECK( sched[5].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <opm/output/eclipse/AggregateMSWData.hpp>
|
#include <opm/output/eclipse/AggregateMSWData.hpp>
|
||||||
#include <opm/output/eclipse/AggregateWellData.hpp>
|
#include <opm/output/eclipse/AggregateWellData.hpp>
|
||||||
|
|
||||||
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/intehead.hpp>
|
#include <opm/output/eclipse/VectorItems/intehead.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/well.hpp>
|
#include <opm/output/eclipse/VectorItems/well.hpp>
|
||||||
@ -34,70 +35,100 @@
|
|||||||
|
|
||||||
#include <opm/output/data/Wells.hpp>
|
#include <opm/output/data/Wells.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
|
||||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Python/Python.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||||
#include <opm/input/eclipse/Python/Python.hpp>
|
|
||||||
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
|
||||||
#include <opm/common/utility/TimeService.hpp>
|
#include <opm/common/utility/TimeService.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct MockIH
|
namespace {
|
||||||
{
|
struct MockIH
|
||||||
MockIH(const int numWells,
|
{
|
||||||
|
MockIH(const int numWells,
|
||||||
|
const int nsegWell = 1, // E100
|
||||||
|
const int ncwMax = 20,
|
||||||
|
const int iConnPerConn = 25, // NICONZ
|
||||||
|
const int sConnPerConn = 41, // NSCONZ
|
||||||
|
const int xConnPerConn = 58); // NXCONZ
|
||||||
|
|
||||||
const int nsegWell = 1, // E100
|
std::vector<int> value;
|
||||||
const int ncwMax = 20,
|
|
||||||
const int iConnPerConn = 25, // NICONZ
|
|
||||||
const int sConnPerConn = 41, // NSCONZ
|
|
||||||
const int xConnPerConn = 58); // NXCONZ
|
|
||||||
|
|
||||||
|
using Sz = std::vector<int>::size_type;
|
||||||
|
|
||||||
std::vector<int> value;
|
Sz nwells;
|
||||||
|
Sz nsegwl;
|
||||||
|
Sz nsegmx;
|
||||||
|
Sz nswlmx;
|
||||||
|
Sz ncwmax;
|
||||||
|
Sz niconz;
|
||||||
|
Sz nsconz;
|
||||||
|
Sz nxconz;
|
||||||
|
};
|
||||||
|
|
||||||
using Sz = std::vector<int>::size_type;
|
MockIH::MockIH(const int numWells,
|
||||||
|
const int nsegWell,
|
||||||
|
const int ncwMax,
|
||||||
|
const int iConnPerConn,
|
||||||
|
const int sConnPerConn,
|
||||||
|
const int xConnPerConn)
|
||||||
|
: value(411, 0)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::intehead;
|
||||||
|
|
||||||
Sz nwells;
|
this->nwells = this->value[Ix::NWELLS] = numWells;
|
||||||
Sz nsegwl;
|
|
||||||
Sz nsegmx;
|
|
||||||
Sz nswlmx;
|
|
||||||
Sz ncwmax;
|
|
||||||
Sz niconz;
|
|
||||||
Sz nsconz;
|
|
||||||
Sz nxconz;
|
|
||||||
};
|
|
||||||
|
|
||||||
MockIH::MockIH(const int numWells,
|
this->nsegwl = this->value[Ix::NSEGWL] = nsegWell;
|
||||||
const int nsegWell,
|
this->ncwmax = this->value[Ix::NCWMAX] = ncwMax;
|
||||||
const int /* ncwMax */,
|
this->nswlmx = this->value[Ix::NSWLMX] = nsegWell;
|
||||||
const int iConnPerConn,
|
this->nsegmx = this->value[Ix::NSEGMX] = 32;
|
||||||
const int sConnPerConn,
|
this->niconz = this->value[Ix::NICONZ] = iConnPerConn;
|
||||||
const int xConnPerConn)
|
this->nsconz = this->value[Ix::NSCONZ] = sConnPerConn;
|
||||||
: value(411, 0)
|
this->nxconz = this->value[Ix::NXCONZ] = xConnPerConn;
|
||||||
{
|
}
|
||||||
using Ix = ::Opm::RestartIO::Helpers::VectorItems::intehead;
|
|
||||||
|
|
||||||
this->nwells = this->value[Ix::NWELLS] = numWells;
|
struct SimulationCase
|
||||||
|
{
|
||||||
|
explicit SimulationCase(const Opm::Deck& deck)
|
||||||
|
: es (deck)
|
||||||
|
, grid (deck)
|
||||||
|
, sched(deck, es, std::make_shared<Opm::Python>())
|
||||||
|
{}
|
||||||
|
|
||||||
this->nsegwl = this->value[Ix::NSEGWL] = nsegWell;
|
// Order requirement: 'es' must be declared/initialised before 'sched'.
|
||||||
this->ncwmax = this->value[Ix::NCWMAX] = 20;
|
Opm::EclipseState es;
|
||||||
this->nswlmx = this->value[Ix::NSWLMX] = 1;
|
Opm::EclipseGrid grid;
|
||||||
this->nsegmx = this->value[Ix::NSEGMX] = 32;
|
Opm::Schedule sched;
|
||||||
this->niconz = this->value[Ix::NICONZ] = iConnPerConn;
|
};
|
||||||
this->nsconz = this->value[Ix::NSCONZ] = sConnPerConn;
|
|
||||||
this->nxconz = this->value[Ix::NXCONZ] = xConnPerConn;
|
} // Anonymous namespace
|
||||||
}
|
|
||||||
|
// =====================================================================
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(Aggregate_ConnData)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Opm::Deck first_sim()
|
Opm::Deck first_sim()
|
||||||
{
|
{
|
||||||
// Mostly copy of tests/FIRST_SIM.DATA
|
// Mostly copy of tests/FIRST_SIM.DATA
|
||||||
@ -474,7 +505,8 @@ END
|
|||||||
return Opm::Parser{}.parseString(input);
|
return Opm::Parser{}.parseString(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Opm::data::Wells, Opm::SummaryState> wr(const Opm::Schedule& sched)
|
std::pair<Opm::data::Wells, Opm::SummaryState>
|
||||||
|
wr(const Opm::Schedule& sched)
|
||||||
{
|
{
|
||||||
using o = ::Opm::data::Rates::opt;
|
using o = ::Opm::data::Rates::opt;
|
||||||
|
|
||||||
@ -502,6 +534,7 @@ END
|
|||||||
c.pressure = 215.0;
|
c.pressure = 215.0;
|
||||||
c.index = connections[i].global_index();
|
c.index = connections[i].global_index();
|
||||||
c.trans_factor = connections[i].CF();
|
c.trans_factor = connections[i].CF();
|
||||||
|
c.compact_mult = 0.875;
|
||||||
|
|
||||||
const auto& global_index = connections[i].global_index();
|
const auto& global_index = connections[i].global_index();
|
||||||
sum_state.update_conn_var("PROD", "CWPR", global_index + 1, qw * (i + 1));
|
sum_state.update_conn_var("PROD", "CWPR", global_index + 1, qw * (i + 1));
|
||||||
@ -543,6 +576,7 @@ END
|
|||||||
c.pressure = 218.0;
|
c.pressure = 218.0;
|
||||||
c.index = connections[i].global_index();
|
c.index = connections[i].global_index();
|
||||||
c.trans_factor = connections[i].CF();
|
c.trans_factor = connections[i].CF();
|
||||||
|
c.compact_mult = 0.987;
|
||||||
|
|
||||||
const auto& global_index = connections[i].global_index();
|
const auto& global_index = connections[i].global_index();
|
||||||
sum_state.update_conn_var("WINJ", "CWIR", global_index+ 1, qw*(i + 1));
|
sum_state.update_conn_var("WINJ", "CWIR", global_index+ 1, qw*(i + 1));
|
||||||
@ -562,24 +596,8 @@ END
|
|||||||
|
|
||||||
return { std::move(xw), std::move(sum_state) };
|
return { std::move(xw), std::move(sum_state) };
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
struct SimulationCase {
|
} // Anonymous namespace
|
||||||
explicit SimulationCase(const Opm::Deck& deck)
|
|
||||||
: es (deck)
|
|
||||||
, grid (deck)
|
|
||||||
, sched(deck, es, std::make_shared<Opm::Python>())
|
|
||||||
{}
|
|
||||||
|
|
||||||
// Order requirement: 'es' must be declared/initialised before 'sched'.
|
|
||||||
Opm::EclipseState es;
|
|
||||||
Opm::EclipseGrid grid;
|
|
||||||
Opm::Schedule sched;
|
|
||||||
};
|
|
||||||
|
|
||||||
// =====================================================================
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(Aggregate_ConnData)
|
|
||||||
|
|
||||||
// test dimensions of Connection data
|
// test dimensions of Connection data
|
||||||
BOOST_AUTO_TEST_CASE (Constructor)
|
BOOST_AUTO_TEST_CASE (Constructor)
|
||||||
@ -683,40 +701,46 @@ BOOST_AUTO_TEST_CASE(Declared_Connection_Data)
|
|||||||
const auto& sconn = amconn.getSConn();
|
const auto& sconn = amconn.getSConn();
|
||||||
int connNo = 1;
|
int connNo = 1;
|
||||||
auto i0 = (connNo - 1) * ih.nsconz;
|
auto i0 = (connNo - 1) * ih.nsconz;
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::ConnTrans], 2.55826545, 1.0e-5); // PROD - conn 1 : Transmissibility factor
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffConnTrans], 2.55826545, 1.0e-5); // PROD - conn 1 : Effective transmissibility factor
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Depth], 7050., 1.0e-5); // PROD - conn 1 : Centre depth
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Depth], 7050., 1.0e-5); // PROD - conn 1 : Centre depth
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Diameter], 0.20, 1.0e-5); // PROD - conn 1 : diameter
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Diameter], 0.20, 1.0e-5); // PROD - conn 1 : diameter
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveKH], 1581.13879, 1.0e-5); // PROD - conn 1 : effective kh-product
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveKH], 1581.13879, 1.0e-5); // PROD - conn 1 : effective kh-product
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::item12], 2.55826545, 1.0e-5); // PROD - conn 1 : Transmissibility factor
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::CFDenom], 4.37696314, 1.0e-5);
|
||||||
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::ConnTrans], 2.55826545 / 0.875, 1.0e-5); // PROD - conn 1 : Transmissibility factor
|
||||||
BOOST_CHECK_CLOSE(
|
BOOST_CHECK_CLOSE(
|
||||||
sconn[i0 + Ix::SegDistEnd], 130., 1.0e-5); // PROD - conn 1 : Distance to end of connection in segment
|
sconn[i0 + Ix::SegDistEnd], 130., 1.0e-5); // PROD - conn 1 : Distance to end of connection in segment
|
||||||
BOOST_CHECK_CLOSE(
|
BOOST_CHECK_CLOSE(
|
||||||
sconn[i0 + Ix::SegDistStart], 30., 1.0e-5); // PROD - conn 1 : Distance to start of connection in segment
|
sconn[i0 + Ix::SegDistStart], 30., 1.0e-5); // PROD - conn 1 : Distance to start of connection in segment
|
||||||
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveLength], 100.0, 1.0e-5);
|
||||||
|
|
||||||
// Well no 2 - WINJ well
|
// Well no 2 - WINJ well
|
||||||
connNo = 3;
|
connNo = 3;
|
||||||
i0 = ih.ncwmax * ih.nsconz + (connNo - 1) * ih.nsconz;
|
i0 = ih.ncwmax * ih.nsconz + (connNo - 1) * ih.nsconz;
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::ConnTrans], 2.55826545, 1.0e-5); // WINJ - conn 3 : Transmissibility factor
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffConnTrans], 2.55826545, 1.0e-5); // WINJ - conn 3 : Effective transmissibility factor
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Depth], 7250., 1.0e-5); // WINJ - conn 3 : Centre depth
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Depth], 7250., 1.0e-5); // WINJ - conn 3 : Centre depth
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Diameter], 0.20, 1.0e-5); // WINJ - conn 3 : diameter
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Diameter], 0.20, 1.0e-5); // WINJ - conn 3 : diameter
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveKH], 1581.13879, 1.0e-5); // WINJ - conn 3 : effective kh-product
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveKH], 1581.13879, 1.0e-5); // WINJ - conn 3 : effective kh-product
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::item12], 2.55826545, 1.0e-5); // WINJ - conn 3 : Transmissibility factor
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::CFDenom], 4.37696314, 1.0e-5);
|
||||||
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::ConnTrans], 2.55826545 / 0.987, 1.0e-5); // WINJ - conn 3 : Transmissibility factor
|
||||||
BOOST_CHECK_CLOSE(
|
BOOST_CHECK_CLOSE(
|
||||||
sconn[i0 + Ix::SegDistEnd], 0., 1.0e-5); // WINJ - conn 3 : Distance to end of connection in segment
|
sconn[i0 + Ix::SegDistEnd], 0., 1.0e-5); // WINJ - conn 3 : Distance to end of connection in segment
|
||||||
BOOST_CHECK_CLOSE(
|
BOOST_CHECK_CLOSE(
|
||||||
sconn[i0 + Ix::SegDistStart], 0., 1.0e-5); // WINJ - conn 3 : Distance to start of connection in segment
|
sconn[i0 + Ix::SegDistStart], 0., 1.0e-5); // WINJ - conn 3 : Distance to start of connection in segment
|
||||||
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveLength], 100.0, 1.0e-5);
|
||||||
|
|
||||||
connNo = 4;
|
connNo = 4;
|
||||||
i0 = ih.ncwmax * ih.nsconz + (connNo - 1) * ih.nsconz;
|
i0 = ih.ncwmax * ih.nsconz + (connNo - 1) * ih.nsconz;
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::ConnTrans], 2.55826545, 1.0e-5); // WINJ - conn 4 : Transmissibility factor
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffConnTrans], 2.55826545, 1.0e-5); // WINJ - conn 4 : Effective transmissibility factor
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Depth], 7250., 1.0e-5); // WINJ - conn 4 : Centre depth
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Depth], 7250., 1.0e-5); // WINJ - conn 4 : Centre depth
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Diameter], 0.20, 1.0e-5); // WINJ - conn 4 : diameter
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::Diameter], 0.20, 1.0e-5); // WINJ - conn 4 : diameter
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveKH], 1581.13879, 1.0e-5); // WINJ - conn 4 : effective kh-product
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveKH], 1581.13879, 1.0e-5); // WINJ - conn 4 : effective kh-product
|
||||||
BOOST_CHECK_CLOSE(sconn[i0 + Ix::item12], 2.55826545, 1.0e-5); // WINJ - conn 4 : Transmissibility factor
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::CFDenom], 4.37696314, 1.0e-5);
|
||||||
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::ConnTrans], 2.55826545 / 0.987, 1.0e-5); // WINJ - conn 4 : Transmissibility factor
|
||||||
BOOST_CHECK_CLOSE(
|
BOOST_CHECK_CLOSE(
|
||||||
sconn[i0 + Ix::SegDistEnd], 0., 1.0e-5); // WINJ - conn 4 : Distance to end of connection in segment
|
sconn[i0 + Ix::SegDistEnd], 0., 1.0e-5); // WINJ - conn 4 : Distance to end of connection in segment
|
||||||
BOOST_CHECK_CLOSE(
|
BOOST_CHECK_CLOSE(
|
||||||
sconn[i0 + Ix::SegDistStart], 0., 1.0e-5); // WINJ - conn 4 : Distance to start of connection in segment
|
sconn[i0 + Ix::SegDistStart], 0., 1.0e-5); // WINJ - conn 4 : Distance to start of connection in segment
|
||||||
|
BOOST_CHECK_CLOSE(sconn[i0 + Ix::EffectiveLength], 100.0, 1.0e-5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XCONN (PROD) + (WINJ)
|
// XCONN (PROD) + (WINJ)
|
||||||
@ -808,10 +832,12 @@ BOOST_AUTO_TEST_CASE(Declared_Connection_Data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(InactiveCell) {
|
BOOST_AUTO_TEST_CASE(InactiveCell)
|
||||||
|
{
|
||||||
auto simCase = SimulationCase{first_sim()};
|
auto simCase = SimulationCase{first_sim()};
|
||||||
const auto rptStep = std::size_t{1};
|
const auto rptStep = std::size_t{1};
|
||||||
const auto ih = MockIH {static_cast<int>(simCase.sched.getWells(rptStep).size())};
|
const auto ih = MockIH {static_cast<int>(simCase.sched.getWells(rptStep).size())};
|
||||||
|
|
||||||
const auto& [wrc, sum_state] = wr(simCase.sched);
|
const auto& [wrc, sum_state] = wr(simCase.sched);
|
||||||
auto conn0 = Opm::RestartIO::Helpers::AggregateConnectionData{ih.value};
|
auto conn0 = Opm::RestartIO::Helpers::AggregateConnectionData{ih.value};
|
||||||
conn0.captureDeclaredConnData(simCase.sched,
|
conn0.captureDeclaredConnData(simCase.sched,
|
||||||
@ -819,11 +845,10 @@ BOOST_AUTO_TEST_CASE(InactiveCell) {
|
|||||||
simCase.es.getUnits(),
|
simCase.es.getUnits(),
|
||||||
wrc,
|
wrc,
|
||||||
sum_state,
|
sum_state,
|
||||||
rptStep
|
rptStep);
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<int> actnum(500, 1);
|
|
||||||
// Here we deactive the cell holding connection number 2.
|
// Here we deactive the cell holding connection number 2.
|
||||||
|
std::vector<int> actnum(500, 1);
|
||||||
actnum[simCase.grid.getGlobalIndex(2,4,1)] = 0;
|
actnum[simCase.grid.getGlobalIndex(2,4,1)] = 0;
|
||||||
simCase.grid.resetACTNUM(actnum);
|
simCase.grid.resetACTNUM(actnum);
|
||||||
|
|
||||||
@ -833,62 +858,330 @@ BOOST_AUTO_TEST_CASE(InactiveCell) {
|
|||||||
simCase.es.getUnits(),
|
simCase.es.getUnits(),
|
||||||
wrc,
|
wrc,
|
||||||
sum_state,
|
sum_state,
|
||||||
rptStep
|
rptStep);
|
||||||
);
|
|
||||||
|
|
||||||
const std::size_t num_test_connections = 4;
|
const std::size_t num_test_connections = 4;
|
||||||
|
|
||||||
{
|
using IC = ::Opm::RestartIO::Helpers::VectorItems::IConn::index;
|
||||||
using IC = ::Opm::RestartIO::Helpers::VectorItems::IConn::index;
|
|
||||||
const auto iconn0 = conn0.getIConn();
|
|
||||||
const auto iconn1 = conn1.getIConn();
|
|
||||||
for (std::size_t conn_index = 0; conn_index < num_test_connections; conn_index++) {
|
|
||||||
std::size_t offset1 = conn_index * ih.niconz;
|
|
||||||
std::size_t offset0 = offset1;
|
|
||||||
|
|
||||||
if (conn_index >= 2)
|
const auto iconn0 = conn0.getIConn();
|
||||||
offset0 += ih.niconz;
|
const auto iconn1 = conn1.getIConn();
|
||||||
|
|
||||||
for (std::size_t elm_index = 0; elm_index < ih.niconz; elm_index++) {
|
for (std::size_t conn_index = 0; conn_index < num_test_connections; ++conn_index) {
|
||||||
if (elm_index == IC::SeqIndex && conn_index >= 2) {
|
const std::size_t offset1 = conn_index * ih.niconz;
|
||||||
// Comparing the connection ID - which should be different;
|
const std::size_t offset0 = offset1 + (conn_index >= 2)*ih.niconz;
|
||||||
BOOST_CHECK_EQUAL(iconn1[offset1 + elm_index] + 1 , iconn0[offset0 + elm_index]);
|
|
||||||
} else
|
for (std::size_t elm_index = 0; elm_index < ih.niconz; ++elm_index) {
|
||||||
BOOST_CHECK_EQUAL(iconn1[offset1 + elm_index], iconn0[offset0 + elm_index]);
|
if (elm_index == IC::SeqIndex && conn_index >= 2) {
|
||||||
|
// Comparing the connection ID - which should be different;
|
||||||
|
BOOST_CHECK_EQUAL(iconn1[offset1 + elm_index] + 1,
|
||||||
|
iconn0[offset0 + elm_index]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BOOST_CHECK_EQUAL(iconn1[offset1 + elm_index],
|
||||||
|
iconn0[offset0 + elm_index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto sconn0 = conn0.getSConn();
|
const auto sconn0 = conn0.getSConn();
|
||||||
const auto sconn1 = conn1.getSConn();
|
const auto sconn1 = conn1.getSConn();
|
||||||
for (std::size_t conn_index = 0; conn_index < num_test_connections; conn_index++) {
|
|
||||||
std::size_t offset1 = conn_index * ih.nsconz;
|
|
||||||
std::size_t offset0 = offset1;
|
|
||||||
|
|
||||||
if (conn_index >= 2)
|
for (std::size_t conn_index = 0; conn_index < num_test_connections; ++conn_index) {
|
||||||
offset0 += ih.nsconz;
|
const std::size_t offset1 = conn_index * ih.nsconz;
|
||||||
|
const std::size_t offset0 = offset1 + (conn_index >= 2)*ih.nsconz;
|
||||||
|
|
||||||
for (std::size_t elm_index = 0; elm_index < ih.nsconz; elm_index++)
|
for (std::size_t elm_index = 0; elm_index < ih.nsconz; ++elm_index) {
|
||||||
BOOST_CHECK_EQUAL(sconn1[offset1 + elm_index], sconn0[offset0 + elm_index]);
|
BOOST_CHECK_EQUAL(sconn1[offset1 + elm_index],
|
||||||
|
sconn0[offset0 + elm_index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto xconn0 = conn0.getXConn();
|
const auto xconn0 = conn0.getXConn();
|
||||||
const auto xconn1 = conn1.getXConn();
|
const auto xconn1 = conn1.getXConn();
|
||||||
for (std::size_t conn_index = 0; conn_index < num_test_connections; conn_index++) {
|
|
||||||
|
for (std::size_t conn_index = 0; conn_index < num_test_connections; ++conn_index) {
|
||||||
std::size_t offset1 = conn_index * ih.nxconz;
|
std::size_t offset1 = conn_index * ih.nxconz;
|
||||||
std::size_t offset0 = offset1;
|
std::size_t offset0 = offset1;
|
||||||
|
|
||||||
if (conn_index >= 2)
|
if (conn_index >= 2) {
|
||||||
offset0 += ih.nxconz;
|
offset0 += ih.nxconz;
|
||||||
|
}
|
||||||
|
|
||||||
for (std::size_t elm_index = 0; elm_index < ih.nxconz; elm_index++)
|
for (std::size_t elm_index = 0; elm_index < ih.nxconz; ++elm_index) {
|
||||||
BOOST_CHECK_EQUAL(xconn1[offset1 + elm_index], xconn0[offset0 + elm_index]);
|
BOOST_CHECK_EQUAL(xconn1[offset1 + elm_index],
|
||||||
|
xconn0[offset0 + elm_index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END() // Aggregate_ConnData
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(DFactor_Correlation)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
SimulationCase wdfaccorCase()
|
||||||
|
{
|
||||||
|
return SimulationCase { Opm::Parser{}.parseString(R"(
|
||||||
|
DIMENS
|
||||||
|
10 10 10 /
|
||||||
|
|
||||||
|
START -- 0
|
||||||
|
19 JUN 2007 /
|
||||||
|
|
||||||
|
GRID
|
||||||
|
|
||||||
|
DXV
|
||||||
|
10*100.0 /
|
||||||
|
DYV
|
||||||
|
10*100.0 /
|
||||||
|
DZV
|
||||||
|
10*10.0 /
|
||||||
|
DEPTHZ
|
||||||
|
121*2000.0 /
|
||||||
|
|
||||||
|
PORO
|
||||||
|
1000*0.1 /
|
||||||
|
PERMX
|
||||||
|
1000*1 /
|
||||||
|
PERMY
|
||||||
|
1000*0.1 /
|
||||||
|
PERMZ
|
||||||
|
1000*0.01 /
|
||||||
|
|
||||||
|
SCHEDULE
|
||||||
|
|
||||||
|
DATES -- 1
|
||||||
|
10 OKT 2008 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WELSPECS
|
||||||
|
'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' /
|
||||||
|
'W2' 'G2' 5 5 1 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' /
|
||||||
|
/
|
||||||
|
|
||||||
|
COMPDAT
|
||||||
|
'W1' 3 3 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
||||||
|
'W2' 3 3 2 2 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WDFACCOR
|
||||||
|
'W2' 1.984e-7 -1.1045 0.0 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONINJE
|
||||||
|
'W1' 'WATER' 'OPEN' 'RATE' 4000.0 1* 850.0 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONPROD
|
||||||
|
'W2' 'OPEN' 'ORAT' 5000.0 4* 20.0 /
|
||||||
|
/
|
||||||
|
|
||||||
|
DATES -- 2
|
||||||
|
12 NOV 2008 /
|
||||||
|
/
|
||||||
|
|
||||||
|
END
|
||||||
|
)") };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Opm::data::Wells, Opm::SummaryState>
|
||||||
|
dynamicState(const Opm::Schedule& sched)
|
||||||
|
{
|
||||||
|
auto dyn_state = std::pair<Opm::data::Wells, Opm::SummaryState> {
|
||||||
|
std::piecewise_construct,
|
||||||
|
std::forward_as_tuple(),
|
||||||
|
std::forward_as_tuple(Opm::TimeService::now())
|
||||||
|
};
|
||||||
|
|
||||||
|
using o = ::Opm::data::Rates::opt;
|
||||||
|
|
||||||
|
auto& [xw, sum_state] = dyn_state;
|
||||||
|
|
||||||
|
const double qv = 12.34*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day;
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto wname = std::string { "W2" };
|
||||||
|
|
||||||
|
xw[wname].rates.set(o::wat, 1.0).set(o::oil, 2.0).set(o::gas, 3.0);
|
||||||
|
xw[wname].bhp = 213.0*Opm::unit::barsa;
|
||||||
|
|
||||||
|
{
|
||||||
|
const double qw = 4.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day;
|
||||||
|
const double qo = 5.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day;
|
||||||
|
const double qg = 50.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day;
|
||||||
|
|
||||||
|
const auto& well = sched.getWell(wname, 1);
|
||||||
|
const auto& connections = well.getConnections();
|
||||||
|
for (auto i = 0*connections.size(); i < connections.size(); ++i) {
|
||||||
|
auto& c = xw[wname].connections.emplace_back();
|
||||||
|
|
||||||
|
c.rates
|
||||||
|
.set(o::wat, qw * (float(i) + 1.0)*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day)
|
||||||
|
.set(o::oil, qo * (float(i) + 1.0)*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day)
|
||||||
|
.set(o::gas, qg * (float(i) + 1.0)*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day);
|
||||||
|
c.pressure = 215.0*Opm::unit::barsa;
|
||||||
|
c.index = connections[i].global_index();
|
||||||
|
c.trans_factor = connections[i].CF();
|
||||||
|
c.cell_pressure = 200.0*Opm::unit::barsa;
|
||||||
|
c.cell_saturation_water = 0.55;
|
||||||
|
c.cell_saturation_gas =.038;
|
||||||
|
c.effective_Kh = 100*Opm::prefix::milli*Opm::unit::darcy*Opm::unit::meter;
|
||||||
|
c.d_factor = 3.0e-6*Opm::unit::day/Opm::unit::cubic(Opm::unit::meter);
|
||||||
|
c.compact_mult = 0.875;
|
||||||
|
|
||||||
|
const auto& global_index = connections[i].global_index();
|
||||||
|
sum_state.update_conn_var(wname, "CWPR", global_index + 1, qw * (i + 1));
|
||||||
|
sum_state.update_conn_var(wname, "COPR", global_index + 1, qo * (i + 1));
|
||||||
|
sum_state.update_conn_var(wname, "CGPR", global_index + 1, qg * (i + 1));
|
||||||
|
sum_state.update_conn_var(wname, "CVPR", global_index + 1, qv * (i + 1));
|
||||||
|
|
||||||
|
sum_state.update_conn_var(wname, "COPT", global_index + 1, qo * (i + 1) * 2.0);
|
||||||
|
sum_state.update_conn_var(wname, "CWPT", global_index + 1, qw * (i + 1) * 2.0);
|
||||||
|
sum_state.update_conn_var(wname, "CGPT", global_index + 1, qg * (i + 1) * 2.0);
|
||||||
|
sum_state.update_conn_var(wname, "CVPT", global_index + 1, qv * (i + 1) * 2.0);
|
||||||
|
|
||||||
|
sum_state.update_conn_var(wname, "CGOR", global_index + 1, qg / qo);
|
||||||
|
|
||||||
|
sum_state.update_conn_var(wname, "CPR", global_index + 1, 215.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto wname = std::string { "W1" };
|
||||||
|
|
||||||
|
const auto& well = sched.getWell(wname, 1);
|
||||||
|
const auto& connections = well.getConnections();
|
||||||
|
|
||||||
|
xw[wname].bhp = 234.0*Opm::unit::barsa;
|
||||||
|
xw[wname].rates
|
||||||
|
.set(o::wat, 5.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day)
|
||||||
|
.set(o::oil, 0.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day)
|
||||||
|
.set(o::gas, 0.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day);
|
||||||
|
|
||||||
|
const double qw = 7.0;
|
||||||
|
for (auto i = 0*connections.size(); i < connections.size(); ++i) {
|
||||||
|
xw[wname].connections.emplace_back();
|
||||||
|
auto& c = xw[wname].connections.back();
|
||||||
|
|
||||||
|
c.rates.set(o::wat, qw * (float(i) + 1.0)).set(o::oil, 0.0).set(o::gas, 0.0);
|
||||||
|
c.pressure = 218.0*Opm::unit::barsa;
|
||||||
|
c.index = connections[i].global_index();
|
||||||
|
c.trans_factor = connections[i].CF();
|
||||||
|
c.cell_pressure = 230.0*Opm::unit::barsa;
|
||||||
|
c.cell_saturation_water = 0.15;
|
||||||
|
c.cell_saturation_gas = 0.50;
|
||||||
|
c.effective_Kh = 100*Opm::prefix::milli*Opm::unit::darcy*Opm::unit::meter;
|
||||||
|
c.d_factor = 3.0e-6*Opm::unit::day/Opm::unit::cubic(Opm::unit::meter);
|
||||||
|
c.compact_mult = 0.987;
|
||||||
|
|
||||||
|
const auto& global_index = connections[i].global_index();
|
||||||
|
sum_state.update_conn_var(wname, "CWIR", global_index+ 1, qw*(i + 1));
|
||||||
|
sum_state.update_conn_var(wname, "COIR", global_index+ 1, 0.0);
|
||||||
|
sum_state.update_conn_var(wname, "CGIR", global_index+ 1, 0.0);
|
||||||
|
sum_state.update_conn_var(wname, "CVIR", global_index+ 1, qv*(i + 1));
|
||||||
|
|
||||||
|
sum_state.update_conn_var(wname, "COIT", global_index + 1, 543.21 * (i + 1));
|
||||||
|
sum_state.update_conn_var(wname, "CWIT", global_index + 1, qw * (i + 1) * 2.0);
|
||||||
|
sum_state.update_conn_var(wname, "CGIT", global_index + 1, 9876.54 * (i + 1));
|
||||||
|
sum_state.update_conn_var(wname, "CVIT", global_index + 1, qv * (i + 1) * 2.0);
|
||||||
|
|
||||||
|
sum_state.update_conn_var(wname, "CPR", global_index + 1, 218.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dyn_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(Basic)
|
||||||
|
{
|
||||||
|
const auto cse = wdfaccorCase();
|
||||||
|
|
||||||
|
const auto ih = MockIH { 2, 0, 1 };
|
||||||
|
|
||||||
|
const auto& [wrc, sum_state] = dynamicState(cse.sched);
|
||||||
|
|
||||||
|
auto amconn = Opm::RestartIO::Helpers::AggregateConnectionData {ih.value};
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto rptStep = std::size_t {0};
|
||||||
|
|
||||||
|
amconn.captureDeclaredConnData(cse.sched,
|
||||||
|
cse.grid,
|
||||||
|
cse.es.getUnits(),
|
||||||
|
wrc, sum_state, rptStep);
|
||||||
|
|
||||||
|
// W1 (injector)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SConn::index;
|
||||||
|
const auto& sconn = amconn.getSConn();
|
||||||
|
|
||||||
|
const auto wellNo = 1;
|
||||||
|
const auto connNo = 1;
|
||||||
|
const auto wellStart = (wellNo - 1) * ih.ncwmax * ih.nsconz;
|
||||||
|
const auto start = wellStart + (connNo - 1) * ih.nsconz;
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE(sconn[start + Ix::StaticDFacCorrCoeff], 0.0, 1.0e-7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// W2 (producer)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SConn::index;
|
||||||
|
const auto& sconn = amconn.getSConn();
|
||||||
|
|
||||||
|
const auto wellNo = 2;
|
||||||
|
const auto connNo = 1;
|
||||||
|
const auto wellStart = (wellNo - 1) * ih.ncwmax * ih.nsconz;
|
||||||
|
const auto start = wellStart + (connNo - 1)*ih.nsconz;
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE(sconn[start + Ix::StaticDFacCorrCoeff], 0.0, 1.0e-7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto rptStep = std::size_t {1};
|
||||||
|
|
||||||
|
amconn.captureDeclaredConnData(cse.sched,
|
||||||
|
cse.grid,
|
||||||
|
cse.es.getUnits(),
|
||||||
|
wrc, sum_state, rptStep);
|
||||||
|
|
||||||
|
// W1 (injector)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SConn::index;
|
||||||
|
const auto& sconn = amconn.getSConn();
|
||||||
|
|
||||||
|
const auto wellNo = 1;
|
||||||
|
const auto connNo = 1;
|
||||||
|
const auto wellStart = (wellNo - 1) * ih.ncwmax * ih.nsconz;
|
||||||
|
const auto start = wellStart + (connNo - 1) * ih.nsconz;
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE(sconn[start + Ix::StaticDFacCorrCoeff], 0.0, 1.0e-7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// W2 (producer)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SConn::index;
|
||||||
|
const auto& sconn = amconn.getSConn();
|
||||||
|
|
||||||
|
const auto wellNo = 2;
|
||||||
|
const auto connNo = 1;
|
||||||
|
const auto wellStart = (wellNo - 1) * ih.ncwmax * ih.nsconz;
|
||||||
|
const auto start = wellStart + (connNo - 1)*ih.nsconz;
|
||||||
|
|
||||||
|
BOOST_CHECK_CLOSE(sconn[start + Ix::StaticDFacCorrCoeff], 1.89919365e-11, 1.0e-7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END() // DFactor_Correlation
|
||||||
|
@ -51,6 +51,8 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellTestState.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellTestState.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
|
|
||||||
@ -64,42 +66,65 @@
|
|||||||
|
|
||||||
#include "tests/WorkArea.hpp"
|
#include "tests/WorkArea.hpp"
|
||||||
|
|
||||||
struct MockIH
|
namespace {
|
||||||
{
|
|
||||||
MockIH(const int numWells,
|
|
||||||
const int iwelPerWell = 155, // E100
|
|
||||||
const int swelPerWell = 122, // E100
|
|
||||||
const int xwelPerWell = 130, // E100
|
|
||||||
const int zwelPerWell = 3); // E100
|
|
||||||
|
|
||||||
std::vector<int> value;
|
struct MockIH
|
||||||
|
{
|
||||||
|
MockIH(const int numWells,
|
||||||
|
const int iwelPerWell = 155, // E100
|
||||||
|
const int swelPerWell = 122, // E100
|
||||||
|
const int xwelPerWell = 130, // E100
|
||||||
|
const int zwelPerWell = 3); // E100
|
||||||
|
|
||||||
using Sz = std::vector<int>::size_type;
|
std::vector<int> value;
|
||||||
|
|
||||||
Sz nwells;
|
using Sz = std::vector<int>::size_type;
|
||||||
Sz niwelz;
|
|
||||||
Sz nswelz;
|
|
||||||
Sz nxwelz;
|
|
||||||
Sz nzwelz;
|
|
||||||
};
|
|
||||||
|
|
||||||
MockIH::MockIH(const int numWells,
|
Sz nwells;
|
||||||
const int iwelPerWell,
|
Sz niwelz;
|
||||||
const int swelPerWell,
|
Sz nswelz;
|
||||||
const int xwelPerWell,
|
Sz nxwelz;
|
||||||
const int zwelPerWell)
|
Sz nzwelz;
|
||||||
: value(411, 0)
|
};
|
||||||
{
|
|
||||||
using Ix = ::Opm::RestartIO::Helpers::VectorItems::intehead;
|
|
||||||
|
|
||||||
this->nwells = this->value[Ix::NWELLS] = numWells;
|
MockIH::MockIH(const int numWells,
|
||||||
this->niwelz = this->value[Ix::NIWELZ] = iwelPerWell;
|
const int iwelPerWell,
|
||||||
this->nswelz = this->value[Ix::NSWELZ] = swelPerWell;
|
const int swelPerWell,
|
||||||
this->nxwelz = this->value[Ix::NXWELZ] = xwelPerWell;
|
const int xwelPerWell,
|
||||||
this->nzwelz = this->value[Ix::NZWELZ] = zwelPerWell;
|
const int zwelPerWell)
|
||||||
}
|
: value(411, 0)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::intehead;
|
||||||
|
|
||||||
|
this->nwells = this->value[Ix::NWELLS] = numWells;
|
||||||
|
this->niwelz = this->value[Ix::NIWELZ] = iwelPerWell;
|
||||||
|
this->nswelz = this->value[Ix::NSWELZ] = swelPerWell;
|
||||||
|
this->nxwelz = this->value[Ix::NXWELZ] = xwelPerWell;
|
||||||
|
this->nzwelz = this->value[Ix::NZWELZ] = zwelPerWell;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SimulationCase
|
||||||
|
{
|
||||||
|
explicit SimulationCase(const Opm::Deck& deck)
|
||||||
|
: es { deck }
|
||||||
|
, grid { deck }
|
||||||
|
, sched{ deck, es, std::make_shared<Opm::Python>() }
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Order requirement: 'es' must be declared/initialised before 'sched'.
|
||||||
|
Opm::EclipseState es;
|
||||||
|
Opm::EclipseGrid grid;
|
||||||
|
Opm::Schedule sched;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(Aggregate_WD)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
Opm::Deck first_sim()
|
Opm::Deck first_sim()
|
||||||
{
|
{
|
||||||
// Mostly copy of tests/FIRST_SIM.DATA
|
// Mostly copy of tests/FIRST_SIM.DATA
|
||||||
@ -817,25 +842,8 @@ TSTEP -- 3
|
|||||||
|
|
||||||
return xw;
|
return xw;
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
struct SimulationCase
|
} // Anonymous namespace
|
||||||
{
|
|
||||||
explicit SimulationCase(const Opm::Deck& deck)
|
|
||||||
: es { deck }
|
|
||||||
, grid { deck }
|
|
||||||
, sched{ deck, es, std::make_shared<Opm::Python>() }
|
|
||||||
{}
|
|
||||||
|
|
||||||
// Order requirement: 'es' must be declared/initialised before 'sched'.
|
|
||||||
Opm::EclipseState es;
|
|
||||||
Opm::EclipseGrid grid;
|
|
||||||
Opm::Schedule sched;
|
|
||||||
};
|
|
||||||
|
|
||||||
// =====================================================================
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(Aggregate_WD)
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE (Constructor)
|
BOOST_AUTO_TEST_CASE (Constructor)
|
||||||
{
|
{
|
||||||
@ -1822,3 +1830,157 @@ BOOST_AUTO_TEST_CASE(WELL_POD)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(Extra_Effects)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
SimulationCase wdfaccorCase()
|
||||||
|
{
|
||||||
|
return SimulationCase { Opm::Parser{}.parseString(R"~(
|
||||||
|
DIMENS
|
||||||
|
10 10 10 /
|
||||||
|
|
||||||
|
START -- 0
|
||||||
|
19 JUN 2007 /
|
||||||
|
|
||||||
|
GRID
|
||||||
|
|
||||||
|
DXV
|
||||||
|
10*100.0 /
|
||||||
|
DYV
|
||||||
|
10*100.0 /
|
||||||
|
DZV
|
||||||
|
10*10.0 /
|
||||||
|
DEPTHZ
|
||||||
|
121*2000.0 /
|
||||||
|
|
||||||
|
PORO
|
||||||
|
1000*0.1 /
|
||||||
|
PERMX
|
||||||
|
1000*1 /
|
||||||
|
PERMY
|
||||||
|
1000*0.1 /
|
||||||
|
PERMZ
|
||||||
|
1000*0.01 /
|
||||||
|
|
||||||
|
SCHEDULE
|
||||||
|
|
||||||
|
DATES -- 1
|
||||||
|
10 OKT 2008 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WELSPECS
|
||||||
|
'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' /
|
||||||
|
'W2' 'G2' 5 5 1 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' /
|
||||||
|
/
|
||||||
|
|
||||||
|
COMPDAT
|
||||||
|
'W1' 3 3 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
||||||
|
'W2' 3 3 2 2 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WDFACCOR
|
||||||
|
'W2' 1.984e-7 -1.1045 0.0 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONINJE
|
||||||
|
'W1' 'WATER' 'OPEN' 'RATE' 4000.0 1* 850.0 /
|
||||||
|
/
|
||||||
|
|
||||||
|
WCONPROD
|
||||||
|
'W2' 'OPEN' 'ORAT' 5000.0 4* 20.0 /
|
||||||
|
/
|
||||||
|
|
||||||
|
DATES -- 2
|
||||||
|
12 NOV 2008 /
|
||||||
|
/
|
||||||
|
|
||||||
|
END
|
||||||
|
)~") };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Opm::data::Wells, Opm::SummaryState>
|
||||||
|
dynamicStateWDFacCorr(const Opm::Schedule& sched)
|
||||||
|
{
|
||||||
|
auto dyn_state = std::pair<Opm::data::Wells, Opm::SummaryState> {
|
||||||
|
std::piecewise_construct,
|
||||||
|
std::forward_as_tuple(),
|
||||||
|
std::forward_as_tuple(Opm::TimeService::now())
|
||||||
|
};
|
||||||
|
|
||||||
|
using o = ::Opm::data::Rates::opt;
|
||||||
|
|
||||||
|
auto& [xw, sum_state] = dyn_state;
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto wname = std::string { "W2" };
|
||||||
|
|
||||||
|
xw[wname].rates.set(o::wat, 1.0).set(o::oil, 2.0).set(o::gas, 3.0);
|
||||||
|
xw[wname].bhp = 213.0*Opm::unit::barsa;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto wname = std::string { "W1" };
|
||||||
|
|
||||||
|
xw[wname].bhp = 234.0*Opm::unit::barsa;
|
||||||
|
xw[wname].rates
|
||||||
|
.set(o::wat, 5.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day)
|
||||||
|
.set(o::oil, 0.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day)
|
||||||
|
.set(o::gas, 0.0*Opm::unit::cubic(Opm::unit::meter)/Opm::unit::day);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dyn_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(WdFac_Correlation)
|
||||||
|
{
|
||||||
|
const auto cse = wdfaccorCase();
|
||||||
|
const auto& [xw, smry] = dynamicStateWDFacCorr(cse.sched);
|
||||||
|
|
||||||
|
const auto ih = MockIH{ 2 };
|
||||||
|
|
||||||
|
const auto action_state = Opm::Action::State{};
|
||||||
|
const auto wtest_state = Opm::WellTestState{};
|
||||||
|
|
||||||
|
const auto rptStep = std::size_t{1};
|
||||||
|
|
||||||
|
auto awd = Opm::RestartIO::Helpers::AggregateWellData{ ih.value };
|
||||||
|
awd.captureDeclaredWellData(cse.sched,
|
||||||
|
cse.es.tracer(),
|
||||||
|
rptStep,
|
||||||
|
action_state,
|
||||||
|
wtest_state,
|
||||||
|
smry,
|
||||||
|
ih.value);
|
||||||
|
|
||||||
|
// W1 (injector)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SWell::index;
|
||||||
|
|
||||||
|
const auto i1 = 0*ih.nswelz;
|
||||||
|
|
||||||
|
const auto& swell = awd.getSWell();
|
||||||
|
BOOST_CHECK_CLOSE(swell[i1 + Ix::DFacCorrCoeffA], 0.0f, 1.0e-7f);
|
||||||
|
BOOST_CHECK_CLOSE(swell[i1 + Ix::DFacCorrExpB] , 0.0f, 1.0e-7f);
|
||||||
|
BOOST_CHECK_CLOSE(swell[i1 + Ix::DFacCorrExpC] , 0.0f, 1.0e-7f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// W2 (producer)
|
||||||
|
{
|
||||||
|
using Ix = ::Opm::RestartIO::Helpers::VectorItems::SWell::index;
|
||||||
|
|
||||||
|
const auto i1 = 1*ih.nswelz;
|
||||||
|
|
||||||
|
const auto& swell = awd.getSWell();
|
||||||
|
BOOST_CHECK_CLOSE(swell[i1 + Ix::DFacCorrCoeffA], 1.984e-7f, 1.0e-7f);
|
||||||
|
BOOST_CHECK_CLOSE(swell[i1 + Ix::DFacCorrExpB] , -1.1045f , 1.0e-7f);
|
||||||
|
BOOST_CHECK_CLOSE(swell[i1 + Ix::DFacCorrExpC] , 0.0f , 1.0e-7f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END() // Extra_Effects
|
||||||
|
@ -57,12 +57,22 @@ namespace {
|
|||||||
const auto j = (dims[1] - 1) - 1;
|
const auto j = (dims[1] - 1) - 1;
|
||||||
|
|
||||||
for (auto k = top; k < static_cast<int>(dims.size()); ++k) {
|
for (auto k = top; k < static_cast<int>(dims.size()); ++k) {
|
||||||
|
const auto depth = 2000 + (2*k + 1) / static_cast<double>(2);
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
ctf_props.CF = k / 100.0;
|
||||||
|
ctf_props.Kh = 1.0;
|
||||||
|
ctf_props.Ke = 1.0;
|
||||||
|
ctf_props.rw = 1.0;
|
||||||
|
ctf_props.r0 = 0.5;
|
||||||
|
ctf_props.re = 0.5;
|
||||||
|
ctf_props.connection_length = 1.0;
|
||||||
|
|
||||||
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k,
|
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k,
|
||||||
2000 + (2*k + 1) / static_cast<double>(2),
|
|
||||||
Opm::Connection::State::OPEN,
|
Opm::Connection::State::OPEN,
|
||||||
k / 100.0, 1.0, 1.0, 0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 0,
|
|
||||||
Opm::Connection::Direction::Z,
|
Opm::Connection::Direction::Z,
|
||||||
Opm::Connection::CTFKind::DeckValue, k, false);
|
Opm::Connection::CTFKind::DeckValue,
|
||||||
|
0, depth, ctf_props, k, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Opm::Connection::Order::INPUT, i, j, conns };
|
return { Opm::Connection::Order::INPUT, i, j, conns };
|
||||||
@ -87,18 +97,28 @@ namespace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (auto k = topConn; k < kMax; ++k) {
|
for (auto k = topConn; k < kMax; ++k) {
|
||||||
|
const auto depth = 2000 + (2*k + 1) / static_cast<double>(2);
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
// 0.03, 0.0, 0.01, 0.02, 0.03, ...
|
||||||
|
ctf_props.CF = ((k + 3 - topConn) % 4) / 100.0;
|
||||||
|
|
||||||
|
ctf_props.Kh = 1.0;
|
||||||
|
ctf_props.Ke = 1.0;
|
||||||
|
ctf_props.rw = 1.0;
|
||||||
|
ctf_props.r0 = 0.5;
|
||||||
|
ctf_props.re = 0.5;
|
||||||
|
ctf_props.connection_length = 1.0;
|
||||||
|
|
||||||
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k - topConn,
|
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k - topConn,
|
||||||
2000 + (2*k + 1) / static_cast<double>(2),
|
|
||||||
|
|
||||||
// Open, Shut, Open, Open, Shut, ...
|
// Open, Shut, Open, Open, Shut, ...
|
||||||
state[(k - topConn) % state.size()],
|
state[(k - topConn) % state.size()],
|
||||||
|
|
||||||
// 0.03, 0.0, 0.01, 0.02, 0.03, ...
|
|
||||||
((k + 3 - topConn) % 4) / 100.0,
|
|
||||||
|
|
||||||
1.0, 1.0, 0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 0,
|
|
||||||
Opm::Connection::Direction::Z,
|
Opm::Connection::Direction::Z,
|
||||||
Opm::Connection::CTFKind::DeckValue, k - topConn, false);
|
Opm::Connection::CTFKind::DeckValue,
|
||||||
|
0, depth, ctf_props, k - topConn, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Opm::Connection::Order::INPUT, i, j, conns };
|
return { Opm::Connection::Order::INPUT, i, j, conns };
|
||||||
@ -115,12 +135,22 @@ namespace {
|
|||||||
const auto iMax = std::min(dims[0] - 1, left + numConns);
|
const auto iMax = std::min(dims[0] - 1, left + numConns);
|
||||||
|
|
||||||
for (auto i = left; i < iMax; ++i) {
|
for (auto i = left; i < iMax; ++i) {
|
||||||
|
const auto depth = 2000 + (2*k + 1) / static_cast<double>(2);
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
ctf_props.CF = i / 100.0;
|
||||||
|
ctf_props.Kh = 1.0;
|
||||||
|
ctf_props.Ke = 1.0;
|
||||||
|
ctf_props.rw = 1.0;
|
||||||
|
ctf_props.r0 = 0.5;
|
||||||
|
ctf_props.re = 0.5;
|
||||||
|
ctf_props.connection_length = 1.0;
|
||||||
|
|
||||||
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), i - left,
|
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), i - left,
|
||||||
2000 + (2*k + 1) / static_cast<double>(2),
|
|
||||||
Opm::Connection::State::OPEN,
|
Opm::Connection::State::OPEN,
|
||||||
i / 100.0, 1.0, 1.0, 0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 0,
|
|
||||||
Opm::Connection::Direction::X,
|
Opm::Connection::Direction::X,
|
||||||
Opm::Connection::CTFKind::DeckValue, i - left, false);
|
Opm::Connection::CTFKind::DeckValue,
|
||||||
|
0, depth, ctf_props, i - left, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Opm::Connection::Order::INPUT, left, j, conns };
|
return { Opm::Connection::Order::INPUT, left, j, conns };
|
||||||
|
@ -732,12 +732,12 @@ BOOST_AUTO_TEST_CASE(test_RFT)
|
|||||||
std::vector<Opm::data::Connection> well1_comps(9);
|
std::vector<Opm::data::Connection> well1_comps(9);
|
||||||
Opm::data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not used in this test
|
Opm::data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not used in this test
|
||||||
for (size_t i = 0; i < 9; ++i) {
|
for (size_t i = 0; i < 9; ++i) {
|
||||||
Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 1.2e3, 4.321, 0.0, con_filtrate};
|
Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i), r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 1.2e3, 4.321, 0.0, 1.23, con_filtrate};
|
||||||
well1_comps[i] = std::move(well_comp);
|
well1_comps[i] = std::move(well_comp);
|
||||||
}
|
}
|
||||||
std::vector<Opm::data::Connection> well2_comps(6);
|
std::vector<Opm::data::Connection> well2_comps(6);
|
||||||
for (size_t i = 0; i < 6; ++i) {
|
for (size_t i = 0; i < 6; ++i) {
|
||||||
Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 0.15, 0.54321, 0.0, con_filtrate};
|
Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3), r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 0.15, 0.54321, 0.0, 0.98, con_filtrate};
|
||||||
well2_comps[i] = std::move(well_comp);
|
well2_comps[i] = std::move(well_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,12 +871,12 @@ BOOST_AUTO_TEST_CASE(test_RFT2)
|
|||||||
std::vector<Opm::data::Connection> well1_comps(9);
|
std::vector<Opm::data::Connection> well1_comps(9);
|
||||||
Opm::data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not used in this test
|
Opm::data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not used in this test
|
||||||
for (size_t i = 0; i < 9; ++i) {
|
for (size_t i = 0; i < 9; ++i) {
|
||||||
Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i) ,r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 3.14e5, 0.1234, 0.0, con_filtrate};
|
Opm::data::Connection well_comp { grid.getGlobalIndex(8,8,i), r1, 0.0 , 0.0, (double)i, 0.1*i,0.2*i, 3.14e5, 0.1234, 0.0, 1.23, con_filtrate};
|
||||||
well1_comps[i] = std::move(well_comp);
|
well1_comps[i] = std::move(well_comp);
|
||||||
}
|
}
|
||||||
std::vector<Opm::data::Connection> well2_comps(6);
|
std::vector<Opm::data::Connection> well2_comps(6);
|
||||||
for (size_t i = 0; i < 6; ++i) {
|
for (size_t i = 0; i < 6; ++i) {
|
||||||
Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3) ,r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 355.113, 0.9876, 0.0, con_filtrate};
|
Opm::data::Connection well_comp { grid.getGlobalIndex(3,3,i+3), r2, 0.0 , 0.0, (double)i, i*0.1,i*0.2, 355.113, 0.9876, 0.0, 0.98, con_filtrate};
|
||||||
well2_comps[i] = std::move(well_comp);
|
well2_comps[i] = std::move(well_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,15 +187,15 @@ data::Wells mkWells() {
|
|||||||
* input deck. All other entries in the well structures are arbitrary.
|
* input deck. All other entries in the well structures are arbitrary.
|
||||||
*/
|
*/
|
||||||
Opm::data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not used in this test
|
Opm::data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not used in this test
|
||||||
w1.connections.push_back( { 88, rc1, 30.45, 123.4, 543.21, 0.62, 0.15, 1.0e3, 1.234, 0.0, con_filtrate } );
|
w1.connections.push_back( { 88, rc1, 30.45, 123.4, 543.21, 0.62, 0.15, 1.0e3, 1.234, 0.0, 1.23, con_filtrate } );
|
||||||
w1.connections.push_back( { 288, rc2, 33.19, 123.4, 432.1, 0.26, 0.45, 2.56, 2.345, 0.0, con_filtrate } );
|
w1.connections.push_back( { 288, rc2, 33.19, 123.4, 432.1, 0.26, 0.45, 2.56, 2.345, 0.0, 0.98, con_filtrate } );
|
||||||
|
|
||||||
w2.rates = r2;
|
w2.rates = r2;
|
||||||
w2.thp = 2.0;
|
w2.thp = 2.0;
|
||||||
w2.bhp = 2.34;
|
w2.bhp = 2.34;
|
||||||
w2.temperature = 4.56;
|
w2.temperature = 4.56;
|
||||||
w2.control = 2;
|
w2.control = 2;
|
||||||
w2.connections.push_back( { 188, rc3, 36.22, 123.4, 256.1, 0.55, 0.0125, 314.15, 3.456, 0.0, con_filtrate } );
|
w2.connections.push_back( { 188, rc3, 36.22, 123.4, 256.1, 0.55, 0.0125, 314.15, 3.456, 0.0, 2.46, con_filtrate } );
|
||||||
|
|
||||||
{
|
{
|
||||||
data::Wells wellRates;
|
data::Wells wellRates;
|
||||||
|
@ -193,6 +193,7 @@ TEST_FOR_TYPE_NAMED(Action::State, ActionState)
|
|||||||
TEST_FOR_TYPE(BCConfig)
|
TEST_FOR_TYPE(BCConfig)
|
||||||
TEST_FOR_TYPE(BrineDensityTable)
|
TEST_FOR_TYPE(BrineDensityTable)
|
||||||
TEST_FOR_TYPE(ColumnSchema)
|
TEST_FOR_TYPE(ColumnSchema)
|
||||||
|
TEST_FOR_TYPE_NAMED(Connection::CTFProperties, CTFProperties)
|
||||||
TEST_FOR_TYPE(Connection)
|
TEST_FOR_TYPE(Connection)
|
||||||
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_CarterTracy, serializationTestObjectC)
|
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_CarterTracy, serializationTestObjectC)
|
||||||
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_Fetkovich, serializationTestObjectF)
|
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_Fetkovich, serializationTestObjectF)
|
||||||
@ -315,6 +316,8 @@ TEST_FOR_TYPE(VFPInjTable)
|
|||||||
TEST_FOR_TYPE(VFPProdTable)
|
TEST_FOR_TYPE(VFPProdTable)
|
||||||
TEST_FOR_TYPE(ViscrefTable)
|
TEST_FOR_TYPE(ViscrefTable)
|
||||||
TEST_FOR_TYPE(WatdentTable)
|
TEST_FOR_TYPE(WatdentTable)
|
||||||
|
TEST_FOR_TYPE_NAMED(WDFAC::Correlation, Correlation)
|
||||||
|
TEST_FOR_TYPE(WDFAC)
|
||||||
TEST_FOR_TYPE(Well)
|
TEST_FOR_TYPE(Well)
|
||||||
TEST_FOR_TYPE(Welldims)
|
TEST_FOR_TYPE(Welldims)
|
||||||
TEST_FOR_TYPE(WellBrineProperties)
|
TEST_FOR_TYPE(WellBrineProperties)
|
||||||
@ -335,11 +338,14 @@ TEST_FOR_TYPE(WListManager)
|
|||||||
TEST_FOR_TYPE(WriteRestartFileEvents)
|
TEST_FOR_TYPE(WriteRestartFileEvents)
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
bool init_unit_test_func()
|
bool init_unit_test_func()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
@ -319,11 +319,11 @@ data::Wells result_wells(const bool w3_injector = true)
|
|||||||
data::ConnectionFiltrate zero_filtrate {}; // only injecting connections are counted for filtration related
|
data::ConnectionFiltrate zero_filtrate {}; // only injecting connections are counted for filtration related
|
||||||
data::ConnectionFiltrate con_filtrate = {0.1*sm3_pr_day(), 1*sm3(), 3, 0.01*unit::meter, 1.e-3*unit::darcy, 0.2, 0.05*unit::meter, 10.*unit::square(unit::meter)};
|
data::ConnectionFiltrate con_filtrate = {0.1*sm3_pr_day(), 1*sm3(), 3, 0.01*unit::meter, 1.e-3*unit::darcy, 0.2, 0.05*unit::meter, 10.*unit::square(unit::meter)};
|
||||||
data::ConnectionFiltrate w3_con_filtrate = w3_injector ? con_filtrate : zero_filtrate;
|
data::ConnectionFiltrate w3_con_filtrate = w3_injector ? con_filtrate : zero_filtrate;
|
||||||
data::Connection well1_comp1 { 0 , crates1, 1.9 *unit::barsa, -123.4 *rm3_pr_day(), 314.15, 0.35 , 0.25, 2.718e2, 111.222*cp_rm3_per_db(), 0.0, zero_filtrate};
|
data::Connection well1_comp1 { 0 , crates1, 1.9 *unit::barsa, -123.4 *rm3_pr_day(), 314.15, 0.35 , 0.25, 2.718e2, 111.222*cp_rm3_per_db(), 0.0, 1.0, zero_filtrate};
|
||||||
data::Connection well2_comp1 { 1 , crates2, 1.10*unit::barsa, - 23.4 *rm3_pr_day(), 212.1 , 0.78 , 0.0 , 12.34 , 222.333*cp_rm3_per_db(), 0.0, zero_filtrate};
|
data::Connection well2_comp1 { 1 , crates2, 1.10*unit::barsa, - 23.4 *rm3_pr_day(), 212.1 , 0.78 , 0.0 , 12.34 , 222.333*cp_rm3_per_db(), 0.0, 1.0, zero_filtrate};
|
||||||
data::Connection well2_comp2 { 101, crates3, 1.11*unit::barsa, -234.5 *rm3_pr_day(), 150.6 , 0.001, 0.89, 100.0 , 333.444*cp_rm3_per_db(), 0.0, con_filtrate /* output should be zero since it is a producer */};
|
data::Connection well2_comp2 { 101, crates3, 1.11*unit::barsa, -234.5 *rm3_pr_day(), 150.6 , 0.001, 0.89, 100.0 , 333.444*cp_rm3_per_db(), 0.0, 1.0, con_filtrate /* output should be zero since it is a producer */};
|
||||||
data::Connection well3_comp1 { 2 , crates3, 1.11*unit::barsa, 432.1 *rm3_pr_day(), 456.78, 0.0 , 0.15, 432.1 , 444.555*cp_rm3_per_db(), 0.0, w3_con_filtrate};
|
data::Connection well3_comp1 { 2 , crates3, 1.11*unit::barsa, 432.1 *rm3_pr_day(), 456.78, 0.0 , 0.15, 432.1 , 444.555*cp_rm3_per_db(), 0.0, 1.0, w3_con_filtrate};
|
||||||
data::Connection well6_comp1 { 77 , crates6, 6.11*unit::barsa, 321.09*rm3_pr_day(), 656.78, 0.0 , 0.65, 632.1 , 555.666*cp_rm3_per_db(), 0.0, zero_filtrate};
|
data::Connection well6_comp1 { 77 , crates6, 6.11*unit::barsa, 321.09*rm3_pr_day(), 656.78, 0.0 , 0.65, 632.1 , 555.666*cp_rm3_per_db(), 0.0, 1.0, zero_filtrate};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The completions
|
The completions
|
||||||
|
@ -172,7 +172,7 @@ static data::Wells result_wells() {
|
|||||||
input deck.
|
input deck.
|
||||||
*/
|
*/
|
||||||
data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not tested in this test
|
data::ConnectionFiltrate con_filtrate {0.1, 1, 3, 0.4, 1.e-9, 0.2, 0.05, 10.}; // values are not tested in this test
|
||||||
data::Connection well1_comp1 { 0 , crates1, 1.9 , 123.4, 314.15, 0.35, 0.25, 2.718e2, 0.12345, 0.0, con_filtrate };
|
data::Connection well1_comp1 { 0, crates1, 1.9, 123.4, 314.15, 0.35, 0.25, 2.718e2, 0.12345, 0.0, 1.23, con_filtrate };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The completions
|
The completions
|
||||||
|
@ -116,8 +116,8 @@ BOOST_AUTO_TEST_CASE(get_connections) {
|
|||||||
* the completion keys (active indices) and well names correspond to the
|
* the completion keys (active indices) and well names correspond to the
|
||||||
* input deck. All other entries in the well structures are arbitrary.
|
* input deck. All other entries in the well structures are arbitrary.
|
||||||
*/
|
*/
|
||||||
w1.connections.push_back( { 88, rc1, 30.45, 123.45, 543.21, 0.123, 0.5, 17.29, 0.1729,0.0,{}} );
|
w1.connections.push_back( { 88, rc1, 30.45, 123.45, 543.21, 0.123, 0.5, 17.29, 0.1729, 0.0, 1.23, {}} );
|
||||||
w1.connections.push_back( { 288, rc2, 33.19, 67.89, 98.76, 0.5, 0.125, 355.113, 0.355113,0.0, {}} );
|
w1.connections.push_back( { 288, rc2, 33.19, 67.89, 98.76, 0.5, 0.125, 355.113, 0.355113, 0.0, 0.98, {}} );
|
||||||
|
|
||||||
{
|
{
|
||||||
Json::JsonObject json_data;
|
Json::JsonObject json_data;
|
||||||
@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE(get_connections) {
|
|||||||
w2.temperature = 4.56;
|
w2.temperature = 4.56;
|
||||||
w2.control = 2;
|
w2.control = 2;
|
||||||
w2.filtrate = {0.3, 3, 0.4}; // values are not tested in this test
|
w2.filtrate = {0.3, 3, 0.4}; // values are not tested in this test
|
||||||
w2.connections.push_back( { 188, rc3, 36.22, 19.28, 28.91, 0.125, 0.125, 3.141, 0.31415, 0.0, {}} );
|
w2.connections.push_back( { 188, rc3, 36.22, 19.28, 28.91, 0.125, 0.125, 3.141, 0.31415, 0.0, 1.21, {}} );
|
||||||
data::Wells wellRates;
|
data::Wells wellRates;
|
||||||
|
|
||||||
wellRates["OP_1"] = w1;
|
wellRates["OP_1"] = w1;
|
||||||
|
Loading…
Reference in New Issue
Block a user