mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #4621 from vkip/use_mb_from_tuning
Use mass balance limit (XXXMBE) from TUNING with --enable-tuning=true
This commit is contained in:
commit
8c6a92356f
@ -253,6 +253,7 @@ list (APPEND TEST_SOURCE_FILES
|
||||
tests/test_RestartSerialization.cpp
|
||||
tests/test_stoppedwells.cpp
|
||||
tests/test_timer.cpp
|
||||
tests/test_tuning_XXXMBE.cpp
|
||||
tests/test_vfpproperties.cpp
|
||||
tests/test_wellmodel.cpp
|
||||
tests/test_wellprodindexcalculator.cpp
|
||||
|
@ -21,7 +21,7 @@ set(BASE_RESULT_PATH ${PROJECT_BINARY_DIR}/tests/results)
|
||||
# Details:
|
||||
# - This test class simply runs a simulation.
|
||||
function(add_test_runSimulator)
|
||||
set(oneValueArgs CASENAME FILENAME SIMULATOR DIR DIR_PREFIX PROCS)
|
||||
set(oneValueArgs CASENAME FILENAME SIMULATOR DIR DIR_PREFIX PROCS CONFIGURATION)
|
||||
set(multiValueArgs TEST_ARGS)
|
||||
cmake_parse_arguments(PARAM "$" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
||||
if(NOT PARAM_DIR)
|
||||
@ -37,7 +37,8 @@ function(add_test_runSimulator)
|
||||
-f ${PARAM_FILENAME}
|
||||
-n ${PARAM_PROCS}
|
||||
TEST_ARGS ${TEST_ARGS}
|
||||
CONFIGURATION extra)
|
||||
CONFIGURATION ${PARAM_CONFIGURATION})
|
||||
set_tests_properties(runSimulator/${PARAM_CASENAME} PROPERTIES PROCESSORS ${PARAM_PROCS})
|
||||
endfunction()
|
||||
|
||||
###########################################################################
|
||||
@ -277,13 +278,52 @@ opm_set_test_driver(${PROJECT_SOURCE_DIR}/tests/run-test.sh "")
|
||||
add_test_runSimulator(CASENAME norne
|
||||
FILENAME NORNE_ATW2013
|
||||
SIMULATOR flow
|
||||
PROCS 1)
|
||||
PROCS 1
|
||||
CONFIGURATION extra)
|
||||
|
||||
add_test_runSimulator(CASENAME norne_parallel
|
||||
FILENAME NORNE_ATW2013
|
||||
SIMULATOR flow
|
||||
DIR norne
|
||||
PROCS 4)
|
||||
PROCS 4
|
||||
CONFIGURATION extra)
|
||||
|
||||
|
||||
# Tests that are run based on simulator results, but not necessarily direct comparison to reference results
|
||||
add_test_runSimulator(CASENAME run_tuning_xxxmbe
|
||||
FILENAME 01_TUNING_XXXMBE
|
||||
SIMULATOR flow
|
||||
DIR tuning
|
||||
PROCS 1
|
||||
TEST_ARGS --output-extra-convergence-info=iterations --enable-tuning=true)
|
||||
|
||||
add_test_runSimulator(CASENAME run_notuning_xxxmbe
|
||||
FILENAME 01_TUNING_XXXMBE
|
||||
SIMULATOR flow
|
||||
DIR tuning
|
||||
PROCS 1
|
||||
TEST_ARGS --output-extra-convergence-info=iterations --enable-tuning=false)
|
||||
|
||||
|
||||
set_tests_properties(tuning_XXXMBE PROPERTIES DEPENDS "runSimulator/run_tuning_xxxmbe")
|
||||
set_tests_properties(tuning_XXXMBE PROPERTIES WORKING_DIRECTORY "${BASE_RESULT_PATH}/flow+run_tuning_xxxmbe")
|
||||
|
||||
# Workaround to run same test on different simulation results
|
||||
get_target_property(notuning_XXXMBE_cmd test_tuning_XXXMBE LOCATION)
|
||||
if(MPI_FOUND)
|
||||
set(notuning_XXXMBE_cmd ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 1 ${notuning_XXXMBE_cmd})
|
||||
endif()
|
||||
|
||||
add_test(
|
||||
NAME notuning_XXXMBE
|
||||
COMMAND ${notuning_XXXMBE_cmd}
|
||||
)
|
||||
set_tests_properties(notuning_XXXMBE PROPERTIES DEPENDS "runSimulator/run_notuning_xxxmbe")
|
||||
set_tests_properties(notuning_XXXMBE PROPERTIES WORKING_DIRECTORY "${BASE_RESULT_PATH}/flow+run_notuning_xxxmbe")
|
||||
set_tests_properties(notuning_XXXMBE PROPERTIES WILL_FAIL TRUE)
|
||||
|
||||
|
||||
|
||||
|
||||
include (${CMAKE_CURRENT_SOURCE_DIR}/regressionTests.cmake)
|
||||
include (${CMAKE_CURRENT_SOURCE_DIR}/restartTests.cmake)
|
||||
|
@ -24,6 +24,8 @@
|
||||
#ifndef OPM_BLACKOILMODELEBOS_HEADER_INCLUDED
|
||||
#define OPM_BLACKOILMODELEBOS_HEADER_INCLUDED
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <ebos/eclproblem.hh>
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
@ -1523,6 +1525,7 @@ namespace Opm {
|
||||
return grid_.comm().sum(errorPV);
|
||||
}
|
||||
|
||||
|
||||
ConvergenceReport getDomainReservoirConvergence(const double reportTime,
|
||||
const double dt,
|
||||
const int iteration,
|
||||
@ -1632,6 +1635,14 @@ namespace Opm {
|
||||
|
||||
|
||||
|
||||
void updateTUNING(const Tuning& tuning) {
|
||||
param_.tolerance_mb_ = tuning.XXXMBE;
|
||||
if ( terminal_output_ ) {
|
||||
OpmLog::debug(fmt::format("Setting BlackoilModelEbos mass balance limit (XXXMBE) to {:.2e}", tuning.XXXMBE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ConvergenceReport getReservoirConvergence(const double reportTime,
|
||||
const double dt,
|
||||
const int iteration,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define OPM_SIMULATORFULLYIMPLICITBLACKOILEBOS_HEADER_INCLUDED
|
||||
|
||||
#include <dune/common/hash.hh>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <opm/simulators/flow/BlackoilModelEbos.hpp>
|
||||
#include <opm/simulators/flow/BlackoilModelParametersEbos.hpp>
|
||||
@ -320,6 +321,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void updateTUNING(const Tuning& tuning) {
|
||||
modelParam_.tolerance_mb_ = tuning.XXXMBE;
|
||||
if (terminalOutput_) {
|
||||
OpmLog::debug(fmt::format("Setting SimulatorFullyImplicitBlackoilEbos mass balance limit (XXXMBE) to {:.2e}", tuning.XXXMBE));
|
||||
}
|
||||
}
|
||||
|
||||
bool runStep(SimulatorTimer& timer)
|
||||
{
|
||||
if (schedule().exitStatus().has_value()) {
|
||||
@ -393,6 +401,10 @@ public:
|
||||
const auto& tuning = sched_state.tuning();
|
||||
const auto& max_next_tstep = sched_state.max_next_tstep();
|
||||
adaptiveTimeStepping_->updateTUNING(max_next_tstep, tuning);
|
||||
// \Note: Assumes TUNING is only used with adaptive time-stepping
|
||||
// \Note: Need to update both solver (model) and simulator since solver is re-created each report step.
|
||||
solver_->model().updateTUNING(tuning);
|
||||
this->updateTUNING(tuning);
|
||||
}
|
||||
}
|
||||
bool event = events.hasEvent(ScheduleEvents::NEW_WELL) ||
|
||||
|
@ -33,8 +33,8 @@ TEST_ARGS="$@"
|
||||
mkdir -p ${RESULT_PATH}
|
||||
if (( ${MPI_PROCS} > 1))
|
||||
then
|
||||
mpirun -np ${MPI_PROCS} ${BINPATH}/${EXE_NAME} ${TEST_ARGS} --output-dir=${RESULT_PATH}
|
||||
mpirun -np ${MPI_PROCS} ${BINPATH}/${EXE_NAME} ${TEST_ARGS} --output-dir=${RESULT_PATH} "${INPUT_DATA_PATH}/${FILENAME}.DATA"
|
||||
else
|
||||
${BINPATH}/${EXE_NAME} ${TEST_ARGS} --output-dir=${RESULT_PATH}
|
||||
${BINPATH}/${EXE_NAME} ${TEST_ARGS} --output-dir=${RESULT_PATH} "${INPUT_DATA_PATH}/${FILENAME}.DATA"
|
||||
fi
|
||||
test $? -eq 0 || exit 1
|
||||
|
157
tests/test_tuning_XXXMBE.cpp
Normal file
157
tests/test_tuning_XXXMBE.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
#define BOOST_TEST_MODULE TestTuningXXXMBE
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
struct Column : public std::vector<std::string> {
|
||||
Column(const std::string& name_, const int size = 0, const int num_rows_estimate = 1000) :
|
||||
std::vector<std::string>(size), name(name_)
|
||||
{
|
||||
this->reserve(num_rows_estimate);
|
||||
}
|
||||
|
||||
// Return vector of double values, invalid elements set to NaN
|
||||
std::vector<double> dvalues() const {
|
||||
std::vector<double> vec;
|
||||
vec.reserve(this->size());
|
||||
|
||||
const auto& conv_func = [](const std::string& strval) {
|
||||
double dval;
|
||||
try {
|
||||
dval = std::stod(strval);
|
||||
} catch (std::invalid_argument& exc) {
|
||||
dval = std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
return dval;
|
||||
};
|
||||
|
||||
std::transform(this->cbegin(), this->cend(), std::back_inserter(vec), conv_func);
|
||||
return vec;
|
||||
}
|
||||
|
||||
// Return vector of double values values, invalid elements set to std::numeric_limits<int>::min()
|
||||
std::vector<int> ivalues() const {
|
||||
std::vector<int> vec;
|
||||
vec.reserve(this->size());
|
||||
|
||||
const auto& conv_func = [](const std::string& strval) {
|
||||
int ival;
|
||||
try {
|
||||
ival = std::stoi(strval);
|
||||
} catch (std::invalid_argument& exc) {
|
||||
ival = std::numeric_limits<int>::min();
|
||||
}
|
||||
return ival;
|
||||
};
|
||||
|
||||
std::transform(this->cbegin(), this->cend(), std::back_inserter(vec), conv_func);
|
||||
return vec;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
|
||||
struct ColumnData {
|
||||
ColumnData(const std::string& file_name, const int num_columns_estimate=20) {
|
||||
raw_columns.reserve(num_columns_estimate);
|
||||
load_file(file_name);
|
||||
}
|
||||
|
||||
void load_file(const std::string& file_name) {
|
||||
// Open file and read first line with column names
|
||||
std::ifstream ifs(file_name);
|
||||
std::string line, colname;
|
||||
|
||||
std::getline(ifs, line);
|
||||
std::istringstream iss(line);
|
||||
while (iss >> colname) {
|
||||
column_names.push_back(colname);
|
||||
raw_columns.emplace_back(colname);
|
||||
columns[colname] = &(raw_columns.back());
|
||||
}
|
||||
const int num_columns = column_names.size();
|
||||
|
||||
// Read remaining lines into std::string vectors
|
||||
int lineno = 1;
|
||||
while (std::getline(ifs, line)) {
|
||||
iss.str(line); iss.clear();
|
||||
int i=0;
|
||||
while (iss >> colname && i < num_columns) {
|
||||
raw_columns[i].push_back(colname);
|
||||
++i;
|
||||
}
|
||||
if (i >= num_columns && iss >> colname) {
|
||||
std::cout << "Warning: Ignoring extra column(s) on line " << lineno << std::endl;
|
||||
}
|
||||
++lineno;
|
||||
}
|
||||
}
|
||||
|
||||
// Get data vectors of different types
|
||||
std::vector<double> get_dvector(const std::string& colname) const { return columns.at(colname)->dvalues(); }
|
||||
std::vector<int> get_ivector(const std::string& colname) const { return columns.at(colname)->ivalues(); }
|
||||
// Default is to return double values
|
||||
std::vector<double> operator[](const std::string& colname) const { return columns.at(colname)->dvalues(); }
|
||||
|
||||
std::vector<std::string> column_names;
|
||||
std::vector<Column> raw_columns;
|
||||
std::map<std::string, Column*> columns;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CheckMassBalanceWithinXXXMBE)
|
||||
{
|
||||
//std::string case_name(boost::unit_test::framework::master_test_suite().argv[1]);
|
||||
std::string case_name("01_TUNING_XXXMBE");
|
||||
std::string file_name = case_name + ".INFOITER";
|
||||
|
||||
ColumnData data(file_name);
|
||||
auto rstep = data.get_ivector("ReportStep");
|
||||
auto tstep = data.get_ivector("TimeStep");
|
||||
auto mbo = data["MB_Oil"];
|
||||
auto mbw = data["MB_Water"];
|
||||
auto mbg = data["MB_Gas"];
|
||||
|
||||
const int num_reports = 1 + *std::max_element(rstep.begin(), rstep.end());
|
||||
std::vector<double> max_mb;
|
||||
max_mb.reserve(num_reports);
|
||||
|
||||
|
||||
// Find the maximum mass balance error at each converged time step for each report step..
|
||||
const int nrows = rstep.size();
|
||||
int rcur = 0;
|
||||
int tcur = 0;
|
||||
double max_mb_step = std::numeric_limits<double>::min();
|
||||
for (int i=0; i<(nrows-1); ++i) {
|
||||
if (tcur != tstep[i+1] || rcur != rstep[i+1]) {
|
||||
max_mb_step = std::max({mbo[i], mbw[i], mbg[i], max_mb_step});
|
||||
tcur = tstep[i+1];
|
||||
}
|
||||
if (rcur != rstep[i+1]) {
|
||||
max_mb.push_back(max_mb_step);
|
||||
max_mb_step = std::numeric_limits<double>::min();
|
||||
rcur = rstep[i+1];
|
||||
}
|
||||
}
|
||||
max_mb.push_back( std::max({mbo.back(), mbw.back(), mbg.back(), max_mb_step}) );
|
||||
|
||||
BOOST_TEST_MESSAGE("---------------------------------------------------------------------------");
|
||||
BOOST_TEST_MESSAGE("Found the following converged max mass balance error (per report step):");
|
||||
for (auto& val : max_mb)
|
||||
BOOST_TEST_MESSAGE(val);
|
||||
BOOST_TEST_MESSAGE("---------------------------------------------------------------------------");
|
||||
|
||||
|
||||
BOOST_CHECK( max_mb[0] < 1.0e-6 );
|
||||
BOOST_CHECK( max_mb[1] < 1.0e-8 );
|
||||
BOOST_CHECK( max_mb[2] < 1.0e-10 );
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user