opm-common/test_util/compareECL.cpp
2022-11-01 23:32:24 +01:00

267 lines
10 KiB
C++

/*
Copyright 2019 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include "EclRegressionTest.hpp"
#include <opm/common/ErrorMacros.hpp>
#include <iostream>
#include <string>
#include <getopt.h>
#include <fstream>
static void printHelp() {
std::cout << "\ncompareECL compares ECLIPSE files (restart (.RST), unified restart (.UNRST), initial (.INIT), summary (.SMRY), unified summary (.UNSMRY) or .RFT) and gridsizes (from .EGRID or .GRID file) from two simulations.\n"
<< "The program takes four arguments:\n\n"
<< "1. Case number 1, reference case (full path without extension)\n"
<< "2. Case number 2, test case (full path without extension)\n"
<< "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"
<< "-d Use report steps only when comparing results from summary files.\n"
<< "-i Execute integration test (regression test is default).\n"
<< " The integration test compares SGAS, SWAT and PRESSURE in unified restart files, and WOPR, WGPR, WWPR and WBHP (all wells) in summary file. \n"
<< "-k Specify specific keyword to compare (capitalized), for examples -k PRESSURE or -k WOPR:A-1H \n"
<< "-l Only do comparison for the last Report Step. This option is only valid for restart files.\n"
<< "-n Do not throw on errors.\n"
<< "-p Print keywords in both cases and exit.\n"
<< "-r compare a specific report time step number in a restart file.\n"
<< "-t Specify ECLIPSE filetype to compare, (default behaviour is that all files are compared if found). Different possible arguments are:\n"
<< " -t UNRST \t Compare two unified restart files (.UNRST). This the default value, so it is the same as not passing option -t.\n"
<< " -t EGRID \t Compare two EGrid files (.EGRID).\n"
<< " -t INIT \t Compare two initial files (.INIT).\n"
<< " -t RFT \t Compare two RFT files (.RFT).\n"
<< " -t SMRY \t Compare two cases consistent of (unified) summary files.\n"
<< " -t RSM \t Compare RSM file against a summary file.\n"
<< "-x Allow extra keywords in case number 2. These additional keywords (not found in case number1) will be ignored in the comparison.\n"
<< "\nExample usage of the program: \n\n"
<< "compareECL -k PRESSURE <path to first casefile> <path to second casefile> 1e-3 1e-5\n"
<< "compareECL -t INIT -k PORO <path to first casefile> <path to second casefile> 1e-3 1e-5\n"
<< "compareECL -i <path to first casefile> <path to second casefile> 0.01 1e-6\n\n"
<< "Exceptions are thrown (and hence program exits) when deviations are larger than the specified "
<< "tolerances, or when the number of cells does not match -- either in the grid file or for a "
<< "specific keyword. Information about the keyword, keyword occurrence (zero based) and cell "
<< "coordinate is printed when an exception is thrown. For more information about how the cases "
<< "are compared, see the documentation of the EclFilesComparator class.\n\n";
}
static bool has_result_files(const std::string& rootName)
{
std::vector<std::string> extList = { "EGRID", "INIT", "UNRST", "SMSPEC", "RFT" };
for (const auto& ext : extList) {
std::ifstream is(rootName + '.' + ext);
if (is) {
return true;
}
}
return false;
}
//------------------------------------------------//
int main(int argc, char** argv) {
bool integrationTest = false;
bool onlyLastSequence = false;
bool reportStepOnly = false;
bool printKeywords = false;
bool specificKeyword = false;
bool specificReportStepNumber = false;
bool specificFileType = false;
bool throwOnError = true;
bool restartFile = false;
bool acceptExtraKeywords = false;
bool analysis = false;
char* keyword = nullptr;
int c = 0;
int reportStepNumber = -1;
std::string fileTypeString;
while ((c = getopt(argc, argv, "hik:alnpt:Rr:xd")) != -1) {
switch (c) {
case 'a':
analysis = true;
throwOnError = false;
break;
case 'h':
printHelp();
return 0;
case 'd':
reportStepOnly = true;
break;
case 'i':
integrationTest = true;
break;
case 'k':
specificKeyword = true;
keyword = optarg;
break;
case 'l':
onlyLastSequence = true;
break;
case 'n':
throwOnError = false;
break;
case 'p':
printKeywords = true;
break;
case 'r':
specificReportStepNumber=true;
reportStepNumber = atoi(optarg);
break;
case 'R':
restartFile = true;
break;
case 't':
specificFileType = true;
fileTypeString=optarg;
break;
case 'x':
acceptExtraKeywords = true;
break;
case '?':
if (optopt == 'k' || optopt == 'm' || optopt == 's') {
std::cerr << "Option " << optopt << " requires a keyword as argument, see manual (-h) for more information." << std::endl;
return EXIT_FAILURE;
}
else if (optopt == 't') {
std::cerr << "Option t requires an ECLIPSE filetype as argument, see manual (-h) for more information." << std::endl;
return EXIT_FAILURE;
}
else {
std::cerr << "Unknown option." << std::endl;
return EXIT_FAILURE;
}
default:
return EXIT_FAILURE;
}
}
int argOffset = optind;
if (argc != argOffset + 4) {
std::cerr << "Error: The number of options and arguments given is not correct. "
<< "Please run compareECL -h to see manual." << std::endl;
return EXIT_FAILURE;
}
std::string basename1 = argv[argOffset];
std::string basename2 = argv[argOffset + 1];
double absTolerance = strtod(argv[argOffset + 2], nullptr);
double relTolerance = strtod(argv[argOffset + 3], nullptr);
std::cout << "Comparing '" << basename1 << "' to '" << basename2 << "'." << std::endl;
if (!has_result_files(basename1)){
std::cerr << "No files found for reference case." << std::endl;
return EXIT_FAILURE;
}
try {
ECLRegressionTest comparator(basename1, basename2, absTolerance, relTolerance);
comparator.throwOnErrors(throwOnError);
comparator.doAnalysis(analysis);
comparator.setAcceptExtraKeywords(acceptExtraKeywords);
if (integrationTest) {
comparator.setIntegrationTest(true);
}
if (printKeywords) {
comparator.setPrintKeywordOnly(printKeywords);
}
if (onlyLastSequence) {
comparator.setOnlyLastReportNumber(true);
}
if (reportStepOnly) {
comparator.setReportStepOnly(true);
}
if (specificKeyword) {
comparator.compareSpesificKeyword(keyword);
}
if (specificReportStepNumber) {
comparator.compareSpesificRstReportStepNumber(reportStepNumber);
}
if (restartFile) {
comparator.setLoadBaseRunData(true);
}
comparator.loadGrids();
if (integrationTest && specificFileType) {
if (fileTypeString=="EGRID" || fileTypeString=="INIT" || fileTypeString=="RFT") {
std::cerr << "Integration test and specific file type, only valid for UNRST and SMRY" << std::endl;
return EXIT_FAILURE;
}
}
if (specificFileType) {
if (fileTypeString == "EGRID") {
comparator.gridCompare();
} else if (fileTypeString == "INIT") {
comparator.results_init();
} else if (fileTypeString == "UNRST") {
comparator.results_rst();
} else if (fileTypeString == "SMRY") {
comparator.results_smry();
} else if (fileTypeString == "RSM") {
comparator.results_rsm();
} else if (fileTypeString == "RFT") {
comparator.results_rft();
} else {
std::cerr << "Unknown ECLIPSE filetype specified with option -t. Please run compareECL -h to see manual." << std::endl;
return EXIT_FAILURE;
}
} else if (integrationTest) {
comparator.results_rst();
comparator.results_smry();
} else {
comparator.gridCompare();
comparator.results_init();
comparator.results_rst();
comparator.results_smry();
comparator.results_rsm();
comparator.results_rft();
}
if (comparator.getNoErrors() > 0)
OPM_THROW(std::runtime_error, comparator.getNoErrors() << " errors encountered in comparisons.");
}
catch (const std::exception& e) {
std::cerr << "Program threw an exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
std::cout << "\nProgram finished \n" << std::endl;
return 0;
}