mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-12-23 07:53:29 -06:00
027eed16e9
This commit includes the fraction of pore-volume whose CNV targets are violated as a new per-iteration quantity in the INFOITER file (--output-extra-convergence-info=iteration), with the column header "CnvErrPvFrac". We collect the values which are already calculated in BlackoilModel<>::getReservoirConvergence() and store these as a pair of numerator and denominator in the ConvergenceReport class. Note that we need both the numerator and the denominator in order to aggregate contributions from multiple ranks. While here, also make a few more objects 'const' and calculate column widths directly instead of the maximum number of characters in writeConvergenceHeader().
157 lines
5.0 KiB
C++
157 lines
5.0 KiB
C++
#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_MESSAGE( max_mb[0] < 1.0e-6, "max_mb[0] (= " << max_mb[0] << ") is not strictly less than 1.0e-6" );
|
||
BOOST_CHECK_MESSAGE( max_mb[1] < 1.0e-8, "max_mb[1] (= " << max_mb[1] << ") is not strictly less than 1.0e-8" );
|
||
BOOST_CHECK_MESSAGE( max_mb[2] < 1.0e-10, "max_mb[2] (= " << max_mb[1] << ") is not strictly less than 1.0e-10" );
|
||
|
||
}
|