Merge pull request #472 from akva2/add_analysis

added: error analysis support in compareSummary / compareECL
This commit is contained in:
Arne Morten Kvarving 2018-08-15 08:08:47 +02:00 committed by GitHub
commit e407e65b54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 95 additions and 15 deletions

View File

@ -36,6 +36,7 @@ static void printHelp() {
<< "3. Absolute tolerance\n"
<< "4. Relative tolerance (between 0 and 1)\n\n"
<< "In addition, the program takes these options (which must be given before the arguments):\n\n"
<< "-a Run a full analysis of errors.\n"
<< "-h Print help and exit.\n"
<< "-i Execute integration test (regression test is default).\n"
<< " The integration test compares SGAS, SWAT and PRESSURE in unified restart files, so this option can not be used in combination with -t.\n"
@ -114,13 +115,17 @@ int main(int argc, char** argv) {
bool specificKeyword = false;
bool specificFileType = false;
bool throwOnError = true;
bool analysis = false;
bool volumecheck = true;
char* keyword = nullptr;
char* fileTypeCstr = nullptr;
int c = 0;
while ((c = getopt(argc, argv, "hiIk:lnpPt:V")) != -1) {
while ((c = getopt(argc, argv, "hiIk:alnpPt:V")) != -1) {
switch (c) {
case 'a':
analysis = true;
break;
case 'h':
printHelp();
return 0;
@ -246,6 +251,7 @@ int main(int argc, char** argv) {
else {
RegressionTest comparator(file_type, basename1, basename2, absTolerance, relTolerance);
comparator.throwOnErrors(throwOnError);
comparator.doAnalysis(analysis);
if (printKeywords) {
comparator.printKeywords();
return 0;

View File

@ -37,6 +37,7 @@ void printHelp(){
std::cout << "The program is capable of performing both a regression test and an integration test, \nhowever only one type of test at a time. ";
std::cout << "By default the program will run a regression test."<< std::endl;
std::cout << "\nThe program have command line options:" << std::endl;
std::cout << "-a \tRun a full analysis of errors." << std::endl;
std::cout << "-h \t\tPrint help message." << std::endl << std::endl;
std::cout << "For the regression test: " << std::endl;
std::cout << "-r \t\tChoosing regression test (this is default)."<< std::endl;
@ -80,6 +81,7 @@ int main (int argc, char ** argv){
bool throwExceptionForTooGreatErrorRatio = true;
bool isRestartFile = false;
bool throwOnError = true;
bool analysis = false;
const char* keyword = nullptr;
const char* mainVariable = nullptr;
int c = 0;
@ -88,8 +90,11 @@ int main (int argc, char ** argv){
//------------------------------------------------
//For setting the options selected
while ((c = getopt(argc, argv, "dghik:Km:npP:rRs:vV:")) != -1) {
while ((c = getopt(argc, argv, "dghik:Km:napP:rRs:vV:")) != -1) {
switch (c) {
case 'a':
analysis = true;
break;
case 'd':
throwExceptionForTooGreatErrorRatio = false;
break;
@ -177,6 +182,7 @@ int main (int argc, char ** argv){
if(regressionTest){
RegressionTest compare(basename1,basename2, absoluteTolerance, relativeTolerance);
compare.throwOnErrors(throwOnError);
compare.doAnalysis(analysis);
if(printKeywords){compare.setPrintKeywords(true);}
if(isRestartFile){compare.setIsRestartFile(true);}
if(specificKeyword){

View File

@ -20,6 +20,7 @@
#ifndef ECLFILESCOMPARATOR_HPP
#define ECLFILESCOMPARATOR_HPP
#include <map>
#include <vector>
#include <string>
@ -61,6 +62,8 @@ class ECLFilesComparator {
ecl_grid_type* ecl_grid2 = nullptr;
std::vector<std::string> keywords1, keywords2;
bool throwOnError = true; //!< Throw on first error
bool analysis = false; //!< Perform full error analysis
std::map<std::string, std::vector<Deviation>> deviations;
mutable size_t num_errors = 0;
//! \brief Checks if the keyword exists in both cases.
@ -99,6 +102,9 @@ class ECLFilesComparator {
//! \brief Set whether to throw on errors or not.
void throwOnErrors(bool dothrow) { throwOnError = dothrow; }
//! \brief Set whether to perform a full error analysis.
void doAnalysis(bool analize) { analysis = analize; }
//! \brief Returns the number of errors encountered in the performed comparisons.
size_t getNoErrors() const { return num_errors; }

View File

@ -22,6 +22,7 @@
#include <iostream>
#include <iomanip>
#include <map>
#include <vector>
#include <algorithm>
#include <string>
@ -48,8 +49,8 @@ typedef struct ecl_sum_struct ecl_sum_type;
//! \brief Struct for storing the deviation between two values.
struct Deviation {
double abs = 0;//!< The absolute deviation
double rel = 0; //!< The relative deviation
double abs = 0; //!< The absolute deviation
double rel = 0; //!< The relative deviation
};
@ -73,6 +74,8 @@ class SummaryComparator {
bool printKeyword = false; //!< Boolean value for choosing whether to print the keywords or not
bool printSpecificKeyword = false; //!< Boolean value for choosing whether to print the vectors of a keyword or not
bool throwOnError = true; //!< Throw on first error
bool analysis = false; //!< Perform error analysis
std::map<std::string, std::vector<Deviation>> deviations;
//! \brief Calculate deviation between two data values and stores it in a Deviation struct.
//! \param[in] refIndex Index in reference data
@ -175,6 +178,9 @@ class SummaryComparator {
//! \brief Set whether to throw on errors or not.
void throwOnErrors(bool dothrow) { throwOnError = dothrow; }
//! \brief Set whether or not to perform error analysis.
void doAnalysis(bool analyse) { analysis = analyse; }
};
#endif

View File

@ -391,10 +391,14 @@ void RegressionTest::deviationsForCell(double val1, double val2, const std::stri
}
Deviation dev = calculateDeviations(val1, val2);
if (dev.abs > absTolerance && dev.rel > relTolerance) {
printValuesForCell(keyword, occurrence1, occurrence2, kw_size, cell, val1, val2);
HANDLE_ERROR(std::runtime_error, "Deviations exceed tolerances."
<< "\nThe absolute deviation is " << dev.abs << ", and the tolerance limit is " << absTolerance << "."
<< "\nThe relative deviation is " << dev.rel << ", and the tolerance limit is " << relTolerance << ".");
if (analysis) {
deviations[keyword].push_back(dev);
} else {
printValuesForCell(keyword, occurrence1, occurrence2, kw_size, cell, val1, val2);
HANDLE_ERROR(std::runtime_error, "Deviations exceed tolerances."
<< "\nThe absolute deviation is " << dev.abs << ", and the tolerance limit is " << absTolerance << "."
<< "\nThe relative deviation is " << dev.rel << ", and the tolerance limit is " << relTolerance << ".");
}
}
if (dev.abs != -1) {
absDeviation.push_back(dev.abs);
@ -496,6 +500,30 @@ void RegressionTest::results() {
}
for (const auto& it : keywords1)
resultsForKeyword(it);
if (analysis) {
std::cout << deviations.size() << " keyword"
<< (deviations.size() > 1 ? "s":"") << " exhibit failures" << std::endl;
for (const auto& iter : deviations) {
std::cout << "\t" << iter.first << std::endl;
std::cout << "\t\tFails for " << iter.second.size() << " entries" << std::endl;
std::cout.precision(7);
double absErr = std::max_element(iter.second.begin(), iter.second.end(),
[](const Deviation& a, const Deviation& b)
{
return a.abs < b.abs;
})->abs;
double relErr = std::max_element(iter.second.begin(), iter.second.end(),
[](const Deviation& a, const Deviation& b)
{
return a.rel < b.rel;
})->rel;
std::cout << "\t\tLargest absolute error: "
<< std::scientific << absErr << std::endl;
std::cout << "\t\tLargest relative error: "
<< std::scientific << relErr << std::endl;
}
}
}

View File

@ -72,6 +72,30 @@ void RegressionTest::getRegressionTest(){
}
ivar++;
}
if (analysis) {
std::cout << deviations.size() << " summary keyword"
<< (deviations.size() > 1 ? "s":"") << " exhibit failures" << std::endl;
size_t len = ecl_sum_get_data_length(ecl_sum1);
for (const auto& iter : deviations) {
std::cout << "\t" << iter.first << std::endl;
std::cout << "\t\tFails for " << iter.second.size() << " / " << len << " steps." << std::endl;
std::cout.precision(7);
double absErr = std::max_element(iter.second.begin(), iter.second.end(),
[](const Deviation& a, const Deviation& b)
{
return a.abs < b.abs;
})->abs;
double relErr = std::max_element(iter.second.begin(), iter.second.end(),
[](const Deviation& a, const Deviation& b)
{
return a.rel < b.rel;
})->rel;
std::cout << "\t\tLargest absolute error: "
<< std::scientific << absErr << std::endl;
std::cout << "\t\tLargest relative error: "
<< std::scientific << relErr << std::endl;
}
}
if (throwAtEnd)
OPM_THROW(std::runtime_error, "Regression test failed.");
else
@ -107,13 +131,17 @@ bool RegressionTest::checkDeviation(Deviation deviation, const char* keyword, in
double relTol = getRelTolerance();
if (deviation.rel > relTol && deviation.abs > absTol){
std::cout << "For keyword " << keyword << std::endl;
std::cout << "(days, reference value) and (days, check value) = (" << (*referenceVec)[refIndex] << ", " << (*referenceDataVec)[refIndex]
<< ") and (" << (*checkVec)[checkIndex-1] << ", " << (*checkDataVec)[checkIndex-1] << ")\n";
// -1 in [checkIndex -1] because checkIndex is updated after leaving getDeviation function
std::cout << "The absolute deviation is " << deviation.abs << ". The tolerance limit is " << absTol << std::endl;
std::cout << "The relative deviation is " << deviation.rel << ". The tolerance limit is " << relTol << std::endl;
HANDLE_ERROR(std::runtime_error, "Deviation exceed the limit.");
if (analysis) {
deviations[keyword].push_back(deviation);
} else {
std::cout << "For keyword " << keyword << std::endl;
std::cout << "(days, reference value) and (days, check value) = (" << (*referenceVec)[refIndex] << ", " << (*referenceDataVec)[refIndex]
<< ") and (" << (*checkVec)[checkIndex-1] << ", " << (*checkDataVec)[checkIndex-1] << ")\n";
// -1 in [checkIndex -1] because checkIndex is updated after leaving getDeviation function
std::cout << "The absolute deviation is " << deviation.abs << ". The tolerance limit is " << absTol << std::endl;
std::cout << "The relative deviation is " << deviation.rel << ". The tolerance limit is " << relTol << std::endl;
HANDLE_ERROR(std::runtime_error, "Deviation exceed the limit.");
}
return false;
}
return true;