Skip to content

Commit

Permalink
Stop Processing if COPYing From Undefined Source Array
Browse files Browse the repository at this point in the history
This commit adds defined value checking to the source array from
which we're copying in a COPY operation--either with the COPY or
with the COPYREG keywords.  We count the number of source array
values which do not have the status of 'deck_value' and if this
count is positive, then we throw an OpmInputError exception which
halts further input processing.

As an example of this behaviour, the (deliberately faulty) setup

    EQUALS
    -- SGL not defined prior to this point
     'SGL' 0.0 2* 2* 1 5 /
    /

    COPY
      SGL SWL 2* 2* 4 7 /
    /

will generate an "Error" of the form

    Error: Problem with keyword COPY
    In USER_ERR_COPY_BOX_PARTIALLY_UNDEF.DATA line 195
    Copying from source array SGL in BOX (1-13, 1-22, 4-7)
    would generate an undefined result in 572 blocks of target array SWL.

and stop input processing.
  • Loading branch information
bska committed Jul 2, 2024
1 parent 7c5c81b commit 866079d
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 8 deletions.
1 change: 1 addition & 0 deletions CMakeLists_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ if(ENABLE_ECL_INPUT)
opm/input/eclipse/EclipseState/Grid/CarfinManager.cpp
opm/input/eclipse/EclipseState/Grid/LgrCollection.cpp
opm/input/eclipse/EclipseState/Grid/EclipseGrid.cpp
opm/input/eclipse/EclipseState/Grid/FieldData.cpp
opm/input/eclipse/EclipseState/Grid/FieldProps.cpp
opm/input/eclipse/EclipseState/Grid/FieldPropsManager.cpp
opm/input/eclipse/EclipseState/Grid/FaceDir.cpp
Expand Down
86 changes: 86 additions & 0 deletions opm/input/eclipse/EclipseState/Grid/FieldData.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
Copyright 2024 Equinor AS.
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/input/eclipse/EclipseState/Grid/FieldData.hpp>

#include <opm/common/OpmLog/KeywordLocation.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/common/utility/OpmInputError.hpp>

#include <opm/input/eclipse/EclipseState/Grid/Box.hpp>

#include <opm/input/eclipse/Deck/value_status.hpp>

#include <string>
#include <vector>

#include <fmt/format.h>

template <typename T>
void
Opm::Fieldprops::FieldData<T>::
checkInitialisedCopy(const FieldData& src,
const std::vector<Box::cell_index>& index_list,
const std::string& from,
const std::string& to,
const KeywordLocation& loc)
{
auto unInit = 0;

for (const auto& ci : index_list) {
const auto ix = ci.active_index;
const auto st = src.value_status[ix];

if (st != value::status::deck_value) {
++unInit;
continue;
}

this->data[ix] = src.data[ix];
this->value_status[ix] = st;
}

if (unInit > 0) {
const auto* plural = (unInit > 1) ? "s" : "";

throw OpmInputError {
fmt::format
(R"(Copying from source array {0}
would generate an undefined result in {2} block{3} of target array {1}.)",
from, to, unInit, plural),
loc
};
}
}

template
void Opm::Fieldprops::FieldData<double>::
checkInitialisedCopy(const FieldData&,
const std::vector<Box::cell_index>&,
const std::string&,
const std::string&,
const KeywordLocation&);

template
void Opm::Fieldprops::FieldData<int>::
checkInitialisedCopy(const FieldData&,
const std::vector<Box::cell_index>&,
const std::string&,
const std::string&,
const KeywordLocation&);
15 changes: 9 additions & 6 deletions opm/input/eclipse/EclipseState/Grid/FieldData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include <string>
#include <vector>

namespace Opm {
class KeywordLocation;
} // namespace Opm

namespace Opm::Fieldprops {

template <typename T>
Expand Down Expand Up @@ -148,12 +152,11 @@ namespace Opm::Fieldprops {
Fieldprops::compress(this->value_status, active_map, this->numValuePerCell());
}

void copy(const FieldData<T>& src, const std::vector<Box::cell_index>& index_list) {
for (const auto& ci : index_list) {
this->data[ci.active_index] = src.data[ci.active_index];
this->value_status[ci.active_index] = src.value_status[ci.active_index];
}
}
void checkInitialisedCopy(const FieldData& src,
const std::vector<Box::cell_index>& index_list,
const std::string& from,
const std::string& to,
const KeywordLocation& loc);

void default_assign(T value)
{
Expand Down
16 changes: 14 additions & 2 deletions opm/input/eclipse/EclipseState/Grid/FieldProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1623,26 +1623,36 @@ void FieldProps::handle_COPY(const DeckKeyword& keyword,
const auto target_kw = arrayName(record.getItem(1));

std::vector<Box::cell_index> index_list;
auto srcDescr = std::string {};

if (isRegionOperation) {
using Kw = ParserKeywords::COPYREG;
const auto regionId = record.getItem<Kw::REGION_NUMBER>().get<int>(0);
const auto& regionName = this->region_name(record.getItem<Kw::REGION_NAME>());

index_list = this->region_index(regionName, regionId);
srcDescr = fmt::format("{} in region {} of region set {}",
src_kw, regionId, regionName);
}
else {
box.update(record);
index_list = box.index_list();

srcDescr = fmt::format("{} in BOX ({}-{}, {}-{}, {}-{})",
src_kw,
box.I1() + 1, box.I2() + 1,
box.J1() + 1, box.J2() + 1,
box.K1() + 1, box.K2() + 1);
}

if (FieldProps::supported<double>(src_kw)) {
const auto& src_data = this->try_get<double>(src_kw);
src_data.verify_status();

auto& target_data = this->init_get<double>(target_kw);
target_data.copy(src_data.field_data(), index_list);
target_data.checkInitialisedCopy(src_data.field_data(), index_list,
srcDescr, target_kw,
keyword.location());
continue;
}

Expand All @@ -1651,7 +1661,9 @@ void FieldProps::handle_COPY(const DeckKeyword& keyword,
src_data.verify_status();

auto& target_data = this->init_get<int>(target_kw);
target_data.copy(src_data.field_data(), index_list);
target_data.checkInitialisedCopy(src_data.field_data(), index_list,
srcDescr, target_kw,
keyword.location());
continue;
}
}
Expand Down
76 changes: 76 additions & 0 deletions tests/parser/FieldPropsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,82 @@ COPY
BOOST_CHECK_THROW( FieldPropsManager(deck, Phases{true, true, true}, grid, TableManager()), std::out_of_range);
}

BOOST_AUTO_TEST_CASE(INVALID_COPY_UNDEFINED_BOX)
{
const auto deck = Parser{}.parseString(R"(RUNSPEC
OIL
GAS
WATER
TABDIMS
/
DIMENS
10 10 10 /
PROPS
SGFN
0.0 0.0 0.0
0.8 1.0 0.0
/
SWFN
0.2 0.0 0.0
1.0 1.0 0.0
/
SOF3
0.0 0.0 0.0
0.8 1.0 1.0
/
EQUALS
'SGL' 0.0 2* 2* 1 5 /
/
COPY
SGL SWL 2* 2* 6 10 /
/
)");

// Note: 'grid' must be mutable.
auto grid = EclipseGrid { 10, 10, 10 };

BOOST_CHECK_THROW(FieldPropsManager(deck, Phases{true, true, true}, grid, TableManager{deck}),
OpmInputError);
}

BOOST_AUTO_TEST_CASE(INVALID_COPY_PARTIALLY_DEFINED)
{
const auto deck = Parser{}.parseString(R"(RUNSPEC
OIL
GAS
WATER
TABDIMS
/
DIMENS
10 10 10 /
PROPS
SGFN
0.0 0.0 0.0
0.8 1.0 0.0
/
SWFN
0.2 0.0 0.0
1.0 1.0 0.0
/
SOF3
0.0 0.0 0.0
0.8 1.0 1.0
/
EQUALS
'SGL' 0.0 2* 2* 1 5 /
/
COPY
SGL SWL 2* 2* 4 7 /
/
)");

// Note: 'grid' must be mutable.
auto grid = EclipseGrid { 10, 10, 10 };

BOOST_CHECK_THROW(FieldPropsManager(deck, Phases{true, true, true}, grid, TableManager{deck}),
OpmInputError);
}

BOOST_AUTO_TEST_CASE(GRID_RESET) {
std::string deck_string = R"(
REGIONS
Expand Down

0 comments on commit 866079d

Please sign in to comment.