#include #include #include #include #include #include #include #include #define BOOST_TEST_MODULE TestTuningXXXMBE #include struct Column : public std::vector { Column(const std::string& name_, const int size = 0, const int num_rows_estimate = 1000) : std::vector(size), name(name_) { this->reserve(num_rows_estimate); } // Return vector of double values, invalid elements set to NaN std::vector dvalues() const { std::vector 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::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::min() std::vector ivalues() const { std::vector 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::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 get_dvector(const std::string& colname) const { return columns.at(colname)->dvalues(); } std::vector get_ivector(const std::string& colname) const { return columns.at(colname)->ivalues(); } // Default is to return double values std::vector operator[](const std::string& colname) const { return columns.at(colname)->dvalues(); } std::vector column_names; std::vector raw_columns; std::map 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 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::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::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" ); }