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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <limits>
#include <algorithm>
#define BOOST_TEST_MODULE TestTuningTRGMBE
#include <boost/test/unit_test.hpp>
struct Column : public std::vector<std::string>
{
explicit 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
{
explicit 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(CheckMassBalanceWithinTRGMBE)
{
//std::string case_name(boost::unit_test::framework::master_test_suite().argv[1]);
std::string case_name("01_TUNING_TRGMBE");
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-7, "max_mb[0] (= " << max_mb[0] << ") is not strictly less than 1.0e-7" );
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" );
}
|