Merge pull request #1056 from joakim-hove/field-properties
Add FieldProps skeleton
This commit is contained in:
commit
0fb55b23c0
@ -11,7 +11,11 @@ option(ENABLE_MOCKSIM "Build the mock simulator for io testing" ON)
|
||||
option(OPM_ENABLE_PYTHON "Enable python bindings?" OFF)
|
||||
option(OPM_INSTALL_PYTHON "Enable python bindings?" OFF)
|
||||
option(OPM_ENABLE_EMBEDDED_PYTHON "Enable python bindings?" OFF)
|
||||
option(ENABLE_3DPROPS_TESTING "Enable the in-constructor testing of 3D properties" OFF)
|
||||
|
||||
if (ENABLE_3DPROPS_TESTING)
|
||||
add_definitions(-DENABLE_3DPROPS_TESTING)
|
||||
endif()
|
||||
|
||||
# Output implies input
|
||||
if(ENABLE_ECL_OUTPUT)
|
||||
|
@ -58,6 +58,8 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/parser/eclipse/EclipseState/EclipseState.cpp
|
||||
src/opm/parser/eclipse/EclipseState/EndpointScaling.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Edit/EDITNNC.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/FieldProps.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/Box.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/BoxManager.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/EclipseGrid.cpp
|
||||
@ -284,6 +286,7 @@ if(ENABLE_ECL_INPUT)
|
||||
tests/parser/EventTests.cpp
|
||||
tests/parser/FaceDirTests.cpp
|
||||
tests/parser/FaultTests.cpp
|
||||
tests/parser/FieldPropsTests.cpp
|
||||
tests/parser/FoamTests.cpp
|
||||
tests/parser/FunctionalTests.cpp
|
||||
tests/parser/GeomodifierTests.cpp
|
||||
@ -501,6 +504,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/Grid/SatfuncPropertyInitializers.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/Fault.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/Box.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/GridProperty.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/FaultFace.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/NNC.hpp
|
||||
|
@ -4,7 +4,7 @@ declare -A configurations
|
||||
|
||||
declare -A EXTRA_MODULE_FLAGS
|
||||
EXTRA_MODULE_FLAGS[opm-simulators]="-DBUILD_EBOS_EXTENSIONS=ON -DBUILD_EBOS_DEBUG_EXTENSIONS=ON -DBUILD_FLOW_VARIANTS=ON"
|
||||
EXTRA_MODULE_FLAGS[opm-common]="-DOPM_ENABLE_PYTHON=ON -DOPM_ENABLE_EMBEDDED_PYTHON=ON -DOPM_INSTALL_PYTHON=ON"
|
||||
EXTRA_MODULE_FLAGS[opm-common]="-DOPM_ENABLE_PYTHON=ON -DOPM_ENABLE_EMBEDDED_PYTHON=ON -DOPM_INSTALL_PYTHON=ON -DENABLE_3DPROPS_TESTING=ON"
|
||||
|
||||
# Parse revisions from trigger comment and setup arrays
|
||||
# Depends on: 'upstreams', upstreamRev',
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/FaultCollection.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
||||
@ -129,6 +130,7 @@ namespace Opm {
|
||||
EDITNNC m_inputEditNnc;
|
||||
EclipseGrid m_inputGrid;
|
||||
Eclipse3DProperties m_eclipseProperties;
|
||||
FieldPropsManager field_props;
|
||||
const SimulationConfig m_simulationConfig;
|
||||
TransMult m_transMult;
|
||||
|
||||
|
@ -64,6 +64,7 @@ namespace Opm {
|
||||
void endKeyword();
|
||||
|
||||
const Box& getActiveBox() const;
|
||||
const std::vector<Box::cell_index>& index_list() const;
|
||||
|
||||
private:
|
||||
const EclipseGrid& grid;
|
||||
|
56
opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp
Normal file
56
opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FIELDPROPS_MANAGER_HPP
|
||||
#define FIELDPROPS_MANAGER_HPP
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class EclipseGrid;
|
||||
class Deck;
|
||||
class FieldProps;
|
||||
|
||||
class FieldPropsManager {
|
||||
public:
|
||||
// The default constructor should be removed when the FieldPropsManager is mandatory
|
||||
FieldPropsManager() = default;
|
||||
FieldPropsManager(const Deck& deck, const EclipseGrid& grid);
|
||||
void reset_grid(const EclipseGrid& grid);
|
||||
|
||||
template <typename T>
|
||||
const std::vector<T>& get(const std::string& keyword) const;
|
||||
|
||||
template <typename T>
|
||||
const std::vector<T>* try_get(const std::string& keyword) const;
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> get_global(const std::string& keyword) const;
|
||||
|
||||
template <typename T>
|
||||
static bool supported(const std::string& keyword);
|
||||
|
||||
|
||||
private:
|
||||
std::shared_ptr<FieldProps> fp;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -51,7 +51,7 @@ const std::vector< double >& DeckItem::value_ref< double >() const {
|
||||
if (this->type == get_type<double>())
|
||||
return this->dval;
|
||||
|
||||
throw std::invalid_argument( "DeckItem::value_ref<double> Item of wrong type." );
|
||||
throw std::invalid_argument( "DeckItem::value_ref<double> Item of wrong type. this->type: " + tag_name(this->type) + " " + this->name());
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -49,6 +49,88 @@
|
||||
namespace Opm {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef ENABLE_3DPROPS_TESTING
|
||||
void assert_field_properties(const EclipseGrid& grid, const FieldPropsManager& fp, const Eclipse3DProperties& ep) {
|
||||
std::vector<std::string> int_keywords = {"FLUXNUM",
|
||||
"MULTNUM",
|
||||
"OPERNUM",
|
||||
"ROCKNUM",
|
||||
//"ENDNUM",
|
||||
"EQLNUM",
|
||||
"FIPNUM",
|
||||
"IMBNUM",
|
||||
"MISCNUM",
|
||||
"OPERNUM",
|
||||
"PVTNUM",
|
||||
"SATNUM"};
|
||||
|
||||
std::vector<std::string> double_keywords = {"MULTPV",
|
||||
//"NTG",
|
||||
"PORO",
|
||||
"PERMX",
|
||||
"PERMY",
|
||||
"PERMZ",
|
||||
"SWATINIT",
|
||||
"TEMPI",
|
||||
"THCONR"};
|
||||
|
||||
for (const auto& kw : double_keywords) {
|
||||
bool has = fp.try_get<double>(kw);
|
||||
if (has != ep.hasDeckDoubleGridProperty(kw)) {
|
||||
std::cerr << "FieldPropsManager: " << has << std::endl;
|
||||
std::cerr << "Eclipse3dProperties: " << ep.hasDeckDoubleGridProperty(kw) << std::endl;
|
||||
throw std::logic_error("Exist Error for: " + kw);
|
||||
}
|
||||
|
||||
if (has) {
|
||||
const auto& fp_data = fp.get<double>(kw);
|
||||
const auto& ep_data = ep.getDoubleGridProperty(kw).compressedCopy(grid);
|
||||
if (fp_data != ep_data) {
|
||||
printf("size: %ld %ld \n", fp_data.size(), ep_data.size());
|
||||
for (std::size_t i=0; i< fp_data.size(); i++) {
|
||||
if (fp_data[i] == ep_data[i])
|
||||
printf("fp[%ld]: %lg ep[%ld]: %lg \n", i, fp_data[i], i, ep_data[i]);
|
||||
else
|
||||
printf("fp[%ld]: %lg ep[%ld]: %lg ** \n", i, fp_data[i], i, ep_data[i]);
|
||||
}
|
||||
|
||||
throw std::logic_error("Data error for: " + kw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& kw : int_keywords) {
|
||||
bool has = fp.try_get<int>(kw);
|
||||
if (has != ep.hasDeckIntGridProperty(kw)) {
|
||||
std::cerr << "FieldPropsManager: " << has << std::endl;
|
||||
std::cerr << "Eclipse3dProperties: " << ep.hasDeckIntGridProperty(kw) << std::endl;
|
||||
throw std::logic_error("Exists error for: " + kw);
|
||||
}
|
||||
|
||||
if (has) {
|
||||
const auto& fp_data = fp.get<int>(kw);
|
||||
const auto& ep_data = ep.getIntGridProperty(kw).compressedCopy(grid);
|
||||
if (fp_data != ep_data) {
|
||||
printf("size: %ld %ld \n", fp_data.size(), ep_data.size());
|
||||
for (std::size_t i=0; i< fp_data.size(); i++)
|
||||
printf("fp[%ld]: %d ep[%ld]: %d \n", i, fp_data[i], i, ep_data[i]);
|
||||
|
||||
throw std::logic_error("Data error for: " + kw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
EclipseState::EclipseState(const Deck& deck , const ParseContext& parseContext, ErrorGuard& errors) :
|
||||
m_tables( deck ),
|
||||
m_runspec( deck ),
|
||||
@ -58,6 +140,9 @@ namespace Opm {
|
||||
m_inputEditNnc( deck ),
|
||||
m_inputGrid( deck, nullptr ),
|
||||
m_eclipseProperties( deck, m_tables, m_inputGrid ),
|
||||
#ifdef ENABLE_3DPROPS_TESTING
|
||||
field_props( deck, m_inputGrid),
|
||||
#endif
|
||||
m_simulationConfig( m_eclipseConfig.getInitConfig().restartRequested(), deck, m_eclipseProperties ),
|
||||
m_transMult( GridDims(deck), deck, m_eclipseProperties )
|
||||
{
|
||||
@ -76,6 +161,10 @@ namespace Opm {
|
||||
|
||||
initTransMult();
|
||||
initFaults(deck);
|
||||
#ifdef ENABLE_3DPROPS_TESTING
|
||||
this->field_props.reset_grid( this->m_inputGrid );
|
||||
assert_field_properties(this->m_inputGrid, this->field_props, this->m_eclipseProperties);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -199,6 +288,9 @@ namespace Opm {
|
||||
}
|
||||
|
||||
void EclipseState::initFaults(const Deck& deck) {
|
||||
if (!Section::hasGRID(deck))
|
||||
return;
|
||||
|
||||
const GRIDSection gridSection ( deck );
|
||||
|
||||
m_faults = FaultCollection(gridSection, m_inputGrid);
|
||||
|
@ -64,4 +64,7 @@ namespace Opm {
|
||||
this->m_keywordBox.reset( 0 );
|
||||
}
|
||||
|
||||
const std::vector<Box::cell_index>& BoxManager::index_list() const {
|
||||
return this->getActiveBox().index_list();
|
||||
}
|
||||
}
|
||||
|
569
src/opm/parser/eclipse/EclipseState/Grid/FieldProps.cpp
Normal file
569
src/opm/parser/eclipse/EclipseState/Grid/FieldProps.cpp
Normal file
@ -0,0 +1,569 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/A.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/B.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/C.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/E.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/M.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/P.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/BoxManager.hpp>
|
||||
|
||||
#include "FieldProps.hpp"
|
||||
|
||||
|
||||
namespace Opm {
|
||||
|
||||
namespace {
|
||||
|
||||
namespace keywords {
|
||||
static const std::map<std::string, std::string> unit_string = {{"PORO", "1"},
|
||||
{"PERMX", "Permeability"},
|
||||
{"PERMY", "Permeability"},
|
||||
{"PERMZ", "Permeability"},
|
||||
{"NTG", "1"},
|
||||
{"SWATINIT", "1"}};
|
||||
|
||||
static const std::set<std::string> oper_keywords = {"ADD", "EQUALS", "MAXVALUE", "MINVALUE", "MULTIPLY"};
|
||||
static const std::set<std::string> box_keywords = {"BOX", "ENDBOX"};
|
||||
static const std::map<std::string, double> double_scalar_init = {{"NTG", 1}};
|
||||
|
||||
|
||||
namespace GRID {
|
||||
static const std::set<std::string> double_keywords = {"MULTPV", "NTG", "PORO", "PERMX", "PERMY", "PERMZ", "THCONR"};
|
||||
static const std::set<std::string> int_keywords = {"FLUXNUM", "MULTNUM", "OPERNUM", "ROCKNUM"};
|
||||
static const std::set<std::string> top_keywords = {"PORO", "PERMX", "PERMY", "PERMZ"};
|
||||
}
|
||||
|
||||
namespace EDIT {
|
||||
static const std::set<std::string> double_keywords = {"MULTPV"};
|
||||
}
|
||||
|
||||
namespace PROPS {
|
||||
static const std::set<std::string> double_keywords = {"SWATINIT"};
|
||||
}
|
||||
|
||||
namespace REGIONS {
|
||||
static const std::set<std::string> int_keywords = {"ENDNUM", "EQLNUM", "FIPNUM", "IMBNUM", "MISCNUM", "OPERNUM", "PVTNUM", "SATNUM"};
|
||||
}
|
||||
|
||||
namespace SOLUTION {
|
||||
static const std::set<std::string> double_keywords = {"TEMPI"};
|
||||
}
|
||||
|
||||
namespace SCHEDULE {
|
||||
static const std::set<std::string> int_keywords = {"ROCKNUM"};
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The EQUALREG, MULTREG, COPYREG, ... keywords are used to manipulate
|
||||
* vectors based on region values; for instance the statement
|
||||
*
|
||||
* EQUALREG
|
||||
* PORO 0.25 3 / -- Region array not specified
|
||||
* PERMX 100 3 F /
|
||||
* /
|
||||
*
|
||||
* will set the PORO field to 0.25 for all cells in region 3 and the PERMX
|
||||
* value to 100 mD for the same cells. The fourth optional argument to the
|
||||
* EQUALREG keyword is used to indicate which REGION array should be used
|
||||
* for the selection.
|
||||
*
|
||||
* If the REGION array is not indicated (as in the PORO case) above, the
|
||||
* default region to use in the xxxREG keywords depends on the GRIDOPTS
|
||||
* keyword:
|
||||
*
|
||||
* 1. If GRIDOPTS is present, and the NRMULT item is greater than zero,
|
||||
* the xxxREG keywords will default to use the MULTNUM region.
|
||||
*
|
||||
* 2. If the GRIDOPTS keyword is not present - or the NRMULT item equals
|
||||
* zero, the xxxREG keywords will default to use the FLUXNUM keyword.
|
||||
*
|
||||
* This quite weird behaviour comes from reading the GRIDOPTS and MULTNUM
|
||||
* documentation, and practical experience with ECLIPSE
|
||||
* simulations. Ufortunately the documentation of the xxxREG keywords does
|
||||
* not confirm this.
|
||||
*/
|
||||
std::string default_region_keyword(const Deck& deck) {
|
||||
if (deck.hasKeyword("GRIDOPTS")) {
|
||||
const auto& gridOpts = deck.getKeyword("GRIDOPTS");
|
||||
const auto& record = gridOpts.getRecord(0);
|
||||
const auto& nrmult_item = record.getItem("NRMULT");
|
||||
|
||||
if (nrmult_item.get<int>(0) > 0)
|
||||
return "MULTNUM"; // GRIDOPTS and positive NRMULT
|
||||
}
|
||||
return "FLUXNUM";
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
void assign_deck(const DeckKeyword& keyword, FieldProps::FieldData<T>& field_data, const std::vector<T>& deck_data, const Box& box) {
|
||||
if (box.size() != deck_data.size()) {
|
||||
const auto& location = keyword.location();
|
||||
std::string msg = "Fundamental error with keyword: " + keyword.name() +
|
||||
" at: " + location.filename + ", line: " + std::to_string(location.lineno) +
|
||||
" got " + std::to_string(deck_data.size()) + " elements - expected : " + std::to_string(box.size());
|
||||
throw std::invalid_argument(msg);
|
||||
}
|
||||
|
||||
|
||||
for (const auto& cell_index : box.index_list()) {
|
||||
field_data.data[cell_index.active_index] = deck_data[cell_index.data_index];
|
||||
field_data.assigned[cell_index.active_index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void distribute_toplayer(const EclipseGrid& grid, FieldProps::FieldData<T>& field_data, const std::vector<T>& deck_data, const Box& box) {
|
||||
const std::size_t layer_size = grid.getNX() * grid.getNY();
|
||||
FieldProps::FieldData<double> toplayer(grid.getNX() * grid.getNY());
|
||||
for (const auto& cell_index : box.index_list()) {
|
||||
if (cell_index.global_index < layer_size) {
|
||||
toplayer.data[cell_index.global_index] = deck_data[cell_index.data_index];
|
||||
toplayer.assigned[cell_index.global_index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t active_index = 0; active_index < field_data.size(); active_index++) {
|
||||
if (!field_data.assigned[active_index]) {
|
||||
std::size_t global_index = grid.getGlobalIndex(active_index);
|
||||
const auto ijk = grid.getIJK(global_index);
|
||||
std::size_t layer_index = ijk[0] + ijk[1] * grid.getNX();
|
||||
if (toplayer.assigned[layer_index]) {
|
||||
field_data.data[active_index] = toplayer.data[layer_index];
|
||||
field_data.assigned[active_index] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void assign_scalar(FieldProps::FieldData<T>& field_data, T value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
field_data.data[cell_index.active_index] = value;
|
||||
field_data.assigned[cell_index.active_index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void multiply_scalar(FieldProps::FieldData<T>& field_data, T value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (field_data.assigned[cell_index.active_index])
|
||||
field_data.data[cell_index.active_index] *= value;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void add_scalar(FieldProps::FieldData<T>& field_data, T value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (field_data.assigned[cell_index.active_index])
|
||||
field_data.data[cell_index.active_index] += value;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void min_value(FieldProps::FieldData<T>& field_data, T min_value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (field_data.assigned[cell_index.active_index]) {
|
||||
T value = field_data.data[cell_index.active_index];
|
||||
field_data.data[cell_index.active_index] = std::max(value, min_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void max_value(FieldProps::FieldData<T>& field_data, T max_value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (field_data.assigned[cell_index.active_index]) {
|
||||
T value = field_data.data[cell_index.active_index];
|
||||
field_data.data[cell_index.active_index] = std::min(value, max_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setKeywordBox( const DeckRecord& deckRecord, BoxManager& boxManager) {
|
||||
const auto& I1Item = deckRecord.getItem("I1");
|
||||
const auto& I2Item = deckRecord.getItem("I2");
|
||||
const auto& J1Item = deckRecord.getItem("J1");
|
||||
const auto& J2Item = deckRecord.getItem("J2");
|
||||
const auto& K1Item = deckRecord.getItem("K1");
|
||||
const auto& K2Item = deckRecord.getItem("K2");
|
||||
|
||||
const auto& active_box = boxManager.getActiveBox();
|
||||
|
||||
const int i1 = I1Item.defaultApplied(0) ? active_box.I1() : I1Item.get<int>(0) - 1;
|
||||
const int i2 = I2Item.defaultApplied(0) ? active_box.I2() : I2Item.get<int>(0) - 1;
|
||||
const int j1 = J1Item.defaultApplied(0) ? active_box.J1() : J1Item.get<int>(0) - 1;
|
||||
const int j2 = J2Item.defaultApplied(0) ? active_box.J2() : J2Item.get<int>(0) - 1;
|
||||
const int k1 = K1Item.defaultApplied(0) ? active_box.K1() : K1Item.get<int>(0) - 1;
|
||||
const int k2 = K2Item.defaultApplied(0) ? active_box.K2() : K2Item.get<int>(0) - 1;
|
||||
|
||||
boxManager.setKeywordBox( i1,i2,j1,j2,k1,k2 );
|
||||
}
|
||||
|
||||
void handle_box_keyword(const EclipseGrid& grid, const DeckKeyword& deckKeyword, BoxManager& boxManager) {
|
||||
if (deckKeyword.name() == ParserKeywords::BOX::keywordName) {
|
||||
const auto& record = deckKeyword.getRecord(0);
|
||||
|
||||
const auto& I1Item = record.getItem("I1");
|
||||
const auto& I2Item = record.getItem("I2");
|
||||
const auto& J1Item = record.getItem("J1");
|
||||
const auto& J2Item = record.getItem("J2");
|
||||
const auto& K1Item = record.getItem("K1");
|
||||
const auto& K2Item = record.getItem("K2");
|
||||
|
||||
const int i1 = I1Item.defaultApplied(0) ? 0 : I1Item.get<int>(0) - 1;
|
||||
const int i2 = I2Item.defaultApplied(0) ? grid.getNX() : I2Item.get<int>(0) - 1;
|
||||
const int j1 = J1Item.defaultApplied(0) ? 0 : J1Item.get<int>(0) - 1;
|
||||
const int j2 = J2Item.defaultApplied(0) ? grid.getNY() : J2Item.get<int>(0) - 1;
|
||||
const int k1 = K1Item.defaultApplied(0) ? 0 : K1Item.get<int>(0) - 1;
|
||||
const int k2 = K2Item.defaultApplied(0) ? grid.getNZ() : K2Item.get<int>(0) - 1;
|
||||
|
||||
boxManager.setInputBox( i1 , i2 , j1 , j2 , k1 , k2 );
|
||||
} else if (deckKeyword.name() == ParserKeywords::ENDBOX::keywordName)
|
||||
boxManager.endInputBox();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
FieldProps::FieldProps(const Deck& deck, const EclipseGrid& grid_arg) :
|
||||
unit_system(deck.getActiveUnitSystem()),
|
||||
grid(std::addressof(grid_arg)),
|
||||
active_size(grid_arg.getNumActive()),
|
||||
actnum(grid_arg.getACTNUM()),
|
||||
default_region(default_region_keyword(deck))
|
||||
{
|
||||
if (Section::hasGRID(deck))
|
||||
this->scanGRIDSection(GRIDSection(deck));
|
||||
|
||||
if (Section::hasPROPS(deck))
|
||||
this->scanPROPSSection(PROPSSection(deck));
|
||||
|
||||
if (Section::hasREGIONS(deck))
|
||||
this->scanREGIONSSection(REGIONSSection(deck));
|
||||
}
|
||||
|
||||
void FieldProps::reset_grid(const EclipseGrid& grid_arg) {
|
||||
const auto& new_actnum = grid_arg.getACTNUM();
|
||||
if (new_actnum == this->actnum)
|
||||
return;
|
||||
|
||||
std::vector<bool> active_map(this->active_size, true);
|
||||
std::size_t active_index = 0;
|
||||
for (std::size_t g = 0; g < this->actnum.size(); g++) {
|
||||
if (this->actnum[g] != 0) {
|
||||
if (new_actnum[g] == 0)
|
||||
active_map[active_index] = false;
|
||||
active_index += 1;
|
||||
} else {
|
||||
if (new_actnum[g] != 0)
|
||||
throw std::logic_error("It is not possible to activate cells");
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& data : this->double_data)
|
||||
data.second.compress(active_map);
|
||||
|
||||
for (auto& data : this->int_data)
|
||||
data.second.compress(active_map);
|
||||
|
||||
this->grid = std::addressof(grid_arg);
|
||||
this->actnum = new_actnum;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool FieldProps::supported<double>(const std::string& keyword) {
|
||||
if (keywords::GRID::double_keywords.count(keyword) != 0)
|
||||
return true;
|
||||
|
||||
if (keywords::EDIT::double_keywords.count(keyword) != 0)
|
||||
return true;
|
||||
|
||||
if (keywords::PROPS::double_keywords.count(keyword) != 0)
|
||||
return true;
|
||||
|
||||
if (keywords::SOLUTION::double_keywords.count(keyword) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool FieldProps::supported<int>(const std::string& keyword) {
|
||||
if (keywords::REGIONS::int_keywords.count(keyword) != 0)
|
||||
return true;
|
||||
|
||||
if (keywords::GRID::int_keywords.count(keyword) != 0)
|
||||
return true;
|
||||
|
||||
if (keywords::SCHEDULE::int_keywords.count(keyword) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
FieldProps::FieldData<double>& FieldProps::get(const std::string& keyword) {
|
||||
auto iter = this->double_data.find(keyword);
|
||||
if (iter != this->double_data.end())
|
||||
return iter->second;
|
||||
|
||||
if (FieldProps::supported<double>(keyword)) {
|
||||
this->double_data[keyword] = FieldData<double>(this->grid->getNumActive());
|
||||
auto init_iter = keywords::double_scalar_init.find(keyword);
|
||||
if (init_iter != keywords::double_scalar_init.end())
|
||||
this->double_data[keyword].assign(init_iter->second);
|
||||
|
||||
return this->double_data[keyword];
|
||||
} else
|
||||
throw std::out_of_range("Double keyword: " + keyword + " is not supported");
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <>
|
||||
FieldProps::FieldData<int>& FieldProps::get(const std::string& keyword) {
|
||||
auto iter = this->int_data.find(keyword);
|
||||
if (iter != this->int_data.end())
|
||||
return iter->second;
|
||||
|
||||
if (FieldProps::supported<int>(keyword)) {
|
||||
this->int_data[keyword] = FieldData<int>(this->grid->getNumActive());
|
||||
return this->int_data[keyword];
|
||||
} else
|
||||
throw std::out_of_range("Integer keyword " + keyword + " is not supported");
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
bool FieldProps::has<double>(const std::string& keyword) const {
|
||||
return (this->double_data.count(keyword) != 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool FieldProps::has<int>(const std::string& keyword) const {
|
||||
return (this->int_data.count(keyword) != 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
void FieldProps::erase<int>(const std::string& keyword) {
|
||||
this->int_data.erase(keyword);
|
||||
}
|
||||
|
||||
template <>
|
||||
void FieldProps::erase<double>(const std::string& keyword) {
|
||||
this->double_data.erase(keyword);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
double FieldProps::getSIValue(const std::string& keyword, double raw_value) const {
|
||||
const auto& iter = keywords::unit_string.find(keyword);
|
||||
if (iter == keywords::unit_string.end())
|
||||
throw std::logic_error("Trying to look up dimension string for keyword: " + keyword);
|
||||
|
||||
const auto& dim_string = iter->second;
|
||||
const auto& dim = this->unit_system.parse( dim_string );
|
||||
return dim.convertRawToSi(raw_value);
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::scanGRIDSection(const GRIDSection& grid_section) {
|
||||
BoxManager box_manager(*this->grid);
|
||||
|
||||
for (const auto& keyword : grid_section) {
|
||||
const std::string& name = keyword.name();
|
||||
if (keywords::GRID::double_keywords.count(name) == 1)
|
||||
this->handle_grid_section_double_keyword(keyword, box_manager);
|
||||
|
||||
if (keywords::GRID::int_keywords.count(name) == 1)
|
||||
this->handle_int_keyword(keyword, box_manager);
|
||||
|
||||
else if (keywords::oper_keywords.count(name) == 1)
|
||||
this->handle_scalar_operation(keyword, box_manager);
|
||||
|
||||
else if (keywords::box_keywords.count(name) == 1)
|
||||
handle_box_keyword(*this->grid, keyword, box_manager);
|
||||
|
||||
else if (name == ParserKeywords::COPY::keywordName)
|
||||
handle_COPY(keyword, box_manager);
|
||||
|
||||
box_manager.endKeyword();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::scanPROPSSection(const PROPSSection& props_section) {
|
||||
BoxManager box_manager(*this->grid);
|
||||
|
||||
for (const auto& keyword : props_section) {
|
||||
const std::string& name = keyword.name();
|
||||
if (keywords::PROPS::double_keywords.count(name) == 1)
|
||||
this->handle_props_section_double_keyword(keyword, box_manager);
|
||||
|
||||
else if (keywords::oper_keywords.count(name) == 1)
|
||||
this->handle_scalar_operation(keyword, box_manager);
|
||||
|
||||
else if (keywords::box_keywords.count(name) == 1)
|
||||
handle_box_keyword(*this->grid, keyword, box_manager);
|
||||
|
||||
else if (name == ParserKeywords::COPY::keywordName)
|
||||
handle_COPY(keyword, box_manager);
|
||||
|
||||
box_manager.endKeyword();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::scanREGIONSSection(const REGIONSSection& regions_section) {
|
||||
BoxManager box_manager(*this->grid);
|
||||
|
||||
for (const auto& keyword : regions_section) {
|
||||
const std::string& name = keyword.name();
|
||||
|
||||
if (keywords::REGIONS::int_keywords.count(name) == 1)
|
||||
this->handle_int_keyword(keyword, box_manager);
|
||||
|
||||
else if (keywords::oper_keywords.count(name) == 1)
|
||||
this->handle_scalar_operation(keyword, box_manager);
|
||||
|
||||
else if (keywords::box_keywords.count(name) == 1)
|
||||
handle_box_keyword(*this->grid, keyword, box_manager);
|
||||
|
||||
else if (name == ParserKeywords::COPY::keywordName)
|
||||
handle_COPY(keyword, box_manager);
|
||||
|
||||
box_manager.endKeyword();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::handle_int_keyword(const DeckKeyword& keyword, const BoxManager& box_manager) {
|
||||
auto& field_data = this->get<int>(keyword.name());
|
||||
const auto& deck_data = keyword.getIntData();
|
||||
assign_deck(keyword, field_data, deck_data, box_manager.getActiveBox());
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::handle_props_section_double_keyword(const DeckKeyword& keyword, const BoxManager& box_manager) {
|
||||
auto& field_data = this->get<double>(keyword.name());
|
||||
const auto& deck_data = keyword.getSIDoubleData();
|
||||
assign_deck(keyword, field_data, deck_data, box_manager.getActiveBox());
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::handle_grid_section_double_keyword(const DeckKeyword& keyword, const BoxManager& box_manager) {
|
||||
auto& field_data = this->get<double>(keyword.name());
|
||||
const auto& deck_data = keyword.getSIDoubleData();
|
||||
assign_deck(keyword, field_data, deck_data, box_manager.getActiveBox());
|
||||
|
||||
if (field_data.valid())
|
||||
return;
|
||||
|
||||
if (keywords::GRID::top_keywords.count(keyword.name()) == 1)
|
||||
distribute_toplayer(*this->grid, field_data, deck_data, box_manager.getActiveBox());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
void FieldProps::handle_scalar_operation(const std::string& keyword, FieldData<T>& data, T scalar_value, const Box& box) {
|
||||
if (keyword == ParserKeywords::EQUALS::keywordName)
|
||||
assign_scalar(data, scalar_value, box.index_list());
|
||||
|
||||
else if (keyword == ParserKeywords::MULTIPLY::keywordName)
|
||||
multiply_scalar(data, scalar_value, box.index_list());
|
||||
|
||||
else if (keyword == ParserKeywords::ADD::keywordName)
|
||||
add_scalar(data, scalar_value, box.index_list());
|
||||
|
||||
else if (keyword == ParserKeywords::MINVALUE::keywordName)
|
||||
min_value(data, scalar_value, box.index_list());
|
||||
|
||||
else if (keyword == ParserKeywords::MAXVALUE::keywordName)
|
||||
max_value(data, scalar_value, box.index_list());
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::handle_scalar_operation(const DeckKeyword& keyword, BoxManager& box_manager) {
|
||||
for (const auto& record : keyword) {
|
||||
setKeywordBox(record, box_manager);
|
||||
const std::string& target_kw = record.getItem(0).get<std::string>(0);
|
||||
|
||||
if (FieldProps::supported<double>(target_kw)) {
|
||||
double scalar_value = record.getItem(1).get<double>(0);
|
||||
if (keyword.name() != ParserKeywords::MULTIPLY::keywordName)
|
||||
scalar_value = this->getSIValue(target_kw, scalar_value);
|
||||
|
||||
auto& field_data = this->get<double>(target_kw);
|
||||
FieldProps::handle_scalar_operation(keyword.name(), field_data, scalar_value, box_manager.getActiveBox());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (FieldProps::supported<int>(target_kw)) {
|
||||
int scalar_value = static_cast<int>(record.getItem(1).get<double>(0));
|
||||
auto& field_data = this->get<int>(target_kw);
|
||||
FieldProps::handle_scalar_operation(keyword.name(), field_data, scalar_value, box_manager.getActiveBox());
|
||||
continue;
|
||||
}
|
||||
|
||||
//throw std::out_of_range("The keyword: " + target_kw + " is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FieldProps::handle_COPY(const DeckKeyword& keyword, BoxManager& box_manager) {
|
||||
for (const auto& record : keyword) {
|
||||
setKeywordBox(record, box_manager);
|
||||
const std::string& src_kw = record.getItem(0).get<std::string>(0);
|
||||
const std::string& target_kw = record.getItem(1).get<std::string>(0);
|
||||
|
||||
|
||||
if (FieldProps::supported<double>(src_kw)) {
|
||||
const auto * src_data = this->try_get<double>(src_kw);
|
||||
if (!src_data)
|
||||
throw std::invalid_argument("Tried to copy from not fully initialized keword: " + src_kw);
|
||||
auto& target_data = this->get<double>(target_kw);
|
||||
target_data.assign(*src_data, box_manager.getActiveBox());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FieldProps::supported<int>(src_kw)) {
|
||||
const auto * src_data = this->try_get<int>(src_kw);
|
||||
if (!src_data)
|
||||
throw std::invalid_argument("Tried to copy from not fully initialized keword: " + src_kw);
|
||||
auto& target_data = this->get<int>(target_kw);
|
||||
target_data.assign(*src_data, box_manager.getActiveBox());
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
168
src/opm/parser/eclipse/EclipseState/Grid/FieldProps.hpp
Normal file
168
src/opm/parser/eclipse/EclipseState/Grid/FieldProps.hpp
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FIELDPROPS_HPP
|
||||
#define FIELDPROPS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Section.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/BoxManager.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class Deck;
|
||||
class EclipseGrid;
|
||||
|
||||
class FieldProps {
|
||||
public:
|
||||
|
||||
template<typename T>
|
||||
struct FieldData {
|
||||
std::vector<T> data;
|
||||
std::vector<bool> assigned;
|
||||
|
||||
|
||||
FieldData() = default;
|
||||
|
||||
FieldData(std::size_t active_size) :
|
||||
data(std::vector<T>(active_size)),
|
||||
assigned(std::vector<bool>(active_size, false))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::size_t size() const {
|
||||
return this->data.size();
|
||||
}
|
||||
|
||||
bool valid() const {
|
||||
const auto& it = std::find(this->assigned.begin(), this->assigned.end(), false);
|
||||
if (it == this->assigned.end())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void compress(const std::vector<bool>& active_map) {
|
||||
std::size_t shift = 0;
|
||||
for (std::size_t g = 0; g < active_map.size(); g++) {
|
||||
if (active_map[g] && shift > 0) {
|
||||
this->data[g - shift] = this->data[g];
|
||||
this->assigned[g - shift] = this->assigned[g];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!active_map[g])
|
||||
shift += 1;
|
||||
}
|
||||
|
||||
this->data.resize(this->data.size() - shift);
|
||||
this->assigned.resize(this->assigned.size() - shift);
|
||||
}
|
||||
|
||||
void assign(T value) {
|
||||
std::fill(this->data.begin(), this->data.end(), value);
|
||||
std::fill(this->assigned.begin(), this->assigned.end(), true);
|
||||
}
|
||||
|
||||
void assign(const FieldData<T>& src, const Box& box) {
|
||||
for (const auto& ci : box.index_list()) {
|
||||
if (src.assigned[ci.active_index]) {
|
||||
this->data[ci.active_index] = src.data[ci.active_index];
|
||||
this->assigned[ci.active_index] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
FieldProps(const Deck& deck, const EclipseGrid& grid);
|
||||
void reset_grid(const EclipseGrid& grid);
|
||||
|
||||
template <typename T>
|
||||
FieldData<T>& get(const std::string& keyword);
|
||||
|
||||
template <typename T>
|
||||
static bool supported(const std::string& keyword);
|
||||
|
||||
template <typename T>
|
||||
bool has(const std::string& keyword) const;
|
||||
|
||||
template <typename T>
|
||||
const FieldData<T>* try_get(const std::string& keyword) {
|
||||
const FieldData<T> * field_data;
|
||||
|
||||
try {
|
||||
field_data = std::addressof(this->get<T>(keyword));
|
||||
} catch (const std::out_of_range&) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (field_data->valid())
|
||||
return field_data;
|
||||
|
||||
this->erase<T>(keyword);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> global_copy(const std::vector<T>& data) const {
|
||||
std::vector<T> global_data(this->grid->getCartesianSize());
|
||||
std::size_t i = 0;
|
||||
for (std::size_t g = 0; g < this->grid->getCartesianSize(); g++) {
|
||||
if (this->grid->cellActive(g)) {
|
||||
global_data[g] = data[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return global_data;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void scanGRIDSection(const GRIDSection& grid_section);
|
||||
void scanPROPSSection(const PROPSSection& props_section);
|
||||
void scanREGIONSSection(const REGIONSSection& regions_section);
|
||||
double getSIValue(const std::string& keyword, double raw_value) const;
|
||||
template <typename T>
|
||||
void erase(const std::string& keyword);
|
||||
|
||||
template <typename T>
|
||||
static void handle_scalar_operation(const std::string& keyword, FieldData<T>& data, T scalar_value, const Box& box);
|
||||
void handle_scalar_operation(const DeckKeyword& keyword, BoxManager& box_manager);
|
||||
void handle_props_section_double_keyword(const DeckKeyword& keyword, const BoxManager& box_manager);
|
||||
void handle_grid_section_double_keyword(const DeckKeyword& keyword, const BoxManager& box_manager);
|
||||
void handle_int_keyword(const DeckKeyword& keyword, const BoxManager& box_manager);
|
||||
void handle_COPY(const DeckKeyword& keyword, BoxManager& box_manager);
|
||||
|
||||
const UnitSystem unit_system;
|
||||
const EclipseGrid* grid; // A reseatable pointer to const.
|
||||
std::size_t active_size;
|
||||
std::vector<int> actnum;
|
||||
const std::string default_region;
|
||||
std::unordered_map<std::string, FieldData<int>> int_data;
|
||||
std::unordered_map<std::string, FieldData<double>> double_data;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
|
||||
#include "FieldProps.hpp"
|
||||
|
||||
|
||||
namespace Opm {
|
||||
|
||||
FieldPropsManager::FieldPropsManager(const Deck& deck, const EclipseGrid& grid_arg) :
|
||||
fp(std::make_shared<FieldProps>(deck, grid_arg))
|
||||
{}
|
||||
|
||||
void FieldPropsManager::reset_grid(const EclipseGrid& grid) {
|
||||
this->fp->reset_grid(grid);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const std::vector<T>& FieldPropsManager::get(const std::string& keyword) const {
|
||||
const auto& data_ptr = this->try_get<T>(keyword);
|
||||
if (data_ptr)
|
||||
return *data_ptr;
|
||||
|
||||
if (!this->fp->has<T>(keyword))
|
||||
throw std::out_of_range("No such keyword in deck: " + keyword);
|
||||
|
||||
throw std::logic_error("Internal error - should not be here");
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
const std::vector<T>* FieldPropsManager::try_get(const std::string& keyword) const {
|
||||
const auto& data_ptr = this->fp->try_get<T>(keyword);
|
||||
if (data_ptr)
|
||||
return std::addressof(data_ptr->data);
|
||||
|
||||
if (!FieldProps::supported<T>(keyword))
|
||||
throw std::invalid_argument("The keyword: " + keyword + " is not supported");
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> FieldPropsManager::get_global(const std::string& keyword) const {
|
||||
const auto& data = this->get<T>(keyword);
|
||||
return this->fp->global_copy(data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool FieldPropsManager::supported(const std::string& keyword) {
|
||||
return FieldProps::supported<T>(keyword);
|
||||
}
|
||||
|
||||
template bool FieldPropsManager::supported<int>(const std::string&);
|
||||
template bool FieldPropsManager::supported<double>(const std::string&);
|
||||
|
||||
template std::vector<int> FieldPropsManager::get_global(const std::string& keyword) const;
|
||||
template std::vector<double> FieldPropsManager::get_global(const std::string& keyword) const;
|
||||
|
||||
template const std::vector<int>& FieldPropsManager::get(const std::string& keyword) const;
|
||||
template const std::vector<double>& FieldPropsManager::get(const std::string& keyword) const;
|
||||
|
||||
template const std::vector<int>* FieldPropsManager::try_get(const std::string& keyword) const;
|
||||
template const std::vector<double>* FieldPropsManager::try_get(const std::string& keyword) const;
|
||||
}
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
@ -263,12 +264,14 @@ struct Setup
|
||||
Opm::TableManager tablemanager;
|
||||
Opm::EclipseGrid grid;
|
||||
Opm::Eclipse3DProperties props;
|
||||
Opm::FieldPropsManager fp;
|
||||
|
||||
explicit Setup(Opm::Deck&& deckArg) :
|
||||
deck(std::move( deckArg ) ),
|
||||
tablemanager(deck),
|
||||
grid(deck),
|
||||
props(deck, tablemanager, grid)
|
||||
props(deck, tablemanager, grid),
|
||||
fp(deck, grid)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -277,22 +280,26 @@ struct Setup
|
||||
BOOST_AUTO_TEST_CASE(HasDeckProperty) {
|
||||
Setup s(createDeck());
|
||||
BOOST_CHECK(s.props.hasDeckIntGridProperty("SATNUM"));
|
||||
BOOST_CHECK(s.fp.try_get<int>("SATNUM") != nullptr);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(SupportsProperty) {
|
||||
Setup s(createDeck());
|
||||
std::vector<std::string> keywordList = {
|
||||
// int props
|
||||
"ACTNUM", "SATNUM", "IMBNUM", "PVTNUM", "EQLNUM", "ENDNUM", "FLUXNUM", "MULTNUM", "FIPNUM", "MISCNUM", "OPERNUM", "ROCKNUM",
|
||||
// double props
|
||||
"TEMPI", "MULTPV", "PERMX", "permy", "PERMZ", "SWATINIT", "THCONR", "NTG"
|
||||
};
|
||||
std::vector<std::string> int_keywords = {"SATNUM", "IMBNUM", "PVTNUM", "EQLNUM", "ENDNUM", "FLUXNUM", "MULTNUM", "FIPNUM", "MISCNUM", "OPERNUM", "ROCKNUM"};
|
||||
std::vector<std::string> double_keywords = {"TEMPI", "MULTPV", "PERMX", "PERMY", "PERMZ", "SWATINIT", "THCONR", "NTG"};
|
||||
|
||||
for (auto keyword : keywordList)
|
||||
for (auto keyword : int_keywords) {
|
||||
BOOST_CHECK(s.props.supportsGridProperty(keyword));
|
||||
BOOST_CHECK(s.fp.supported<int>(keyword));
|
||||
}
|
||||
|
||||
for (auto keyword : double_keywords) {
|
||||
BOOST_CHECK(s.props.supportsGridProperty(keyword));
|
||||
BOOST_CHECK(s.fp.supported<double>(keyword));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DefaultRegionFluxnum) {
|
||||
Setup s(createDeck());
|
||||
BOOST_CHECK_EQUAL(s.props.getDefaultRegionKeyword(), "FLUXNUM");
|
||||
@ -305,6 +312,8 @@ BOOST_AUTO_TEST_CASE(UnsupportedKeywordsThrows) {
|
||||
|
||||
BOOST_CHECK_THROW(s.props.getIntGridProperty("NONO"), std::logic_error);
|
||||
BOOST_CHECK_THROW(s.props.getDoubleGridProperty("NONO"), std::logic_error);
|
||||
BOOST_CHECK_THROW(s.fp.get<double>("NONO"), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(s.fp.get<int>("NONO"), std::invalid_argument);
|
||||
|
||||
BOOST_CHECK_NO_THROW(s.props.hasDeckIntGridProperty("FluxNUM"));
|
||||
BOOST_CHECK_NO_THROW(s.props.supportsGridProperty("NONO"));
|
||||
@ -312,12 +321,22 @@ BOOST_AUTO_TEST_CASE(UnsupportedKeywordsThrows) {
|
||||
|
||||
BOOST_AUTO_TEST_CASE(IntGridProperty) {
|
||||
Setup s(createDeck());
|
||||
int cnt = 0;
|
||||
for (auto x : s.props.getIntGridProperty("SaTNuM").getData()) {
|
||||
BOOST_CHECK_EQUAL(x, 2);
|
||||
cnt++;
|
||||
{
|
||||
int cnt = 0;
|
||||
for (auto x : s.props.getIntGridProperty("SATNUM").getData()) {
|
||||
BOOST_CHECK_EQUAL(x, 2);
|
||||
cnt++;
|
||||
}
|
||||
BOOST_CHECK_EQUAL(cnt, 1000);
|
||||
}
|
||||
{
|
||||
int cnt = 0;
|
||||
for (auto x : s.fp.get_global<int>("SATNUM")) {
|
||||
BOOST_CHECK_EQUAL(x, 2);
|
||||
cnt++;
|
||||
}
|
||||
BOOST_CHECK_EQUAL(cnt, 1000);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(cnt, 1000);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AddregIntSetCorrectly) {
|
||||
|
@ -675,7 +675,7 @@ BOOST_AUTO_TEST_CASE(TestBox) {
|
||||
"1 1 2 3 /\n";
|
||||
Parser parser;
|
||||
auto deck = parser.parseString(regionData);
|
||||
EclipseState state(deck);
|
||||
EclipseState state(deck);
|
||||
|
||||
}
|
||||
|
||||
|
135
tests/parser/FieldPropsTests.cpp
Normal file
135
tests/parser/FieldPropsTests.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#define BOOST_TEST_MODULE FieldPropsTests
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Section.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
|
||||
|
||||
using namespace Opm;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateFieldProps) {
|
||||
EclipseGrid grid(10,10,10);
|
||||
Deck deck;
|
||||
FieldPropsManager fpm(deck, grid);
|
||||
BOOST_CHECK(!fpm.try_get<int>("SATNUM"));
|
||||
BOOST_CHECK(!fpm.try_get<double>("PORO"));
|
||||
BOOST_CHECK(!fpm.try_get<int>("SATNUM"));
|
||||
BOOST_CHECK(!fpm.try_get<double>("PORO"));
|
||||
BOOST_CHECK_THROW(fpm.get<double>("PORO"), std::out_of_range);
|
||||
BOOST_CHECK_THROW(fpm.get<int>("SATNUM"), std::out_of_range);
|
||||
BOOST_CHECK_THROW(fpm.get_global<double>("PORO"), std::out_of_range);
|
||||
BOOST_CHECK_THROW(fpm.get_global<int>("SATNUM"), std::out_of_range);
|
||||
BOOST_CHECK_THROW(fpm.try_get<int>("NOT_SUPPORTED"), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(fpm.try_get<double>("NOT_SUPPORTED"), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(fpm.get<int>("NOT_SUPPORTED"), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(fpm.get<double>("NOT_SUPPORTED"), std::invalid_argument);
|
||||
|
||||
BOOST_CHECK_THROW(fpm.get_global<double>("NO1"), std::invalid_argument);
|
||||
BOOST_CHECK_THROW(fpm.get_global<int>("NO2"), std::invalid_argument);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateFieldProps2) {
|
||||
std::string deck_string = R"(
|
||||
GRID
|
||||
|
||||
PORO
|
||||
1000*0.10 /
|
||||
)";
|
||||
std::vector<int> actnum(1000, 1);
|
||||
for (std::size_t i=0; i< 1000; i += 2)
|
||||
actnum[i] = 0;
|
||||
EclipseGrid grid(EclipseGrid(10,10,10), actnum);
|
||||
Deck deck = Parser{}.parseString(deck_string);
|
||||
FieldPropsManager fpm(deck, grid);
|
||||
|
||||
|
||||
const auto& poro1 = fpm.get<double>("PORO");
|
||||
BOOST_CHECK_EQUAL(poro1.size(), grid.getNumActive());
|
||||
|
||||
const auto& poro2 = fpm.try_get<double>("PORO");
|
||||
BOOST_CHECK(poro1 == *poro2);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(INVALID_COPY) {
|
||||
std::string deck_string = R"(
|
||||
GRID
|
||||
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
/
|
||||
)";
|
||||
|
||||
EclipseGrid grid(EclipseGrid(10,10,10));
|
||||
Deck deck = Parser{}.parseString(deck_string);
|
||||
BOOST_CHECK_THROW( FieldPropsManager(deck, grid), std::invalid_argument);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GRID_RESET) {
|
||||
std::string deck_string = R"(
|
||||
REGIONS
|
||||
|
||||
SATNUM
|
||||
0 1 2 3 4 5 6 7 8
|
||||
/
|
||||
)";
|
||||
std::vector<int> actnum1 = {1,1,1,0,0,0,1,1,1};
|
||||
EclipseGrid grid(3,1,3); grid.resetACTNUM(actnum1);
|
||||
Deck deck = Parser{}.parseString(deck_string);
|
||||
FieldPropsManager fpm(deck, grid);
|
||||
const auto& s1 = fpm.get<int>("SATNUM");
|
||||
BOOST_CHECK_EQUAL(s1.size(), 6);
|
||||
BOOST_CHECK_EQUAL(s1[0], 0);
|
||||
BOOST_CHECK_EQUAL(s1[1], 1);
|
||||
BOOST_CHECK_EQUAL(s1[2], 2);
|
||||
BOOST_CHECK_EQUAL(s1[3], 6);
|
||||
BOOST_CHECK_EQUAL(s1[4], 7);
|
||||
BOOST_CHECK_EQUAL(s1[5], 8);
|
||||
|
||||
std::vector<int> actnum2 = {1,0,1,0,0,0,1,0,1};
|
||||
grid.resetACTNUM(actnum2);
|
||||
fpm.reset_grid(grid);
|
||||
|
||||
BOOST_CHECK_EQUAL(s1.size(), 4);
|
||||
BOOST_CHECK_EQUAL(s1[0], 0);
|
||||
BOOST_CHECK_EQUAL(s1[1], 2);
|
||||
BOOST_CHECK_EQUAL(s1[2], 6);
|
||||
BOOST_CHECK_EQUAL(s1[3], 8);
|
||||
|
||||
grid.resetACTNUM(actnum1);
|
||||
BOOST_CHECK_THROW(fpm.reset_grid(grid), std::logic_error);
|
||||
}
|
Loading…
Reference in New Issue
Block a user