Merge pull request #1905 from joakim-hove/fp-global2
Enable some support for global keywords
This commit is contained in:
@@ -151,7 +151,7 @@ void verify_deck_data(const DeckKeyword& keyword, const std::vector<T>& deck_dat
|
||||
|
||||
|
||||
template <typename T>
|
||||
void assign_deck(const DeckKeyword& keyword, FieldProps::FieldData<T>& field_data, const std::vector<T>& deck_data, const std::vector<value::status>& deck_status, const Box& box) {
|
||||
void assign_deck(const keywords::keyword_info<T>& kw_info, const DeckKeyword& keyword, FieldProps::FieldData<T>& field_data, const std::vector<T>& deck_data, const std::vector<value::status>& deck_status, const Box& box) {
|
||||
verify_deck_data(keyword, deck_data, box);
|
||||
for (const auto& cell_index : box.index_list()) {
|
||||
auto active_index = cell_index.active_index;
|
||||
@@ -164,11 +164,24 @@ void assign_deck(const DeckKeyword& keyword, FieldProps::FieldData<T>& field_dat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kw_info.global) {
|
||||
auto& global_data = field_data.global_data.value();
|
||||
auto& global_status = field_data.global_value_status.value();
|
||||
const auto& index_list = box.global_index_list();
|
||||
|
||||
for (const auto& cell : index_list) {
|
||||
if (deck_status[cell.data_index] == value::status::deck_value || global_status[cell.global_index] == value::status::uninitialized) {
|
||||
global_data[cell.global_index] = deck_data[cell.data_index];
|
||||
global_status[cell.global_index] = deck_status[cell.data_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void multiply_deck(const DeckKeyword& keyword, FieldProps::FieldData<T>& field_data, const std::vector<T>& deck_data, const std::vector<value::status>& deck_status, const Box& box) {
|
||||
void multiply_deck(const keywords::keyword_info<T>& kw_info, const DeckKeyword& keyword, FieldProps::FieldData<T>& field_data, const std::vector<T>& deck_data, const std::vector<value::status>& deck_status, const Box& box) {
|
||||
verify_deck_data(keyword, deck_data, box);
|
||||
for (const auto& cell_index : box.index_list()) {
|
||||
auto active_index = cell_index.active_index;
|
||||
@@ -179,49 +192,86 @@ void multiply_deck(const DeckKeyword& keyword, FieldProps::FieldData<T>& field_d
|
||||
field_data.value_status[active_index] = deck_status[data_index];
|
||||
}
|
||||
}
|
||||
|
||||
if (kw_info.global) {
|
||||
auto& global_data = field_data.global_data.value();
|
||||
auto& global_status = field_data.global_value_status.value();
|
||||
const auto& index_list = box.global_index_list();
|
||||
|
||||
for (const auto& cell : index_list) {
|
||||
if (deck_status[cell.data_index] == value::status::deck_value || global_status[cell.global_index] == value::status::uninitialized) {
|
||||
global_data[cell.global_index] *= deck_data[cell.data_index];
|
||||
global_status[cell.global_index] = deck_status[cell.data_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void distribute_toplayer(const EclipseGrid& grid, FieldProps::FieldData<double>& field_data, const std::vector<double>& deck_data, const Box& box) {
|
||||
const std::size_t layer_size = grid.getNX() * grid.getNY();
|
||||
FieldProps::FieldData<double> toplayer(keywords::keyword_info<double>(), grid.getNX() * grid.getNY(), 0);
|
||||
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.value_status[cell_index.global_index] = value::status::deck_value;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t active_index = 0; active_index < field_data.size(); active_index++) {
|
||||
if (field_data.value_status[active_index] == value::status::uninitialized) {
|
||||
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.value_status[layer_index] == value::status::deck_value) {
|
||||
field_data.data[active_index] = toplayer.data[layer_index];
|
||||
field_data.value_status[active_index] = value::status::valid_default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void assign_scalar(FieldProps::FieldData<T>& field_data, T value, const std::vector<Box::cell_index>& index_list) {
|
||||
void assign_scalar(std::vector<T>& data, std::vector<value::status>& value_status, 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.value_status[cell_index.active_index] = value::status::deck_value;
|
||||
data[cell_index.active_index] = value;
|
||||
value_status[cell_index.active_index] = value::status::deck_value;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void multiply_scalar(FieldProps::FieldData<T>& field_data, T value, const std::vector<Box::cell_index>& index_list) {
|
||||
void multiply_scalar(std::vector<T>& data, std::vector<value::status>& value_status, T value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (value::has_value(field_data.value_status[cell_index.active_index]))
|
||||
field_data.data[cell_index.active_index] *= value;
|
||||
if (value::has_value(value_status[cell_index.active_index]))
|
||||
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) {
|
||||
void add_scalar(std::vector<T>& data, std::vector<value::status>& value_status, T value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (value::has_value(field_data.value_status[cell_index.active_index]))
|
||||
field_data.data[cell_index.active_index] += value;
|
||||
if (value::has_value(value_status[cell_index.active_index]))
|
||||
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) {
|
||||
void min_value(std::vector<T>& data, std::vector<value::status>& value_status, T min_value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (value::has_value(field_data.value_status[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);
|
||||
if (value::has_value(value_status[cell_index.active_index])) {
|
||||
T value = data[cell_index.active_index];
|
||||
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) {
|
||||
void max_value(std::vector<T>& data, std::vector<value::status>& value_status, T max_value, const std::vector<Box::cell_index>& index_list) {
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (value::has_value(field_data.value_status[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);
|
||||
if (value::has_value(value_status[cell_index.active_index])) {
|
||||
T value = data[cell_index.active_index];
|
||||
data[cell_index.active_index] = std::min(value, max_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,7 +429,7 @@ void FieldProps::reset_actnum(const std::vector<int>& new_actnum) {
|
||||
|
||||
void FieldProps::distribute_toplayer(FieldProps::FieldData<double>& field_data, const std::vector<double>& deck_data, const Box& box) {
|
||||
const std::size_t layer_size = this->nx * this->ny;
|
||||
FieldProps::FieldData<double> toplayer(field_data.kw_info, layer_size);
|
||||
FieldProps::FieldData<double> toplayer(field_data.kw_info, layer_size, 0);
|
||||
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];
|
||||
@@ -450,7 +500,7 @@ FieldProps::FieldData<double>& FieldProps::init_get(const std::string& keyword)
|
||||
return iter->second;
|
||||
|
||||
const keywords::keyword_info<double>& kw_info = keywords::global_kw_info<double>(keyword);
|
||||
this->double_data[keyword] = FieldData<double>(kw_info, this->active_size);
|
||||
this->double_data[keyword] = FieldData<double>(kw_info, this->active_size, kw_info.global ? this->global_size : 0);
|
||||
|
||||
if (keyword == ParserKeywords::PORV::keywordName)
|
||||
this->init_porv(this->double_data[keyword]);
|
||||
@@ -476,16 +526,17 @@ FieldProps::FieldData<int>& FieldProps::init_get(const std::string& keyword) {
|
||||
if (keywords::isFipxxx(keyword)) {
|
||||
auto kw_info = keywords::keyword_info<int>{};
|
||||
kw_info.init(1);
|
||||
this->int_data[keyword] = FieldData<int>(kw_info, this->active_size);
|
||||
this->int_data[keyword] = FieldData<int>(kw_info, this->active_size, 0);
|
||||
} else {
|
||||
const keywords::keyword_info<int>& kw_info = keywords::global_kw_info<int>(keyword);
|
||||
this->int_data[keyword] = FieldData<int>(kw_info, this->active_size);
|
||||
this->int_data[keyword] = FieldData<int>(kw_info, this->active_size, kw_info.global ? this->global_size : 0);
|
||||
}
|
||||
|
||||
|
||||
return this->int_data[keyword];
|
||||
}
|
||||
|
||||
|
||||
std::vector<Box::cell_index> FieldProps::region_index( const std::string& region_name, int region_value ) {
|
||||
const auto& region = this->init_get<int>(region_name);
|
||||
if (!region.valid())
|
||||
@@ -504,12 +555,12 @@ std::vector<Box::cell_index> FieldProps::region_index( const std::string& region
|
||||
return index_list;
|
||||
}
|
||||
|
||||
std::vector<Box::cell_index> FieldProps::region_index( const DeckItem& region_item, int region_value ) {
|
||||
std::string region_name = region_item.defaultApplied(0) ? this->m_default_region : make_region_name(region_item.get<std::string>(0));
|
||||
return this->region_index(region_name, region_value);
|
||||
}
|
||||
|
||||
|
||||
std::string FieldProps::region_name(const DeckItem& region_item) {
|
||||
return region_item.defaultApplied(0) ? this->m_default_region : make_region_name(region_item.get<std::string>(0));
|
||||
}
|
||||
|
||||
template <>
|
||||
bool FieldProps::has<double>(const std::string& keyword) const {
|
||||
return (this->double_data.count(keyword) != 0);
|
||||
@@ -594,11 +645,11 @@ double FieldProps::getSIValue(const std::string& keyword, double raw_value) cons
|
||||
|
||||
|
||||
|
||||
void FieldProps::handle_int_keyword(const DeckKeyword& keyword, const Box& box) {
|
||||
void FieldProps::handle_int_keyword(const keywords::keyword_info<int>& kw_info, const DeckKeyword& keyword, const Box& box) {
|
||||
auto& field_data = this->init_get<int>(keyword.name());
|
||||
const auto& deck_data = keyword.getIntData();
|
||||
const auto& deck_status = keyword.getValueStatus();
|
||||
assign_deck(keyword, field_data, deck_data, deck_status, box);
|
||||
assign_deck(kw_info, keyword, field_data, deck_data, deck_status, box);
|
||||
}
|
||||
|
||||
|
||||
@@ -608,9 +659,9 @@ void FieldProps::handle_double_keyword(Section section, const keywords::keyword_
|
||||
const auto& deck_status = keyword.getValueStatus();
|
||||
|
||||
if (section == Section::EDIT && kw_info.multiplier)
|
||||
multiply_deck(keyword, field_data, deck_data, deck_status, box);
|
||||
multiply_deck(kw_info, keyword, field_data, deck_data, deck_status, box);
|
||||
else
|
||||
assign_deck(keyword, field_data, deck_data, deck_status, box);
|
||||
assign_deck(kw_info, keyword, field_data, deck_data, deck_status, box);
|
||||
|
||||
|
||||
if (section == Section::GRID) {
|
||||
@@ -626,21 +677,21 @@ void FieldProps::handle_double_keyword(Section section, const keywords::keyword_
|
||||
|
||||
|
||||
template <typename T>
|
||||
void FieldProps::apply(ScalarOperation op, FieldData<T>& data, T scalar_value, const std::vector<Box::cell_index>& index_list) {
|
||||
void FieldProps::apply(ScalarOperation op, std::vector<T>& data, std::vector<value::status>& value_status, T scalar_value, const std::vector<Box::cell_index>& index_list) {
|
||||
if (op == ScalarOperation::EQUAL)
|
||||
assign_scalar(data, scalar_value, index_list);
|
||||
assign_scalar(data, value_status, scalar_value, index_list);
|
||||
|
||||
else if (op == ScalarOperation::MUL)
|
||||
multiply_scalar(data, scalar_value, index_list);
|
||||
multiply_scalar(data, value_status, scalar_value, index_list);
|
||||
|
||||
else if (op == ScalarOperation::ADD)
|
||||
add_scalar(data, scalar_value, index_list);
|
||||
add_scalar(data, value_status, scalar_value, index_list);
|
||||
|
||||
else if (op == ScalarOperation::MIN)
|
||||
min_value(data, scalar_value, index_list);
|
||||
min_value(data, value_status, scalar_value, index_list);
|
||||
|
||||
else if (op == ScalarOperation::MAX)
|
||||
max_value(data, scalar_value, index_list);
|
||||
max_value(data, value_status, scalar_value, index_list);
|
||||
}
|
||||
|
||||
double FieldProps::get_alpha(const std::string& func_name, const std::string& target_array, double raw_alpha) {
|
||||
@@ -658,7 +709,7 @@ double FieldProps::get_beta(const std::string& func_name, const std::string& tar
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void FieldProps::apply(const DeckRecord& record, FieldData<T>& target_data, const FieldData<T>& src_data, const std::vector<Box::cell_index>& index_list) {
|
||||
void FieldProps::operate(const DeckRecord& record, FieldData<T>& target_data, const FieldData<T>& src_data, const std::vector<Box::cell_index>& index_list) {
|
||||
const std::string& func_name = record.getItem("OPERATION").get< std::string >(0);
|
||||
const std::string& target_array = record.getItem("TARGET_ARRAY").get<std::string>(0);
|
||||
const double alpha = this->get_alpha(func_name, target_array, record.getItem("PARAM1").get< double >(0));
|
||||
@@ -666,6 +717,9 @@ void FieldProps::apply(const DeckRecord& record, FieldData<T>& target_data, cons
|
||||
Operate::function func = Operate::get( func_name, alpha, beta );
|
||||
bool check_target = (func_name == "MULTIPLY" || func_name == "POLY");
|
||||
|
||||
if (target_data.global_data)
|
||||
throw std::logic_error("The OPERATE and OPERATER keywords are not supported for keywords with global storage");
|
||||
|
||||
for (const auto& cell_index : index_list) {
|
||||
if (value::has_value(src_data.value_status[cell_index.active_index])) {
|
||||
if ((check_target == false) || (value::has_value(target_data.value_status[cell_index.active_index]))) {
|
||||
@@ -685,20 +739,34 @@ void FieldProps::handle_region_operation(const DeckKeyword& keyword) {
|
||||
|
||||
if (FieldProps::supported<double>(target_kw)) {
|
||||
auto& field_data = this->init_get<double>(target_kw);
|
||||
/*
|
||||
To support region operations on keywords with global storage we
|
||||
would need to also have global storage for the xxxNUM region
|
||||
keywords involved. To avoid a situation where a significant
|
||||
fraction of the keywords have global storage the implementation
|
||||
has stopped here - there are no principle problems with extending
|
||||
the implementation to also support region operations on fields
|
||||
with global storage.
|
||||
*/
|
||||
if (field_data.global_data)
|
||||
throw std::logic_error("Region operations on 3D fields with global storage is not implemented");
|
||||
|
||||
if (keyword.name() == ParserKeywords::OPERATER::keywordName) {
|
||||
// For the OPERATER keyword we fetch the region name from the deck record
|
||||
// with no extra hoops.
|
||||
const auto& index_list = this->region_index(record.getItem("REGION_NAME").get<std::string>(0), region_value);
|
||||
std::string region_name = record.getItem("REGION_NAME").get<std::string>(0);
|
||||
const auto& index_list = this->region_index(region_name, region_value);
|
||||
const std::string& src_kw = record.getItem("ARRAY_PARAMETER").get<std::string>(0);
|
||||
const auto& src_data = this->init_get<double>(src_kw);
|
||||
FieldProps::apply(record, field_data, src_data, index_list);
|
||||
FieldProps::operate(record, field_data, src_data, index_list);
|
||||
} else {
|
||||
double value = record.getItem(1).get<double>(0);
|
||||
const auto& index_list = this->region_index(record.getItem("REGION_NAME"), region_value);
|
||||
std::string region_name = this->region_name( record.getItem("REGION_NAME") );
|
||||
const auto& index_list = this->region_index( region_name, region_value);
|
||||
if (keyword.name() != ParserKeywords::MULTIPLY::keywordName)
|
||||
value = this->getSIValue(target_kw, value);
|
||||
FieldProps::apply(fromString(keyword.name()), field_data, value, index_list);
|
||||
|
||||
FieldProps::apply(fromString(keyword.name()), field_data.data, field_data.value_status, value, index_list);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -724,12 +792,14 @@ void FieldProps::handle_operation(const DeckKeyword& keyword, Box box) {
|
||||
if (keyword.name() == ParserKeywords::OPERATE::keywordName) {
|
||||
const std::string& src_kw = record.getItem("ARRAY").get<std::string>(0);
|
||||
const auto& src_data = this->init_get<double>(src_kw);
|
||||
FieldProps::apply(record, field_data, src_data, box.index_list());
|
||||
FieldProps::operate(record, field_data, src_data, box.index_list());
|
||||
} else {
|
||||
double scalar_value = record.getItem(1).get<double>(0);
|
||||
if (keyword.name() != ParserKeywords::MULTIPLY::keywordName)
|
||||
scalar_value = this->getSIValue(target_kw, scalar_value);
|
||||
FieldProps::apply(fromString(keyword.name()), field_data, scalar_value, box.index_list());
|
||||
FieldProps::apply(fromString(keyword.name()), field_data.data, field_data.value_status, scalar_value, box.index_list());
|
||||
if (field_data.global_data)
|
||||
FieldProps::apply(fromString(keyword.name()), *field_data.global_data, *field_data.global_value_status, scalar_value, box.global_index_list());
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -739,7 +809,7 @@ void FieldProps::handle_operation(const DeckKeyword& keyword, Box box) {
|
||||
if (FieldProps::supported<int>(target_kw)) {
|
||||
int scalar_value = static_cast<int>(record.getItem(1).get<double>(0));
|
||||
auto& field_data = this->init_get<int>(target_kw);
|
||||
FieldProps::apply(fromString(keyword.name()), field_data, scalar_value, box.index_list());
|
||||
FieldProps::apply(fromString(keyword.name()), field_data.data, field_data.value_status, scalar_value, box.index_list());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -757,7 +827,8 @@ void FieldProps::handle_COPY(const DeckKeyword& keyword, Box box, bool region) {
|
||||
if (region) {
|
||||
int region_value = record.getItem(2).get<int>(0);
|
||||
const auto& region_item = record.getItem(4);
|
||||
index_list = this->region_index(region_item, region_value);
|
||||
const auto& region_name = this->region_name( region_item );
|
||||
index_list = this->region_index(region_name, region_value);
|
||||
} else {
|
||||
box.update(record);
|
||||
index_list = box.index_list();
|
||||
@@ -915,7 +986,7 @@ void FieldProps::scanGRIDSection(const GRIDSection& grid_section) {
|
||||
}
|
||||
|
||||
if (keywords::GRID::int_keywords.count(name) == 1) {
|
||||
this->handle_int_keyword(keyword, box);
|
||||
this->handle_int_keyword(keywords::GRID::int_keywords.at(name), keyword, box);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -933,7 +1004,7 @@ void FieldProps::scanEDITSection(const EDITSection& edit_section) {
|
||||
}
|
||||
|
||||
if (keywords::EDIT::int_keywords.count(name) == 1) {
|
||||
this->handle_int_keyword(keyword, box);
|
||||
this->handle_int_keyword(keywords::GRID::int_keywords.at(name), keyword, box);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -973,7 +1044,7 @@ void FieldProps::scanPROPSSection(const PROPSSection& props_section) {
|
||||
}
|
||||
|
||||
if (keywords::PROPS::int_keywords.count(name) == 1) {
|
||||
this->handle_int_keyword(keyword, box);
|
||||
this->handle_int_keyword(keywords::PROPS::int_keywords.at(name), keyword, box);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -987,8 +1058,15 @@ void FieldProps::scanREGIONSSection(const REGIONSSection& regions_section) {
|
||||
|
||||
for (const auto& keyword : regions_section) {
|
||||
const std::string& name = keyword.name();
|
||||
if (keywords::REGIONS::int_keywords.count(name) == 1 || keywords::isFipxxx(name)) {
|
||||
this->handle_int_keyword(keyword, box);
|
||||
if (keywords::REGIONS::int_keywords.count(name)) {
|
||||
this->handle_int_keyword(keywords::REGIONS::int_keywords.at(name), keyword, box);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keywords::isFipxxx(name)) {
|
||||
auto kw_info = keywords::keyword_info<int>{};
|
||||
kw_info.init(1);
|
||||
this->handle_int_keyword(kw_info, keyword, box);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1020,7 +1098,7 @@ void FieldProps::scanSCHEDULESection(const SCHEDULESection& schedule_section) {
|
||||
}
|
||||
|
||||
if (keywords::SCHEDULE::int_keywords.count(name) == 1) {
|
||||
this->handle_int_keyword(keyword, box);
|
||||
this->handle_int_keyword(keywords::SCHEDULE::int_keywords.at(name), keyword, box);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,48 @@ class TableManager;
|
||||
|
||||
namespace keywords {
|
||||
|
||||
/*
|
||||
Regarding global keywords
|
||||
=========================
|
||||
|
||||
It turns out that when the option 'ALL' is used for the PINCH keyword we
|
||||
require the MULTZ keyword specified for all cells, also the inactive cells.
|
||||
The premise for the FieldProps implementation has all the way been that only
|
||||
the active cells should be stored.
|
||||
|
||||
In order to support the ALL option of the PINCH keyword we have bolted on a
|
||||
limited support for global storage. By setting .global = true in the
|
||||
keyword_info describing the keyword you get:
|
||||
|
||||
1. Normal deck assignment like
|
||||
|
||||
MULTZ
|
||||
..... /
|
||||
|
||||
2. Scalar operations like EQUALS and MULTIPLY.
|
||||
|
||||
These operations also support the full details of the BOX behavior.
|
||||
|
||||
The following operations do not work
|
||||
------------------------------------
|
||||
|
||||
1. Operations involving multiple keywords like
|
||||
|
||||
COPY
|
||||
MULTX MULTZ /
|
||||
/
|
||||
|
||||
this also includes the OPERATE which involves multiple keywords for some
|
||||
of its operations.
|
||||
|
||||
2. All region operatins like EQUALREG and MULTREG.
|
||||
|
||||
The operations which are not properly implemented will be intercepted and a
|
||||
std::logic_error() exception will be thrown.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct keyword_info {
|
||||
std::optional<std::string> unit = std::nullopt;
|
||||
@@ -105,7 +147,7 @@ static const std::unordered_map<std::string, keyword_info<double>> double_keywor
|
||||
{"MULTX-", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTY", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTY-", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTZ", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTZ", keyword_info<double>{}.init(1.0).mult(true).global_kw(true)},
|
||||
{"MULTZ-", keyword_info<double>{}.init(1.0).mult(true)}};
|
||||
|
||||
static const std::unordered_map<std::string, keyword_info<int>> int_keywords = {{"ACTNUM", keyword_info<int>{}.init(1)},
|
||||
@@ -127,7 +169,7 @@ static const std::unordered_map<std::string, keyword_info<double>> double_keywor
|
||||
{"MULTX-", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTY", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTY-", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTZ", keyword_info<double>{}.init(1.0).mult(true)},
|
||||
{"MULTZ", keyword_info<double>{}.init(1.0).mult(true).global_kw(true)},
|
||||
{"MULTZ-", keyword_info<double>{}.init(1.0).mult(true)}};
|
||||
|
||||
static const std::unordered_map<std::string, keyword_info<int>> int_keywords = {};
|
||||
@@ -290,16 +332,23 @@ public:
|
||||
std::vector<T> data;
|
||||
std::vector<value::status> value_status;
|
||||
keywords::keyword_info<T> kw_info;
|
||||
std::optional<std::vector<T>> global_data;
|
||||
std::optional<std::vector<value::status>> global_value_status;
|
||||
mutable bool all_set;
|
||||
|
||||
FieldData() = default;
|
||||
|
||||
FieldData(const keywords::keyword_info<T>& info, std::size_t active_size) :
|
||||
FieldData(const keywords::keyword_info<T>& info, std::size_t active_size, std::size_t global_size) :
|
||||
data(std::vector<T>(active_size)),
|
||||
value_status(active_size, value::status::uninitialized),
|
||||
kw_info(info),
|
||||
all_set(false)
|
||||
{
|
||||
if (global_size != 0) {
|
||||
this->global_data = std::vector<T>(global_size);
|
||||
this->global_value_status = std::vector<value::status>(global_size, value::status::uninitialized);
|
||||
}
|
||||
|
||||
if (info.scalar_init)
|
||||
this->default_assign( *info.scalar_init );
|
||||
}
|
||||
@@ -335,6 +384,11 @@ public:
|
||||
void default_assign(T value) {
|
||||
std::fill(this->data.begin(), this->data.end(), value);
|
||||
std::fill(this->value_status.begin(), this->value_status.end(), value::status::valid_default);
|
||||
|
||||
if (this->global_data) {
|
||||
std::fill(this->global_data->begin(), this->global_data->end(), value);
|
||||
std::fill(this->global_value_status->begin(), this->global_value_status->end(), value::status::valid_default);
|
||||
}
|
||||
}
|
||||
|
||||
void default_assign(const std::vector<T>& src) {
|
||||
@@ -466,7 +520,10 @@ public:
|
||||
const auto& managed_field_data = this->try_get<T>(keyword);
|
||||
const auto& field_data = managed_field_data.field_data();
|
||||
const auto& kw_info = keywords::global_kw_info<T>(keyword);
|
||||
return this->global_copy(field_data.data, kw_info.scalar_init);
|
||||
if (kw_info.global)
|
||||
return *field_data.global_data;
|
||||
else
|
||||
return this->global_copy(field_data.data, kw_info.scalar_init);
|
||||
}
|
||||
|
||||
|
||||
@@ -542,15 +599,15 @@ private:
|
||||
std::vector<T> extract(const std::string& keyword);
|
||||
|
||||
template <typename T>
|
||||
void apply(const DeckRecord& record, FieldData<T>& target_data, const FieldData<T>& src_data, const std::vector<Box::cell_index>& index_list);
|
||||
void operate(const DeckRecord& record, FieldData<T>& target_data, const FieldData<T>& src_data, const std::vector<Box::cell_index>& index_list);
|
||||
|
||||
template <typename T>
|
||||
static void apply(ScalarOperation op, FieldData<T>& data, T scalar_value, const std::vector<Box::cell_index>& index_list);
|
||||
static void apply(ScalarOperation op, std::vector<T>& data, std::vector<value::status>& value_status, T scalar_value, const std::vector<Box::cell_index>& index_list);
|
||||
|
||||
template <typename T>
|
||||
FieldData<T>& init_get(const std::string& keyword);
|
||||
|
||||
std::vector<Box::cell_index> region_index( const DeckItem& regionItem, int region_value );
|
||||
std::string region_name(const DeckItem& region_item);
|
||||
std::vector<Box::cell_index> region_index( const std::string& region_name, int region_value );
|
||||
void handle_operation(const DeckKeyword& keyword, Box box);
|
||||
void handle_region_operation(const DeckKeyword& keyword);
|
||||
@@ -561,7 +618,7 @@ private:
|
||||
|
||||
void handle_keyword(const DeckKeyword& keyword, Box& box);
|
||||
void handle_double_keyword(Section section, const keywords::keyword_info<double>& kw_info, const DeckKeyword& keyword, const Box& box);
|
||||
void handle_int_keyword(const DeckKeyword& keyword, const Box& box);
|
||||
void handle_int_keyword(const keywords::keyword_info<int>& kw_info, const DeckKeyword& keyword, const Box& box);
|
||||
void init_satfunc(const std::string& keyword, FieldData<double>& satfunc);
|
||||
void init_porv(FieldData<double>& porv);
|
||||
void init_tempi(FieldData<double>& tempi);
|
||||
|
||||
@@ -208,7 +208,7 @@ ADDREG
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ASSIGN) {
|
||||
FieldProps::FieldData<int> data({}, 100);
|
||||
FieldProps::FieldData<int> data({}, 100, 0);
|
||||
std::vector<int> wrong_size(50);
|
||||
|
||||
BOOST_CHECK_THROW( data.default_assign( wrong_size ), std::invalid_argument );
|
||||
@@ -1599,3 +1599,182 @@ FIPXYZ
|
||||
BOOST_CHECK_EQUAL(fipxyz[0], 1);
|
||||
BOOST_CHECK_EQUAL(fipxyz[100], 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GLOBAL_FIELD1) {
|
||||
std::string deck_string = R"(
|
||||
GRID
|
||||
|
||||
PORO
|
||||
27*0.10 /
|
||||
|
||||
ACTNUM
|
||||
9*1 9*0 9*1 /
|
||||
|
||||
MULTZ
|
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 /
|
||||
|
||||
)";
|
||||
std::vector<int> actnum(27, 1);
|
||||
for (std::size_t i=9; i< 18; i++)
|
||||
actnum[i] = 0;
|
||||
EclipseGrid grid(EclipseGrid(3,3,3), actnum);
|
||||
Deck deck = Parser{}.parseString(deck_string);
|
||||
FieldPropsManager fpm(deck, Phases{true, true, true}, grid, TableManager());
|
||||
|
||||
auto multz = fpm.get_double("MULTZ");
|
||||
auto multz_global = fpm.get_global_double("MULTZ");
|
||||
for (std::size_t index = 0; index < multz_global.size(); index++)
|
||||
BOOST_CHECK_EQUAL(index * 1.0, multz_global[index]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GLOBAL_FIELD2)
|
||||
{
|
||||
std::string deck_string = R"(
|
||||
GRID
|
||||
|
||||
PORO
|
||||
27*0.10 /
|
||||
|
||||
ACTNUM
|
||||
9*1 9*0 9*1 /
|
||||
|
||||
MULTZ
|
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 /
|
||||
|
||||
EDIT
|
||||
|
||||
MULTZ
|
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 /
|
||||
|
||||
)";
|
||||
std::vector<int> actnum(27, 1);
|
||||
for (std::size_t i=9; i< 18; i++)
|
||||
actnum[i] = 0;
|
||||
EclipseGrid grid(EclipseGrid(3,3,3), actnum);
|
||||
Deck deck = Parser{}.parseString(deck_string);
|
||||
FieldPropsManager fpm(deck, Phases{true, true, true}, grid, TableManager());
|
||||
|
||||
auto multz = fpm.get_double("MULTZ");
|
||||
auto multz_global = fpm.get_global_double("MULTZ");
|
||||
for (std::size_t index = 0; index < multz_global.size(); index++)
|
||||
BOOST_CHECK_EQUAL(index * index * 1.0, multz_global[index]);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GLOBAL_FIELD3)
|
||||
{
|
||||
std::string deck_string = R"(
|
||||
GRID
|
||||
|
||||
PORO
|
||||
27*0.10 /
|
||||
|
||||
ACTNUM
|
||||
9*1 9*0 9*1 /
|
||||
|
||||
MULTZ
|
||||
0 1 2 3 4 5 6 7 8
|
||||
9*0
|
||||
18 19 20 21 22 23 24 25 26 /
|
||||
|
||||
EQUALS
|
||||
MULTZ 99 1 3 1 3 2 2 /
|
||||
/
|
||||
|
||||
|
||||
)";
|
||||
std::vector<int> actnum(27, 1);
|
||||
for (std::size_t i=9; i< 18; i++)
|
||||
actnum[i] = 0;
|
||||
EclipseGrid grid(EclipseGrid(3,3,3), actnum);
|
||||
Deck deck = Parser{}.parseString(deck_string);
|
||||
FieldPropsManager fpm(deck, Phases{true, true, true}, grid, TableManager());
|
||||
|
||||
auto multz = fpm.get_double("MULTZ");
|
||||
auto multz_global = fpm.get_global_double("MULTZ");
|
||||
for (std::size_t index = 0; index < multz_global.size(); index++) {
|
||||
if (index <= 8 || index >= 18)
|
||||
BOOST_CHECK_EQUAL(index * 1.0, multz_global[index]);
|
||||
else
|
||||
BOOST_CHECK_EQUAL(99, multz_global[index]);
|
||||
}
|
||||
}
|
||||
|
||||
FieldPropsManager make_fp(const std::string& deck_string) {
|
||||
std::vector<int> actnum(27, 1);
|
||||
for (std::size_t i=9; i< 18; i++)
|
||||
actnum[i] = 0;
|
||||
EclipseGrid grid(EclipseGrid(3,3,3), actnum);
|
||||
Deck deck = Parser{}.parseString(deck_string);
|
||||
return FieldPropsManager(deck, Phases{true, true, true}, grid, TableManager());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GLOBAL_UNSUPPORTED) {
|
||||
// Operations involving two keywords can not update a global keyword.
|
||||
std::string invalid_copy = R"(
|
||||
GRID
|
||||
|
||||
PORO
|
||||
27*0.10 /
|
||||
|
||||
ACTNUM
|
||||
9*1 9*0 9*1 /
|
||||
|
||||
MULTX
|
||||
27*1.0 /
|
||||
|
||||
COPY
|
||||
MULTX MULTZ
|
||||
/
|
||||
|
||||
)";
|
||||
|
||||
// Can not update a global keyword with xxxxREG operations
|
||||
std::string invalid_region = R"(
|
||||
GRID
|
||||
|
||||
PORO
|
||||
27*0.10 /
|
||||
|
||||
ACTNUM
|
||||
9*1 9*0 9*1 /
|
||||
|
||||
MULTZ
|
||||
27*1.0 /
|
||||
|
||||
EQUALREG
|
||||
MULTZ 2.0 1 /
|
||||
/
|
||||
|
||||
)";
|
||||
|
||||
// Can not update a global keyword with the OPERATE keyword
|
||||
std::string invalid_operate = R"(
|
||||
GRID
|
||||
|
||||
PORO
|
||||
27*0.10 /
|
||||
|
||||
ACTNUM
|
||||
9*1 9*0 9*1 /
|
||||
|
||||
MULTZ
|
||||
27*1.0 /
|
||||
|
||||
OPERATE
|
||||
MULTZ 1 3 1 1 1 1 'MAXLIM' MULTZ 0.50 /
|
||||
/
|
||||
|
||||
)";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
BOOST_CHECK_THROW(make_fp(invalid_copy), std::logic_error);
|
||||
BOOST_CHECK_THROW(make_fp(invalid_region), std::logic_error);
|
||||
BOOST_CHECK_THROW(make_fp(invalid_operate), std::logic_error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user