This commit adds a new helper object
Opm::WriteRestartFileEvents
that identifies when a restart file output event occurs as well as
the most recent output event prior to a particular report step. We
implement this facility in terms of a dense bit vector that wastes
up to 63 bits of space. Most of the logic is devoted to finding the
most recent previous output event, of which the core routine is
counting the number of leading zero bits in a 64 bit value. We've
elected to implement this in a portable manner using binary search,
although most implementations provide efficient intrinsics for this
operation, e.g., GCC's __builtin_clzl. In C++20 we can use the new
function std::countl_zero() from <bit>.
268 lines
9.2 KiB
C++
268 lines
9.2 KiB
C++
/*
|
|
Copyright 2021 Equinor.
|
|
|
|
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/>.
|
|
*/
|
|
|
|
#define BOOST_TEST_MODULE Restart File Events
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include <opm/parser/eclipse/EclipseState/Schedule/WriteRestartFileEvents.hpp>
|
|
|
|
#include <cstddef>
|
|
|
|
BOOST_AUTO_TEST_SUITE(Basic_Operations)
|
|
|
|
BOOST_AUTO_TEST_CASE(Default_Constructor)
|
|
{
|
|
const auto events = Opm::WriteRestartFileEvents{};
|
|
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(0),
|
|
"Default constructed events object must not "
|
|
"have events at report step zero");
|
|
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(11),
|
|
"Default constructed events object must not "
|
|
"have events at report step 11");
|
|
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(1729),
|
|
"Default constructed events object must not "
|
|
"have events at report step 1729");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Add_Events)
|
|
{
|
|
auto events = Opm::WriteRestartFileEvents{};
|
|
|
|
events.addRestartOutput(11);
|
|
events.addRestartOutput(22);
|
|
events.addRestartOutput(33);
|
|
events.addRestartOutput(59);
|
|
events.addRestartOutput(64);
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(11),
|
|
"Events object must have restart event at "
|
|
"report step 11 after 'add'");
|
|
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(22),
|
|
"Events object must have restart event at "
|
|
"report step 22 after 'add'");
|
|
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(33),
|
|
"Events object must have restart event at "
|
|
"report step 33 after 'add'");
|
|
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(59),
|
|
"Events object must have restart event at "
|
|
"report step 59 after 'add'");
|
|
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(64),
|
|
"Events object must have restart event at "
|
|
"report step 64 after 'add'");
|
|
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(0),
|
|
"Events object must have NOT restart event at "
|
|
"report step 0 after 'add(64)'");
|
|
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(42),
|
|
"Events object must have NOT restart event at "
|
|
"report step 42 after 'add(64)'");
|
|
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(65),
|
|
"Events object must have NOT restart event at "
|
|
"report step 65 after 'add(64)'");
|
|
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(1729),
|
|
"Events object must have NOT restart event at "
|
|
"report step 1729 after 'add(64)'");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Clear_Remaining_Events)
|
|
{
|
|
auto events = Opm::WriteRestartFileEvents{};
|
|
|
|
events.addRestartOutput(11);
|
|
events.addRestartOutput(22);
|
|
events.addRestartOutput(33);
|
|
events.addRestartOutput(59);
|
|
|
|
events.clearRemainingEvents(33);
|
|
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(11),
|
|
"Events object must have restart event at "
|
|
"report step 11 after 'add'");
|
|
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(22),
|
|
"Events object must have restart event at "
|
|
"report step 22 after 'add'");
|
|
|
|
for (auto i = 33; i < 64; ++i) {
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(i),
|
|
"Events object must have NOT restart event at "
|
|
"report step " << i << " after 'clearRemainingEvents(33)'");
|
|
}
|
|
|
|
events.addRestartOutput(33);
|
|
events.clearRemainingEvents(34);
|
|
|
|
BOOST_CHECK_MESSAGE(events.writeRestartFile(33),
|
|
"Events object must have restart event at "
|
|
"report step 33 after 'clearRemainingEvents(34)'");
|
|
|
|
for (auto i = 34; i < 64; ++i) {
|
|
BOOST_CHECK_MESSAGE(!events.writeRestartFile(i),
|
|
"Events object must have NOT restart event at "
|
|
"report step " << i << " after 'clearRemainingEvents(34)'");
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(Last_Restart_Event_Before)
|
|
{
|
|
auto events = Opm::WriteRestartFileEvents{};
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(271828);
|
|
BOOST_CHECK_MESSAGE(!event.has_value(), "There must be no output events before report step 271828");
|
|
}
|
|
|
|
events.addRestartOutput(11);
|
|
events.addRestartOutput(22);
|
|
events.addRestartOutput(33);
|
|
events.addRestartOutput(59);
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(11);
|
|
BOOST_CHECK_MESSAGE(!event.has_value(), "There must be no output events before report step 11");
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(12);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 12");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{11});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(22);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 22");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{11});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(23);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 23");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{22});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(28);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 28");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{22});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(33);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 33");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{22});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(34);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 34");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{33});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(50);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 50");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{33});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(59);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 59");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{33});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(60);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 60");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{59});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(64);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 64");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{59});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(1729);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 1729");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{59});
|
|
}
|
|
|
|
events.addRestartOutput(42);
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(42);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 42");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{33});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(43);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 43");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{42});
|
|
}
|
|
|
|
events.addRestartOutput(128);
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(1729);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 1729");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{128});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(128);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 128");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{59});
|
|
}
|
|
|
|
{
|
|
const auto event = events.lastRestartEventBefore(129);
|
|
BOOST_CHECK_MESSAGE(event.has_value(), "There must be an output event before report step 129");
|
|
|
|
BOOST_CHECK_EQUAL(event.value(), std::size_t{128});
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END() // Basic_Operations
|